From: aml Date: Thu, 17 Sep 2015 14:09:20 +0000 (+0300) Subject: 0026196: Wrong result obtained by projection algorithm. X-Git-Tag: V7_0_0_beta~254 X-Git-Url: http://git.dev.opencascade.org/gitweb/?p=occt.git;a=commitdiff_plain;h=7afe616f1f65dd4805171993b916c8402d4c52aa;hp=f41525d378b18496bc25b4733857072511130c18;ds=sidebyside 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 --- diff --git a/src/GeomAdaptor/GeomAdaptor.cxx b/src/GeomAdaptor/GeomAdaptor.cxx index 4378e5d609..78805029ba 100644 --- a/src/GeomAdaptor/GeomAdaptor.cxx +++ b/src/GeomAdaptor/GeomAdaptor.cxx @@ -101,8 +101,8 @@ Handle(Geom_Curve) GeomAdaptor::MakeCurve (const Adaptor3d_Curve& HC) //function : MakeSurface //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; @@ -148,7 +148,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS) case GeomAbs_OffsetSurface: S = new Geom_OffsetSurface(GeomAdaptor::MakeSurface(HS.BasisSurface()->Surface()), - HS.OffsetValue()); + HS.OffsetValue()); break; case GeomAbs_OtherSurface: @@ -156,7 +156,7 @@ Handle(Geom_Surface) GeomAdaptor::MakeSurface(const Adaptor3d_Surface& HS) break; } - if ( S.IsNull() ) + if ( S.IsNull() || !theTrimFlag) return S; // trim the surface if necassary. diff --git a/src/GeomAdaptor/GeomAdaptor.hxx b/src/GeomAdaptor/GeomAdaptor.hxx index b27a5c20e7..d1797b5683 100644 --- a/src/GeomAdaptor/GeomAdaptor.hxx +++ b/src/GeomAdaptor/GeomAdaptor.hxx @@ -48,9 +48,11 @@ public: //! Curve from Adaptor3d Standard_EXPORT static Handle(Geom_Curve) MakeCurve (const Adaptor3d_Curve& C); - //! Build a Geom_Surface using the informations from the - //! Surface from Adaptor3d - Standard_EXPORT static Handle(Geom_Surface) MakeSurface (const Adaptor3d_Surface& S); + //! Build a Geom_Surface using the informations from the Surface from Adaptor3d + //! @param theS - Surface adaptor to convert. + //! @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); diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index fa90489927..07d2aef316 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -93,6 +93,65 @@ struct aFuncStruct 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 //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() 3D // use for calculate start 2D point. //======================================================================= - static gp_Pnt2d Function_Value(const Standard_Real theU, const aFuncStruct& theData) { @@ -236,10 +294,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, Standard_Real uperiod = theData.myPeriod[0], vperiod = theData.myPeriod[1], u, v; - // U0 and V0 are the points within the initialized period - // (periode with u and v), - // U1 and V1 are the points for construction of tops - + + // U0 and V0 are the points within the initialized period. if(U0 < Uinf) { if(!uperiod) @@ -280,8 +336,8 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, 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 uInfLi = 0, vInfLi = 0,uSupLi = 0, vSupLi = 0; if((U0 - Uinf) > uLittle) uInfLi = U0 - uLittle; else uInfLi = Uinf; @@ -372,18 +428,7 @@ class ProjLib_PolarFunction : public AppCont_Function myNbPnt = 0; myNbPnt2d = 1; - myStruct.myPeriod[0] = 0.0; - 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(); - } + computePeriodicity(Surf, myStruct.myPeriod[0], myStruct.myPeriod[1]); myStruct.myCurve = C; 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(); Handle(Geom2d_BSplineCurve) CurBS; 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. 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 = (S->LastUParameter() - S->FirstUParameter() ) * aMultCoeff; - } + Standard_Real aMultCoeff = aC2Beg.X() < aC1End.X() ? 1.0 : -1.0; + anUJump = (anUPeriod) * 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 = (S->LastVParameter() - S->FirstVParameter() ) * aMultCoeff; - } + Standard_Real aMultCoeff = aC2Beg.Y() < aC1End.Y() ? 1.0 : -1.0; + anVJump = (anVPeriod) * aMultCoeff; } 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 DistTol3d = 100.0*Tol3d; - Standard_Real uperiod = 0., vperiod = 0.; - if(Surf->IsUPeriodic() || Surf->IsUClosed()) - uperiod = Surf->LastUParameter() - Surf->FirstUParameter(); - - if(Surf->IsVPeriodic() || Surf->IsVClosed()) - vperiod = Surf->LastVParameter() - Surf->FirstVParameter(); + Standard_Real uperiod = 0.0, vperiod = 0.0; + computePeriodicity(Surf, uperiod, vperiod); - // NO myTol is Tol2d !!!! //Standard_Real TolU = myTolerance, TolV = myTolerance; //Standard_Real Tol3d = 100*myTolerance; // At random Balthazar. diff --git a/tests/bugs/modalg_6/bug26196 b/tests/bugs/modalg_6/bug26196 new file mode 100644 index 0000000000..b5f433b9f8 --- /dev/null +++ b/tests/bugs/modalg_6/bug26196 @@ -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." +}