1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-10 18:51:21 +03:00

0026196: Wrong result obtained by projection algorithm.

Improved periodicity handling when trimmed parameters became unclosed or nonperiodic, but underlying geometry closed or periodic.
Added possibility to not perform trim in GeomAdaptor::MakeSurface.

Minor corrections.

Test-case for issue #26196

Correction of comments
This commit is contained in:
aml 2015-09-17 17:09:20 +03:00 committed by bugmaster
parent f41525d378
commit 7afe616f1f
4 changed files with 128 additions and 45 deletions

View File

@ -101,8 +101,8 @@ Handle(Geom_Curve) GeomAdaptor::MakeCurve (const Adaptor3d_Curve& HC)
//function : MakeSurface //function : MakeSurface
//purpose : //purpose :
//======================================================================= //=======================================================================
Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS,
Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS) const Standard_Boolean theTrimFlag)
{ {
Handle(Geom_Surface) S; Handle(Geom_Surface) S;
@ -148,7 +148,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS)
case GeomAbs_OffsetSurface: case GeomAbs_OffsetSurface:
S = new Geom_OffsetSurface(GeomAdaptor::MakeSurface(HS.BasisSurface()->Surface()), S = new Geom_OffsetSurface(GeomAdaptor::MakeSurface(HS.BasisSurface()->Surface()),
HS.OffsetValue()); HS.OffsetValue());
break; break;
case GeomAbs_OtherSurface: case GeomAbs_OtherSurface:
@ -156,7 +156,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS)
break; break;
} }
if ( S.IsNull() ) if ( S.IsNull() || !theTrimFlag)
return S; return S;
// trim the surface if necassary. // trim the surface if necassary.

View File

@ -48,9 +48,11 @@ public:
//! Curve from Adaptor3d //! Curve from Adaptor3d
Standard_EXPORT static Handle(Geom_Curve) MakeCurve (const Adaptor3d_Curve& C); Standard_EXPORT static Handle(Geom_Curve) MakeCurve (const Adaptor3d_Curve& C);
//! Build a Geom_Surface using the informations from the //! Build a Geom_Surface using the informations from the Surface from Adaptor3d
//! Surface from Adaptor3d //! @param theS - Surface adaptor to convert.
Standard_EXPORT static Handle(Geom_Surface) MakeSurface (const Adaptor3d_Surface& S); //! @param theTrimFlag - True if perform trim surface values by adaptor and false otherwise.
Standard_EXPORT static Handle(Geom_Surface) MakeSurface (const Adaptor3d_Surface& theS,
const Standard_Boolean theTrimFlag = Standard_True);

View File

@ -93,6 +93,65 @@ struct aFuncStruct
Standard_Real myPeriod[2]; // U and V period correspondingly. Standard_Real myPeriod[2]; // U and V period correspondingly.
}; };
//=======================================================================
//function : computePeriodicity
//purpose : Compute period information on adaptor.
//=======================================================================
static void computePeriodicity(const Handle(Adaptor3d_HSurface)& theSurf,
Standard_Real &theUPeriod,
Standard_Real &theVPeriod)
{
theUPeriod = 0.0;
theVPeriod = 0.0;
// Compute once information about periodicity.
// Param space may be reduced in case of rectangular trimmed surface,
// in this case really trimmed bounds should be set as unperiodic.
Standard_Real aTrimF, aTrimL, aBaseF, aBaseL, aDummyF, aDummyL;
Handle(Geom_Surface) aS = GeomAdaptor::MakeSurface(theSurf->Surface(), Standard_False); // Not trim.
// U param space.
if (theSurf->IsUPeriodic())
{
theUPeriod = theSurf->UPeriod();
}
else if(theSurf->IsUClosed())
{
theUPeriod = theSurf->LastUParameter() - theSurf->FirstUParameter();
}
if (theUPeriod != 0.0)
{
aTrimF = theSurf->FirstUParameter(); // Trimmed first
aTrimL = theSurf->LastUParameter(); // Trimmed last
aS->Bounds(aBaseF, aBaseL, aDummyF, aDummyL); // Non-trimmed values.
if (Abs (aBaseF - aTrimF) + Abs (aBaseL - aTrimL) > Precision::PConfusion())
{
// Param space reduced.
theUPeriod = 0.0;
}
}
// V param space.
if (theSurf->IsVPeriodic())
{
theVPeriod = theSurf->VPeriod();
}
else if(theSurf->IsVClosed())
{
theVPeriod = theSurf->LastVParameter() - theSurf->FirstVParameter();
}
if (theVPeriod != 0.0)
{
aTrimF = theSurf->FirstVParameter(); // Trimmed first
aTrimL = theSurf->LastVParameter(); // Trimmed last
aS->Bounds(aDummyF, aDummyL, aBaseF, aBaseL); // Non-trimmed values.
if (Abs (aBaseF - aTrimF) + Abs (aBaseL - aTrimL) > Precision::PConfusion())
{
// Param space reduced.
theVPeriod = 0.0;
}
}
}
//======================================================================= //=======================================================================
//function : aFuncValue //function : aFuncValue
//purpose : compute functional value in (theU,theV) point //purpose : compute functional value in (theU,theV) point
@ -128,7 +187,6 @@ static Standard_Real anOrthogSqValue(const gp_Pnt& aBasePnt,
//purpose : (OCC217 - apo)- Compute Point2d that project on polar surface(<Surf>) 3D<Curve> //purpose : (OCC217 - apo)- Compute Point2d that project on polar surface(<Surf>) 3D<Curve>
// <InitCurve2d> use for calculate start 2D point. // <InitCurve2d> use for calculate start 2D point.
//======================================================================= //=======================================================================
static gp_Pnt2d Function_Value(const Standard_Real theU, static gp_Pnt2d Function_Value(const Standard_Real theU,
const aFuncStruct& theData) const aFuncStruct& theData)
{ {
@ -236,10 +294,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
Standard_Real uperiod = theData.myPeriod[0], Standard_Real uperiod = theData.myPeriod[0],
vperiod = theData.myPeriod[1], vperiod = theData.myPeriod[1],
u, v; u, v;
// U0 and V0 are the points within the initialized period
// (periode with u and v), // U0 and V0 are the points within the initialized period.
// U1 and V1 are the points for construction of tops
if(U0 < Uinf) if(U0 < Uinf)
{ {
if(!uperiod) if(!uperiod)
@ -280,8 +336,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU,
V0 += decalV*vperiod; V0 += decalV*vperiod;
} }
} }
// The surface around U0 is reduced. // The surface around (U0,V0) is reduced.
Standard_Real uLittle = (Usup - Uinf)/10, vLittle = (Vsup - Vinf)/10; Standard_Real uLittle = (Usup - Uinf)/10, vLittle = (Vsup - Vinf)/10;
Standard_Real uInfLi = 0, vInfLi = 0,uSupLi = 0, vSupLi = 0; Standard_Real uInfLi = 0, vInfLi = 0,uSupLi = 0, vSupLi = 0;
if((U0 - Uinf) > uLittle) uInfLi = U0 - uLittle; else uInfLi = Uinf; if((U0 - Uinf) > uLittle) uInfLi = U0 - uLittle; else uInfLi = Uinf;
@ -372,18 +428,7 @@ class ProjLib_PolarFunction : public AppCont_Function
myNbPnt = 0; myNbPnt = 0;
myNbPnt2d = 1; myNbPnt2d = 1;
myStruct.myPeriod[0] = 0.0; computePeriodicity(Surf, myStruct.myPeriod[0], myStruct.myPeriod[1]);
myStruct.myPeriod[1] = 0.0;
// Compute once information about periodicity.
if(Surf->IsUPeriodic() || Surf->IsUClosed())
{
myStruct.myPeriod[0] = Surf->LastUParameter() - Surf->FirstUParameter();
}
if(Surf->IsVPeriodic() || Surf->IsVClosed())
{
myStruct.myPeriod[1] = Surf->LastVParameter() - Surf->FirstVParameter();
}
myStruct.myCurve = C; myStruct.myCurve = C;
myStruct.myInitCurve2d = InitialCurve2d; myStruct.myInitCurve2d = InitialCurve2d;
@ -766,6 +811,8 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
} }
} }
Standard_Real anUPeriod, anVPeriod;
computePeriodicity(S, anUPeriod, anVPeriod);
Standard_Integer NbC = LOfBSpline2d.Extent(); Standard_Integer NbC = LOfBSpline2d.Extent();
Handle(Geom2d_BSplineCurve) CurBS; Handle(Geom2d_BSplineCurve) CurBS;
CurBS = Handle(Geom2d_BSplineCurve)::DownCast(LOfBSpline2d.First()); CurBS = Handle(Geom2d_BSplineCurve)::DownCast(LOfBSpline2d.First());
@ -780,22 +827,18 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform
gp_Pnt2d aC2Beg = BS->Pole(1); // Beginning of C2. gp_Pnt2d aC2Beg = BS->Pole(1); // Beginning of C2.
Standard_Real anUJump = 0.0, anVJump = 0.0; Standard_Real anUJump = 0.0, anVJump = 0.0;
if (S->IsUPeriodic() || S->IsUClosed()) if (anUPeriod > 0.0 &&
Abs (aC1End.X() - aC2Beg.X()) > (anUPeriod ) / 2.01)
{ {
if (Abs (aC1End.X() - aC2Beg.X()) > (S->LastUParameter() - S->FirstUParameter() ) / 2.01) Standard_Real aMultCoeff = aC2Beg.X() < aC1End.X() ? 1.0 : -1.0;
{ anUJump = (anUPeriod) * aMultCoeff;
Standard_Real aMultCoeff = aC2Beg.X() < aC1End.X() ? 1.0 : -1.0;
anUJump = (S->LastUParameter() - S->FirstUParameter() ) * aMultCoeff;
}
} }
if (S->IsVPeriodic() || S->IsVClosed()) if (anVPeriod &&
Abs (aC1End.Y() - aC2Beg.Y()) > (anVPeriod) / 2.01)
{ {
if (Abs (aC1End.Y() - aC2Beg.Y()) > (S->LastVParameter() - S->FirstVParameter() ) / 2.01) Standard_Real aMultCoeff = aC2Beg.Y() < aC1End.Y() ? 1.0 : -1.0;
{ anVJump = (anVPeriod) * aMultCoeff;
Standard_Real aMultCoeff = aC2Beg.Y() < aC1End.Y() ? 1.0 : -1.0;
anVJump = (S->LastVParameter() - S->FirstVParameter() ) * aMultCoeff;
}
} }
CurBS = Concat(CurBS,BS, anUJump, anVJump); CurBS = Concat(CurBS,BS, anUJump, anVJump);
@ -832,14 +875,9 @@ Handle(Adaptor2d_HCurve2d)
Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d); Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d);
Standard_Real DistTol3d = 100.0*Tol3d; Standard_Real DistTol3d = 100.0*Tol3d;
Standard_Real uperiod = 0., vperiod = 0.; Standard_Real uperiod = 0.0, vperiod = 0.0;
if(Surf->IsUPeriodic() || Surf->IsUClosed()) computePeriodicity(Surf, uperiod, vperiod);
uperiod = Surf->LastUParameter() - Surf->FirstUParameter();
if(Surf->IsVPeriodic() || Surf->IsVClosed())
vperiod = Surf->LastVParameter() - Surf->FirstVParameter();
// NO myTol is Tol2d !!!! // NO myTol is Tol2d !!!!
//Standard_Real TolU = myTolerance, TolV = myTolerance; //Standard_Real TolU = myTolerance, TolV = myTolerance;
//Standard_Real Tol3d = 100*myTolerance; // At random Balthazar. //Standard_Real Tol3d = 100*myTolerance; // At random Balthazar.

View File

@ -0,0 +1,43 @@
puts "========"
puts "OCC26196"
puts "========"
puts ""
#################################################
# Wrong result obtained by projection algorithm
#################################################
restore [locate_data_file OCC26196-Face.brep] f
explode f e
mkcurve c f_1
mksurface s f
trim st s 1.33305 4.31185 -1.56174 0.415831
project c2d c st
set bug_info [dump c2d]
set bug_info [string trim [string range $bug_info [expr {[string first "KnotsPoles :" $bug_info] + 12}] [string length $bug_info]]]
set bug_info [string trim [string range $bug_info 0 [expr {[string first "Knots :" $bug_info] - 1}]]]
set bug_info_length [llength $bug_info]
set beg_X [lindex $bug_info 2]
set beg_X [string range $beg_X 0 [expr {[string length $beg_X] - 2}]]
set beg_Y [lindex $bug_info 3]
set end_X [lindex $bug_info [expr {$bug_info_length - 2}]]
set end_X [string range $end_X 0 [expr {[string length $end_X] - 2}]]
set end_Y [lindex $bug_info [expr {$bug_info_length - 1}]]
if {$beg_X > $end_X} {
set diff_X [expr {$beg_X - $end_X}]
} else {
set diff_X [expr {$end_X - $beg_X}]
}
if {$beg_Y > $end_Y} {
set diff_Y [expr {$beg_Y - $end_Y}]
} else {
set diff_Y [expr {$end_Y - $beg_Y}]
}
if {$diff_X > 1.e-06 || $diff_Y > 1.e-06} {
puts "ERROR: OCC26196 is reproduced. Projection is wrong."
}