From: ifv Date: Tue, 11 Jul 2017 07:15:28 +0000 (+0300) Subject: 0030489: Modeling Algorithms - BRepBuilderAPI_GTransform hangs X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=99c3e8934286d0e71434c734c23cc325935012f9;p=occt-copy.git 0030489: Modeling Algorithms - BRepBuilderAPI_GTransform hangs Approx_ComputeCLine.gxx - criterium to stop interval cutting is increased. ProjLib_ProjectedCurve.cxx - fix regression for bugs modalg_5 bug25886 Other tests are modified according to current state of algorithm 0028909: Algorithm of BO is stuck while fusing shell and edges Approximation parameters: degmin, degmax, max number of segments, boundary condition, maximal distance of projecting are added in interface of classes ProjLib_ProjectedCurve, ProjLib_ComputeApprox, ProjLib_ComputeApproxOnPolarSurface Algorithm of Approx/Approx_ComputeCLine is modified in order to treat maximal number of segments allowed for cutting. Algorithm of method BOPTools_AlgoTools2D::MakePCurveOnFace(...) is modified in order to manage cases with big edge tolerances. Test case added Some test cases were modified according to new behavior of algorithms --- diff --git a/src/Approx/Approx_ComputeCLine.gxx b/src/Approx/Approx_ComputeCLine.gxx index f2fc63c460..d13c01e6e3 100644 --- a/src/Approx/Approx_ComputeCLine.gxx +++ b/src/Approx/Approx_ComputeCLine.gxx @@ -34,14 +34,14 @@ //======================================================================= Approx_ComputeCLine::Approx_ComputeCLine - (const MultiLine& Line, - const Standard_Integer degreemin, - const Standard_Integer degreemax, - const Standard_Real Tolerance3d, - const Standard_Real Tolerance2d, - const Standard_Boolean cutting, - const AppParCurves_Constraint FirstC, - const AppParCurves_Constraint LastC) +(const MultiLine& Line, +const Standard_Integer degreemin, +const Standard_Integer degreemax, +const Standard_Real Tolerance3d, +const Standard_Real Tolerance2d, +const Standard_Boolean cutting, +const AppParCurves_Constraint FirstC, +const AppParCurves_Constraint LastC) { mydegremin = degreemin; mydegremax = degreemax; @@ -50,6 +50,7 @@ Approx_ComputeCLine::Approx_ComputeCLine mycut = cutting; myfirstC = FirstC; mylastC = LastC; + myMaxSegments = IntegerLast(); alldone = Standard_False; Perform(Line); } @@ -60,13 +61,13 @@ Approx_ComputeCLine::Approx_ComputeCLine //======================================================================= Approx_ComputeCLine::Approx_ComputeCLine - (const Standard_Integer degreemin, - const Standard_Integer degreemax, - const Standard_Real Tolerance3d, - const Standard_Real Tolerance2d, - const Standard_Boolean cutting, - const AppParCurves_Constraint FirstC, - const AppParCurves_Constraint LastC) +(const Standard_Integer degreemin, +const Standard_Integer degreemax, +const Standard_Real Tolerance3d, +const Standard_Real Tolerance2d, +const Standard_Boolean cutting, +const AppParCurves_Constraint FirstC, +const AppParCurves_Constraint LastC) { alldone = Standard_False; mydegremin = degreemin; @@ -76,6 +77,7 @@ Approx_ComputeCLine::Approx_ComputeCLine mycut = cutting; myfirstC = FirstC; mylastC = LastC; + myMaxSegments = IntegerLast(); } //======================================================================= @@ -86,19 +88,22 @@ Approx_ComputeCLine::Approx_ComputeCLine void Approx_ComputeCLine::Perform(const MultiLine& Line) { Standard_Real UFirst, ULast; - Standard_Boolean Finish = Standard_False, - begin = Standard_True, Ok = Standard_False; + Standard_Boolean Finish = Standard_False, + begin = Standard_True, Ok = Standard_False; Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion(); UFirst = Line.FirstParameter(); - ULast = Line.LastParameter(); - Standard_Real TolU = (ULast-UFirst)*1.e-05; - Standard_Real myfirstU = UFirst; + ULast = Line.LastParameter(); + Standard_Real TolU = Max((ULast - UFirst)*1.e-03, Precision::Confusion()); + Standard_Real myfirstU = UFirst; Standard_Real mylastU = ULast; + Standard_Integer aMaxSegments = 0; + Standard_Integer aMaxSegments1 = myMaxSegments - 1; + Standard_Integer aNbCut = 0, aNbImp = 0, aNbComp = 5; if (!mycut) { alldone = Compute(Line, UFirst, ULast, thetol3d, thetol2d); - if (!alldone) + if (!alldone) { tolreached = Standard_False; myfirstparam.Append(UFirst); @@ -108,25 +113,28 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) Tolers2d.Append(currenttol2d); } } - else + else { // previous decision to be taken if we get worse with next cut (eap) AppParCurves_MultiCurve KeptMultiCurve; Standard_Real KeptUfirst = 0., KeptUlast = 0., KeptT3d = RealLast(), KeptT2d = 0.; - while (!Finish) + while (!Finish) { - + // Gestion du decoupage de la multiline pour approximer: - if (!begin) + if (!begin) { - if (Ok) + if (Ok) { // Calcul de la partie a approximer. myfirstU = mylastU; - mylastU = ULast; - if (Abs(ULast-myfirstU) <= RealEpsilon()) + mylastU = ULast; + aNbCut = 0; + aNbImp = 0; + if (Abs(ULast - myfirstU) <= RealEpsilon() + || aMaxSegments >= myMaxSegments) { Finish = Standard_True; alldone = Standard_True; @@ -142,45 +150,59 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d)) { KeptMultiCurve = TheMultiCurve; - KeptUfirst = myfirstU; - KeptUlast = mylastU; - KeptT3d = thetol3d; - KeptT2d = thetol2d; + KeptUfirst = myfirstU; + KeptUlast = mylastU; + KeptT3d = thetol3d; + KeptT2d = thetol2d; + aNbImp++; } // cut an interval - mylastU = (myfirstU + mylastU)/2; + mylastU = (myfirstU + mylastU) / 2; + aNbCut++; } } // Calcul des parametres sur ce nouvel intervalle. Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d); + if (Ok) + { + aMaxSegments++; + } //cout << myfirstU << " - " << mylastU << " tol : " << thetol3d << " " << thetol2d << endl; - + Standard_Boolean aStopCutting = Standard_False; + if (aNbCut >= aNbComp) + { + if (aNbCut > aNbImp) + { + aStopCutting = Standard_True; + } + } // is new decision better? - if (!Ok && Abs(myfirstU-mylastU) <= TolU) + if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting )) { - Ok = Standard_True; // stop interval cutting, approx the rest part + Ok = Standard_True; // stop interval cutting, approx the rest part - if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d)) - { - KeptMultiCurve = TheMultiCurve; - KeptUfirst = myfirstU; - KeptUlast = mylastU; - KeptT3d = thetol3d; - KeptT2d = thetol2d; - } + if ((thetol3d + thetol2d) < (KeptT3d + KeptT2d)) + { + KeptMultiCurve = TheMultiCurve; + KeptUfirst = myfirstU; + KeptUlast = mylastU; + KeptT3d = thetol3d; + KeptT2d = thetol2d; + } - mylastU = KeptUlast; + mylastU = KeptUlast; - tolreached = Standard_False; // helas - myMultiCurves.Append(KeptMultiCurve); - Tolers3d.Append (KeptT3d); - Tolers2d.Append (KeptT2d); - myfirstparam.Append (KeptUfirst); - mylastparam.Append (KeptUlast); - } + tolreached = Standard_False; // helas + myMultiCurves.Append(KeptMultiCurve); + aMaxSegments++; + Tolers3d.Append(KeptT3d); + Tolers2d.Append(KeptT2d); + myfirstparam.Append(KeptUfirst); + mylastparam.Append(KeptUlast); + } begin = Standard_False; } // while (!Finish) @@ -215,10 +237,10 @@ const //======================================================================= Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line, - const Standard_Real Ufirst, - const Standard_Real Ulast, - Standard_Real& TheTol3d, - Standard_Real& TheTol2d) + const Standard_Real Ufirst, + const Standard_Real Ulast, + Standard_Real& TheTol3d, + Standard_Real& TheTol2d) { @@ -233,14 +255,14 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line, if (mydone) { LSquare.Error(Fv, TheTol3d, TheTol2d); if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) { - // Stockage de la multicurve approximee. - tolreached = Standard_True; + // Stockage de la multicurve approximee. + tolreached = Standard_True; myMultiCurves.Append(LSquare.Value()); - myfirstparam.Append(Ufirst); - mylastparam.Append(Ulast); - Tolers3d.Append(TheTol3d); - Tolers2d.Append(TheTol2d); - return Standard_True; + myfirstparam.Append(Ufirst); + mylastparam.Append(Ulast); + Tolers3d.Append(TheTol3d); + Tolers2d.Append(TheTol2d); + return Standard_True; } } if (deg == mydegremax) { @@ -248,7 +270,7 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line, currenttol3d = TheTol3d; currenttol2d = TheTol2d; } - + } return Standard_False; } @@ -260,11 +282,11 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line, //======================================================================= void Approx_ComputeCLine::Parameters(const Standard_Integer Index, - Standard_Real& firstpar, - Standard_Real& lastpar) const + Standard_Real& firstpar, + Standard_Real& lastpar) const { firstpar = myfirstparam.Value(Index); - lastpar = mylastparam.Value(Index); + lastpar = mylastparam.Value(Index); } //======================================================================= @@ -273,7 +295,7 @@ void Approx_ComputeCLine::Parameters(const Standard_Integer Index, //======================================================================= void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin, - const Standard_Integer degreemax) + const Standard_Integer degreemax) { mydegremin = degreemin; mydegremax = degreemax; @@ -285,7 +307,7 @@ void Approx_ComputeCLine::SetDegrees(const Standard_Integer degreemin, //======================================================================= void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d, - const Standard_Real Tolerance2d) + const Standard_Real Tolerance2d) { mytol3d = Tolerance3d; mytol2d = Tolerance2d; @@ -297,10 +319,20 @@ void Approx_ComputeCLine::SetTolerances(const Standard_Real Tolerance3d, //======================================================================= void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC, - const AppParCurves_Constraint LastC) + const AppParCurves_Constraint LastC) { myfirstC = FirstC; - mylastC = LastC; + mylastC = LastC; +} + +//======================================================================= +//function : SetMaxSegments +//purpose : Changes the max number of segments, which is allowed for cutting. +//======================================================================= + +void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments) +{ + myMaxSegments = theMaxSegments; } //======================================================================= @@ -331,8 +363,8 @@ const { //======================================================================= void Approx_ComputeCLine::Error(const Standard_Integer Index, - Standard_Real& tol3d, - Standard_Real& tol2d) const + Standard_Real& tol3d, + Standard_Real& tol2d) const { tol3d = Tolers3d.Value(Index); tol2d = Tolers2d.Value(Index); diff --git a/src/Approx/Approx_FitAndDivide.hxx b/src/Approx/Approx_FitAndDivide.hxx index 81a55658b7..f33f83e243 100644 --- a/src/Approx/Approx_FitAndDivide.hxx +++ b/src/Approx/Approx_FitAndDivide.hxx @@ -60,6 +60,9 @@ public: //! Changes the constraints of the approximation. Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC); + + //! Changes the max number of segments, which is allowed for cutting. + Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user @@ -114,6 +117,7 @@ private: Standard_Boolean mycut; AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; + Standard_Integer myMaxSegments; }; diff --git a/src/Approx/Approx_FitAndDivide2d.hxx b/src/Approx/Approx_FitAndDivide2d.hxx index 646f45aba3..829bd82fcb 100644 --- a/src/Approx/Approx_FitAndDivide2d.hxx +++ b/src/Approx/Approx_FitAndDivide2d.hxx @@ -60,6 +60,9 @@ public: //! Changes the constraints of the approximation. Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC); + + //! Changes the max number of segments, which is allowed for cutting. + Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user @@ -114,6 +117,7 @@ private: Standard_Boolean mycut; AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; + Standard_Integer myMaxSegments; }; diff --git a/src/BOPTools/BOPTools_AlgoTools2D.cxx b/src/BOPTools/BOPTools_AlgoTools2D.cxx index 9697b92f56..20efb35b5c 100644 --- a/src/BOPTools/BOPTools_AlgoTools2D.cxx +++ b/src/BOPTools/BOPTools_AlgoTools2D.cxx @@ -629,11 +629,13 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace Handle(GeomAdaptor_HCurve) aBAHC = new GeomAdaptor_HCurve(aC3D, aT1, aT2); // Standard_Real aTolR; + Standard_Real aTR = Precision::Confusion();//1.e-7; + Standard_Real aMaxTol = 1.e3 * aTR; //0.0001 + Standard_Boolean isAnaSurf = ProjLib::IsAnaSurf(aBAHS); + //when the type of surface is GeomAbs_SurfaceOfRevolution - if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution) { - Standard_Real aTR; - // - aTR=Precision::Confusion();//1.e-7; + if (pBAS->GetType() == GeomAbs_SurfaceOfRevolution) + { if (TolReached2d > aTR) { aTR=TolReached2d; } @@ -642,23 +644,44 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace ProjLib::MakePCurveOfType(aProj1, aC2D); aTolR = aProj1.GetTolerance(); } - else { - ProjLib_ProjectedCurve aProjCurv(aBAHS, aBAHC);// 1 + else + { + ProjLib_ProjectedCurve aProjCurv(aBAHS); + Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1; + Standard_Real aMaxDist = -1; + AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint; + if ((TolReached2d >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf)) + { + aTR = Min(aMaxTol, 0.1*TolReached2d); + aMaxSegments = 100; + aMaxDist = 1.e3*TolReached2d; + if(!isAnaSurf) + { + aBndPnt = AppParCurves_PassPoint; + } + } + else if(TolReached2d > aMaxTol) + { + aTR = Min(TolReached2d, 1.e3 * aMaxTol); + aMaxDist = 1.e2 * aTR; + aMaxSegments = 100; + } + aProjCurv.Load(aTR); + aProjCurv.SetDegree(aDegMin, aDegMax); + aProjCurv.SetMaxSegments(aMaxSegments); + aProjCurv.SetBndPnt(aBndPnt); + aProjCurv.SetMaxDist(aMaxDist); + aProjCurv.Perform(aBAHC); ProjLib::MakePCurveOfType(aProjCurv, aC2D); aTolR=aProjCurv.GetTolerance(); } // - if (aC2D.IsNull()) { - ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, TolReached2d);// 2 + if (aC2D.IsNull() && (aTR < aMaxTol || aTR < TolReached2d)) + { + aTR = Max(TolReached2d, aMaxTol); + ProjLib_ProjectedCurve aProjCurvAgain(aBAHS, aBAHC, aTR);// 2 ProjLib::MakePCurveOfType(aProjCurvAgain, aC2D); aTolR = aProjCurvAgain.GetTolerance(); - // - if (aC2D.IsNull()) { - Standard_Real aTR=0.0001; - ProjLib_ProjectedCurve aProj3(aBAHS, aBAHC, aTR);// 3 - ProjLib::MakePCurveOfType(aProj3, aC2D); - aTolR = aProj3.GetTolerance(); - } } // if(aC2D.IsNull()) diff --git a/src/BRepFill/BRepFill_ComputeCLine.hxx b/src/BRepFill/BRepFill_ComputeCLine.hxx index 2b438001d5..5391c41aae 100644 --- a/src/BRepFill/BRepFill_ComputeCLine.hxx +++ b/src/BRepFill/BRepFill_ComputeCLine.hxx @@ -61,6 +61,9 @@ public: //! Changes the constraints of the approximation. Standard_EXPORT void SetConstraints (const AppParCurves_Constraint FirstC, const AppParCurves_Constraint LastC); + //! Changes the max number of segments, which is allowed for cutting. + Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); + //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user //! when more points were needed. @@ -114,7 +117,7 @@ private: Standard_Boolean mycut; AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; - + Standard_Integer myMaxSegments; }; diff --git a/src/ProjLib/ProjLib.cxx b/src/ProjLib/ProjLib.cxx index c9f380bcc8..36ee34ddbc 100644 --- a/src/ProjLib/ProjLib.cxx +++ b/src/ProjLib/ProjLib.cxx @@ -48,6 +48,7 @@ #include #include #include +#include //======================================================================= //function : Project @@ -281,3 +282,25 @@ void ProjLib::MakePCurveOfType break; } } +//======================================================================= +//function : IsAnaSurf +//purpose : +//======================================================================= +Standard_Boolean ProjLib::IsAnaSurf + (const Handle(Adaptor3d_HSurface)& theAS) +{ + switch (theAS->GetType()) + { + + case GeomAbs_Plane: + case GeomAbs_Cylinder: + case GeomAbs_Cone: + case GeomAbs_Sphere: + case GeomAbs_Torus: + return Standard_True; + break; + default : + return Standard_False; + break; + } +} diff --git a/src/ProjLib/ProjLib.hxx b/src/ProjLib/ProjLib.hxx index b5fa7ac097..f533479643 100644 --- a/src/ProjLib/ProjLib.hxx +++ b/src/ProjLib/ProjLib.hxx @@ -55,7 +55,7 @@ class ProjLib_Cylinder; class ProjLib_Cone; class ProjLib_Sphere; class ProjLib_Torus; - +class Adaptor3d_HSurface; //! The projLib package first provides projection of //! curves on a plane along a given Direction. The @@ -132,6 +132,12 @@ public: //! Make empty P-Curve of relevant to type Standard_EXPORT static void MakePCurveOfType (const ProjLib_ProjectedCurve& PC, Handle(Geom2d_Curve)& aC); + //! Returns "true" if surface is analytical, that is it can be + //! Plane, Cylinder, Cone, Sphere, Torus. + //! For all other types of surface method returns "false". + Standard_EXPORT static Standard_Boolean IsAnaSurf + (const Handle(Adaptor3d_HSurface)& theAS); + diff --git a/src/ProjLib/ProjLib_ComputeApprox.cxx b/src/ProjLib/ProjLib_ComputeApprox.cxx index 9fc50d35fd..5090998187 100644 --- a/src/ProjLib/ProjLib_ComputeApprox.cxx +++ b/src/ProjLib/ProjLib_ComputeApprox.cxx @@ -17,6 +17,7 @@ // modified by NIZHNY-OFV Thu Jan 20 11:04:19 2005 #include +#include #include #include @@ -956,6 +957,18 @@ static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf, return aTolV; } +//======================================================================= +//function : ProjLib_ComputeApprox +//purpose : +//======================================================================= + +ProjLib_ComputeApprox::ProjLib_ComputeApprox(): + myTolerance(Precision::PApproximation()), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myBndPnt(AppParCurves_TangencyPoint) +{ +} //======================================================================= //function : ProjLib_ComputeApprox @@ -965,19 +978,32 @@ static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf, ProjLib_ComputeApprox::ProjLib_ComputeApprox (const Handle(Adaptor3d_HCurve) & C, const Handle(Adaptor3d_HSurface) & S, - const Standard_Real Tol ) + const Standard_Real Tol): + myTolerance(Max(Tol, Precision::PApproximation())), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myBndPnt(AppParCurves_TangencyPoint) +{ + Perform(C, S); +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= + +void ProjLib_ComputeApprox::Perform + (const Handle(Adaptor3d_HCurve) & C, + const Handle(Adaptor3d_HSurface) & S ) { // if the surface is a plane and the curve a BSpline or a BezierCurve, // don`t make an Approx but only the projection of the poles. - myTolerance = Max(Precision::PApproximation(),Tol); Standard_Integer NbKnots, NbPoles ; GeomAbs_CurveType CType = C->GetType(); GeomAbs_SurfaceType SType = S->GetType(); - Standard_Boolean SurfIsAnal = (SType != GeomAbs_BSplineSurface) && - (SType != GeomAbs_BezierSurface) && - (SType != GeomAbs_OtherSurface) ; + Standard_Boolean SurfIsAnal = ProjLib::IsAnaSurf(S); Standard_Boolean CurvIsAnal = (CType != GeomAbs_BSplineCurve) && (CType != GeomAbs_BezierCurve) && @@ -1085,21 +1111,43 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox #endif //----------- - Standard_Integer Deg1, Deg2; + Standard_Integer Deg1 = 8, Deg2; if(simplecase) { - Deg1 = 8; Deg2 = 10; } else { - Deg1 = 8; Deg2 = 12; } + if(myDegMin > 0) + { + Deg1 = myDegMin; + } + // + if(myDegMax > 0) + { + Deg2 = myDegMax; + } + // + Standard_Integer aMaxSegments = 1000; + if(myMaxSegments > 0) + { + aMaxSegments = myMaxSegments; + } + AppParCurves_Constraint aFistC = AppParCurves_TangencyPoint, aLastC = AppParCurves_TangencyPoint; + if(myBndPnt != AppParCurves_TangencyPoint) + { + aFistC = myBndPnt; + aLastC = myBndPnt; + } + //------------- const Standard_Real aTolU = ComputeTolU(S, myTolerance); const Standard_Real aTolV = ComputeTolV(S, myTolerance); const Standard_Real aTol2d = Max(Sqrt(aTolU*aTolU + aTolV*aTolV), Precision::PConfusion()); - Approx_FitAndDivide2d Fit(F, Deg1, Deg2, myTolerance, aTol2d, Standard_True); + Approx_FitAndDivide2d Fit(Deg1, Deg2, myTolerance, aTol2d, Standard_True, aFistC, aLastC); + Fit.SetMaxSegments(aMaxSegments); + Fit.Perform(F); Standard_Real aNewTol2d = 0; if(Fit.IsAllApproximated()) { @@ -1115,8 +1163,7 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox aNewTol2d = Max(aNewTol2d, Tol2d); AppParCurves_MultiCurve MC = Fit.Value( i); //Charge la Ieme Curve TColgp_Array1OfPnt2d Poles2d( 1, MC.Degree() + 1);//Recupere les poles - MC.Curve(1, Poles2d); - + MC.Curve(1, Poles2d); Conv.AddCurve(Poles2d); } @@ -1141,13 +1188,6 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox C->LastParameter(), NewKnots); - /*cout << endl; - for (int i = 1; i <= NbPoles; i++) - { - cout << NewPoles.Value(i).X() << " " << NewPoles.Value(i).Y() << endl; - } - cout << endl; */ - // il faut recadrer les poles de debut et de fin: // ( Car pour les problemes de couture, on a du ouvrir l`intervalle // de definition de la courbe.) @@ -1157,6 +1197,17 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox NewKnots, NewMults, Conv.Degree()); + + if(aFistC == AppParCurves_PassPoint || aLastC == AppParCurves_PassPoint) + { + // try to smoother the Curve GeomAbs_C1. + Standard_Integer aDeg = myBSpline->Degree(); + Standard_Boolean OK = Standard_True; + Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d); + for (Standard_Integer ij = 2; ij < NbKnots; ij++) { + OK = OK && myBSpline->RemoveKnot(ij, aDeg-1, aSmoothTol); + } + } } else { Standard_Integer NbCurves = Fit.NbMultiCurves(); @@ -1254,6 +1305,42 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox } } } +//======================================================================= +//function : SetTolerance +//purpose : +//======================================================================= +void ProjLib_ComputeApprox::SetTolerance(const Standard_Real theTolerance) +{ + myTolerance = theTolerance; +} + +//======================================================================= +//function : SetDegree +//purpose : +//======================================================================= +void ProjLib_ComputeApprox::SetDegree(const Standard_Integer theDegMin, + const Standard_Integer theDegMax) +{ + myDegMin = theDegMin; + myDegMax = theDegMax; +} +//======================================================================= +//function : SetMaxSegments +//purpose : +//======================================================================= +void ProjLib_ComputeApprox::SetMaxSegments(const Standard_Integer theMaxSegments) +{ + myMaxSegments = theMaxSegments; +} + +//======================================================================= +//function : SetBndPnt +//purpose : +//======================================================================= +void ProjLib_ComputeApprox::SetBndPnt(const AppParCurves_Constraint theBndPnt) +{ + myBndPnt = theBndPnt; +} //======================================================================= //function : BSpline diff --git a/src/ProjLib/ProjLib_ComputeApprox.hxx b/src/ProjLib/ProjLib_ComputeApprox.hxx index 6bb6d54a36..c1aeda678b 100644 --- a/src/ProjLib/ProjLib_ComputeApprox.hxx +++ b/src/ProjLib/ProjLib_ComputeApprox.hxx @@ -22,6 +22,8 @@ #include #include +#include + class Geom2d_BSplineCurve; class Geom2d_BezierCurve; class Adaptor3d_HCurve; @@ -31,17 +33,51 @@ class Adaptor3d_HSurface; //! Approximate the projection of a 3d curve on an //! analytic surface and stores the result in Approx. //! The result is a 2d curve. +//! For approximation some parameters are used, including +//! required tolerance of approximation. +//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from +//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed +//! from 3d tolerance with help of U,V resolutions of surface. +//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation +//! and have nothing to do with distance between the projected curve and the surface. class ProjLib_ComputeApprox { public: DEFINE_STANDARD_ALLOC - + //! Empty constructor, it only sets some initial values for class fields. + Standard_EXPORT ProjLib_ComputeApprox(); + //! is the tolerance with which the //! approximation is performed. + //! Other parameters for approximation have default values. Standard_EXPORT ProjLib_ComputeApprox(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol); + //! Performs projecting. + //! In case of approximation current values of parameters are used: + //! default values or set by corresponding methods Set... + Standard_EXPORT void Perform(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S); + + //! Set tolerance of approximation. + //! Default value is Precision::Confusion(). + Standard_EXPORT void SetTolerance(const Standard_Real theTolerance); + + //! Set min and max possible degree of result BSpline curve2d, which is got by approximation. + //! If theDegMin/Max < 0, algorithm uses values that are chosen depending of types curve 3d + //! and surface. + Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax); + + //! Set the parameter, which defines maximal value of parametric intervals the projected + //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default + //! value = 1000. + Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments); + + //! Set the parameter, which defines type of boundary condition between segments during approximation. + //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint. + //! Default value is AppParCurves_TangencyPoint; + Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt); + Standard_EXPORT Handle(Geom2d_BSplineCurve) BSpline() const; Standard_EXPORT Handle(Geom2d_BezierCurve) Bezier() const; @@ -60,12 +96,13 @@ protected: private: - - Standard_Real myTolerance; Handle(Geom2d_BSplineCurve) myBSpline; Handle(Geom2d_BezierCurve) myBezier; - + Standard_Integer myDegMin; + Standard_Integer myDegMax; + Standard_Integer myMaxSegments; + AppParCurves_Constraint myBndPnt; }; diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index 16e1255320..c639c819f6 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -477,11 +477,15 @@ class ProjLib_PolarFunction : public AppCont_Function ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface() : myProjIsDone(Standard_False), - myTolerance (-1.0) + myTolerance(Precision::Approximation()), + myTolReached(-1.0), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { } - //======================================================================= //function : ProjLib_ComputeApproxOnPolarSurface //purpose : @@ -493,10 +497,37 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface const Handle(Adaptor3d_HSurface)& theSurface, const Standard_Real theTolerance3D) : myProjIsDone(Standard_False), - myTolerance (theTolerance3D) + myTolerance(theTolerance3D), + myTolReached(-1.0), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { myBSpline = Perform(theInitialCurve2d, theCurve, theSurface); } + +//======================================================================= +//function : ProjLib_ComputeApproxOnPolarSurface +//purpose : case without curve of initialization +//======================================================================= + +ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface + (const Handle(Adaptor3d_HCurve)& theCurve, + const Handle(Adaptor3d_HSurface)& theSurface, + const Standard_Real theTolerance3D) +: myProjIsDone(Standard_False), + myTolerance(theTolerance3D), + myTolReached(-1.0), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) +{ + const Handle(Adaptor2d_HCurve2d) anInitCurve2d; + myBSpline = Perform(anInitCurve2d, theCurve, theSurface); +} + //======================================================================= //function : ProjLib_ComputeApproxOnPolarSurface //purpose : Process the case of sewing @@ -509,7 +540,12 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface const Handle(Adaptor3d_HSurface)& theSurface, const Standard_Real theTolerance3D) : myProjIsDone(Standard_False), - myTolerance (theTolerance3D) + myTolerance(theTolerance3D), + myTolReached(-1.0), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { // InitialCurve2d and InitialCurve2dBis are two pcurves of the sewing Handle(Geom2d_BSplineCurve) bsc = @@ -538,21 +574,6 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface } } -//======================================================================= -//function : ProjLib_ComputeApproxOnPolarSurface -//purpose : case without curve of initialization -//======================================================================= - -ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface - (const Handle(Adaptor3d_HCurve)& theCurve, - const Handle(Adaptor3d_HSurface)& theSurface, - const Standard_Real theTolerance3D) -: myProjIsDone(Standard_False), - myTolerance (theTolerance3D) -{ - const Handle(Adaptor2d_HCurve2d) anInitCurve2d; - myBSpline = Perform(anInitCurve2d, theCurve, theSurface); -} //======================================================================= //function : Concat @@ -628,15 +649,27 @@ static Handle(Geom2d_BSplineCurve) Concat(Handle(Geom2d_BSplineCurve) C1, return BS; } +//======================================================================= +//function : Perform +//purpose : +//======================================================================= + +void ProjLib_ComputeApproxOnPolarSurface::Perform +(const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S) +{ + const Handle(Adaptor2d_HCurve2d) anInitCurve2d; + myBSpline = Perform(anInitCurve2d, Curve, S); +} //======================================================================= //function : Perform //purpose : //======================================================================= + Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform (const Handle(Adaptor2d_HCurve2d)& InitialCurve2d, const Handle(Adaptor3d_HCurve)& Curve, - const Handle(Adaptor3d_HSurface)& S) + const Handle(Adaptor3d_HSurface)& S) { //OCC217 Standard_Real Tol3d = myTolerance; @@ -752,8 +785,11 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform } if(myProjIsDone) { - BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d); - if(BSC2d.IsNull()) return Handle(Geom2d_BSplineCurve)(); //IFV + BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d); + if(BSC2d.IsNull()) + { + return Handle(Geom2d_BSplineCurve)(); + } LOfBSpline2d.Append(BSC2d); } else { @@ -799,7 +835,7 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform } } if(myProjIsDone) { - BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d); + BSC2d = ProjectUsingInitialCurve2d(AHC, S, AHC2d); if(BSC2d.IsNull()) { return Handle(Geom2d_BSplineCurve)(); } @@ -854,9 +890,10 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::Perform if(!myProjIsDone) return Handle(Geom2d_BSplineCurve)(); } - return ProjectUsingInitialCurve2d(AHC, S, AHC2d); + return ProjectUsingInitialCurve2d(AHC, S, AHC2d); } + //======================================================================= //function : ProjLib_BuildInitialCurve2d //purpose : @@ -875,7 +912,11 @@ Handle(Adaptor2d_HCurve2d) Standard_Real Tol3d = myTolerance; Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d); Standard_Real DistTol3d = 100.0*Tol3d; - + if(myMaxDist > 0.) + { + DistTol3d = myMaxDist; + } + Standard_Real DistTol3d2 = DistTol3d * DistTol3d; Standard_Real uperiod = 0.0, vperiod = 0.0; computePeriodicity(Surf, uperiod, vperiod); @@ -1054,7 +1095,7 @@ Handle(Adaptor2d_HCurve2d) aMinSqDist = aSqDist; } } - if (aMinSqDist > DistTol3d * DistTol3d) //try to project with less tolerance + if (aMinSqDist > DistTol3d2) //try to project with less tolerance { TolU = Min(TolU, Precision::PConfusion()); TolV = Min(TolV, Precision::PConfusion()); @@ -1070,7 +1111,7 @@ Handle(Adaptor2d_HCurve2d) Standard_Integer GoodValue = 1; for ( i = 1 ; i <= aExtPS.NbExt() ; i++ ) { - if( aExtPS.SquareDistance(i) < DistTol3d * DistTol3d ) { + if( aExtPS.SquareDistance(i) < DistTol3d2 ) { if( aExtPS.SquareDistance(i) <= 1.e-18 ) { aExtPS.Point(i).Parameter(u,v); gp_Pnt2d p2d(u,v); @@ -1092,7 +1133,7 @@ Handle(Adaptor2d_HCurve2d) if( Sols.Length() > 1 ) areManyZeros = Standard_True; - if( Dist2Min <= DistTol3d * DistTol3d) { + if( Dist2Min <= DistTol3d2) { if( !areManyZeros ) { aExtPS.Point(GoodValue).Parameter(u,v); Pts2d(1).SetCoord(u,v); @@ -1122,7 +1163,7 @@ Handle(Adaptor2d_HCurve2d) Dist2Min = 1.e+200; if( aTPS.IsDone() && aTPS.NbExt() >= 1 ) { for( j = 1 ; j <= aTPS.NbExt() ; j++ ) { - if( aTPS.SquareDistance(j) < DistTol3d * DistTol3d ) { + if( aTPS.SquareDistance(j) < DistTol3d2 ) { nbExtOk++; if( aTPS.SquareDistance(j) < Dist2Min ) { Dist2Min = aTPS.SquareDistance(j); @@ -1150,7 +1191,7 @@ Handle(Adaptor2d_HCurve2d) Standard_Integer indExt = 0; if( aTPS.IsDone() && aTPS.NbExt() >= 1 ) { for( i = 1 ; i <= aTPS.NbExt() ; i++ ) { - if( aTPS.SquareDistance(i) < DistTol3d * DistTol3d && aTPS.SquareDistance(i) < Dist2Min ) { + if( aTPS.SquareDistance(i) < DistTol3d2 && aTPS.SquareDistance(i) < Dist2Min ) { Dist2Min = aTPS.SquareDistance(i); indExt = i; isFound = Standard_True; @@ -1224,7 +1265,7 @@ Handle(Adaptor2d_HCurve2d) if (aLocateExtPS.IsDone()) { - if (aLocateExtPS.SquareDistance() < DistTol3d * DistTol3d) + if (aLocateExtPS.SquareDistance() < DistTol3d2) { //OCC217 //if (aLocateExtPS.SquareDistance() < Tol3d * Tol3d) { (aLocateExtPS.Point()).Parameter(U0,V0); @@ -1249,7 +1290,7 @@ Handle(Adaptor2d_HCurve2d) imin = isol; } } - if (LocalMinSqDist < DistTol3d * DistTol3d) + if (LocalMinSqDist < DistTol3d2) { Standard_Real LocalU, LocalV; aGlobalExtr.Point(imin).Parameter(LocalU, LocalV); @@ -1321,7 +1362,7 @@ Handle(Adaptor2d_HCurve2d) locext.Perform(pntproj, Uaux, V0); if (locext.IsDone()) - if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 + if (locext.SquareDistance() < DistTol3d2) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { (locext.Point()).Parameter(u,v); if((aUsup - U0) > (U0 - aUinf)) @@ -1348,7 +1389,7 @@ Handle(Adaptor2d_HCurve2d) locext.Perform(pntproj, U0, Vaux); if (locext.IsDone()) - if (locext.SquareDistance() < DistTol3d * DistTol3d) { //OCC217 + if (locext.SquareDistance() < DistTol3d2) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { (locext.Point()).Parameter(u,v); if((aVsup - V0) > (V0 - aVinf)) @@ -1377,7 +1418,7 @@ Handle(Adaptor2d_HCurve2d) locext.Perform(pntproj, Uaux, Vaux); if (locext.IsDone()) - if (locext.SquareDistance() < DistTol3d * DistTol3d) { + if (locext.SquareDistance() < DistTol3d2) { //if (locext.SquareDistance() < Tol3d * Tol3d) { (locext.Point()).Parameter(u,v); if((Usup - U0) > (U0 - Uinf)) @@ -1405,7 +1446,7 @@ Handle(Adaptor2d_HCurve2d) Dist2Min = ext.SquareDistance(j); aGoodValue = j; } - if (Dist2Min < DistTol3d * DistTol3d) { + if (Dist2Min < DistTol3d2) { //if (Dist2Min < Tol3d * Tol3d) { (ext.Point(aGoodValue)).Parameter(u,v); if(uperiod) { @@ -1490,9 +1531,6 @@ Handle(Adaptor2d_HCurve2d) // Modified by Sergey KHROMOV - Thu Apr 18 10:58:02 2002 End } - - - //======================================================================= //function : ProjLib_ProjectUsingInitialCurve2d //purpose : @@ -1501,24 +1539,27 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface:: ProjectUsingInitialCurve2d(const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& Surf, - const Handle(Adaptor2d_HCurve2d)& InitCurve2d) + const Handle(Adaptor2d_HCurve2d)& InitCurve2d) { //OCC217 Standard_Real Tol3d = myTolerance; - Standard_Real DistTol3d = 1.0*Tol3d; + Standard_Real DistTol3d = 100.0*Tol3d; + if(myMaxDist > 0.) + { + DistTol3d = myMaxDist; + } + Standard_Real DistTol3d2 = DistTol3d * DistTol3d; Standard_Real TolU = Surf->UResolution(Tol3d), TolV = Surf->VResolution(Tol3d); Standard_Real Tol2d = Max(Sqrt(TolU*TolU + TolV*TolV), Precision::PConfusion()); Standard_Integer i; GeomAbs_SurfaceType TheTypeS = Surf->GetType(); GeomAbs_CurveType TheTypeC = Curve->GetType(); -// Handle(Standard_Type) TheTypeS = Surf->DynamicType(); -// Handle(Standard_Type) TheTypeC = Curve->DynamicType(); // si on a : -// if(TheTypeS == STANDARD_TYPE(Geom_BSplineSurface)) { if(TheTypeS == GeomAbs_Plane) { Standard_Real S, T; gp_Pln Plane = Surf->Plane(); if(TheTypeC == GeomAbs_BSplineCurve) { + myTolReached = Precision::Confusion(); Handle(Geom_BSplineCurve) BSC = Curve->BSpline(); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { @@ -1540,6 +1581,7 @@ Handle(Geom2d_BSplineCurve) } if(TheTypeC == GeomAbs_BezierCurve) { + myTolReached = Precision::Confusion(); Handle(Geom_BezierCurve) BC = Curve->Bezier(); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { @@ -1572,17 +1614,11 @@ Handle(Geom2d_BSplineCurve) gp_Pnt p22 = BSS->Pole(2,2); gp_Vec V1(p11,p12); gp_Vec V2(p21,p22); - if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ //OCC217 - //if(V1.IsEqual(V2,myTolerance,myTolerance/(p11.Distance(p12)*180/M_PI))){ - // so the polar surface is plane - // and if it is enough to projet the poles of Curve + if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ Standard_Integer Dist2Min = IntegerLast(); Standard_Real u,v; - //OCC217 - //Standard_Real TolU = Surf->UResolution(myTolerance) - // , TolV = Surf->VResolution(myTolerance); -// gp_Pnt pntproj; if(TheTypeC == GeomAbs_BSplineCurve) { + myTolReached = Tol3d; Handle(Geom_BSplineCurve) BSC = Curve->BSpline(); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { @@ -1594,8 +1630,7 @@ Handle(Geom2d_BSplineCurve) if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); - if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 - //if (Dist2Min < myTolerance * myTolerance) { + if (Dist2Min < DistTol3d2) { (extrloc.Point()).Parameter(u,v); Poles2d(i).SetCoord(u,v); myProjIsDone = Standard_True; @@ -1624,6 +1659,7 @@ Handle(Geom2d_BSplineCurve) } } if(TheTypeC == GeomAbs_BezierCurve) { + myTolReached = Tol3d; Handle(Geom_BezierCurve) BC = Curve->Bezier(); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { @@ -1634,8 +1670,7 @@ Handle(Geom2d_BSplineCurve) if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); - if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 - //if (Dist2Min < myTolerance * myTolerance) { + if (Dist2Min < DistTol3d2) { (extrloc.Point()).Parameter(u,v); Poles2d(i).SetCoord(u,v); myProjIsDone = Standard_True; @@ -1677,19 +1712,15 @@ Handle(Geom2d_BSplineCurve) gp_Pnt p22 = BS->Pole(2,2); gp_Vec V1(p11,p12); gp_Vec V2(p21,p22); - if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ //OCC217 - //if (V1.IsEqual(V2,myTolerance,myTolerance/(p11.Distance(p12)*180/M_PI))){ - // and if it is enough to project the poles of Curve + if(V1.IsEqual(V2,Tol3d,Tol3d/(p11.Distance(p12)*180/M_PI))){ Standard_Integer Dist2Min = IntegerLast(); Standard_Real u,v; - //OCC217 - //Standard_Real TolU = Surf->UResolution(myTolerance) - // , TolV = Surf->VResolution(myTolerance); - + // gp_Pnt pntproj; if(TheTypeC == GeomAbs_BSplineCurve) { + myTolReached = Tol3d; Handle(Geom_BSplineCurve) BSC = Curve->BSpline(); - TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); + TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { myProjIsDone = Standard_False; Dist2Min = IntegerLast(); @@ -1699,8 +1730,7 @@ Handle(Geom2d_BSplineCurve) if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); - if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 - //if (Dist2Min < myTolerance * myTolerance) { + if (Dist2Min < DistTol3d2) { (extrloc.Point()).Parameter(u,v); Poles2d(i).SetCoord(u,v); myProjIsDone = Standard_True; @@ -1729,6 +1759,7 @@ Handle(Geom2d_BSplineCurve) } } if(TheTypeC == GeomAbs_BezierCurve) { + myTolReached = Tol3d; Handle(Geom_BezierCurve) BC = Curve->Bezier(); TColgp_Array1OfPnt2d Poles2d(1,Curve->NbPoles()); for(i = 1;i <= Curve->NbPoles();i++) { @@ -1739,8 +1770,7 @@ Handle(Geom2d_BSplineCurve) if (extrloc.IsDone()) { Dist2Min = (Standard_Integer ) extrloc.SquareDistance(); - if (Dist2Min < DistTol3d * DistTol3d) { //OCC217 - //if (Dist2Min < myTolerance * myTolerance) { + if (Dist2Min < DistTol3d2) { (extrloc.Point()).Parameter(u,v); Poles2d(i).SetCoord(u,v); myProjIsDone = Standard_True; @@ -1772,8 +1802,7 @@ Handle(Geom2d_BSplineCurve) } } - ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, Tol3d) ; //OCC217 - //ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, myTolerance) ; + ProjLib_PolarFunction F(Curve, Surf, InitCurve2d, Tol3d) ; #ifdef OCCT_DEBUG Standard_Integer Nb = 50; @@ -1812,15 +1841,34 @@ Handle(Geom2d_BSplineCurve) #endif Standard_Integer Deg1,Deg2; -// Deg1 = 8; -// Deg2 = 8; - Deg1 = 2; //IFV - Deg2 = 8; //IFV + Deg1 = 2; + Deg2 = 8; + if(myDegMin > 0) + { + Deg1 = myDegMin; + } + if(myDegMax > 0) + { + Deg2 = myDegMax; + } + Standard_Integer aMaxSegments = 1000; + if(myMaxSegments > 0) + { + aMaxSegments = myMaxSegments; + } + AppParCurves_Constraint aFistC = AppParCurves_TangencyPoint, aLastC = AppParCurves_TangencyPoint; + if(myBndPnt != AppParCurves_TangencyPoint) + { + aFistC = myBndPnt; + aLastC = myBndPnt; + } - Approx_FitAndDivide2d Fit(F,Deg1,Deg2,Tol3d,Tol2d, //OCC217 - //Approx_FitAndDivide2d Fit(F,Deg1,Deg2,myTolerance,myTolerance, - Standard_True); + Approx_FitAndDivide2d Fit(Deg1, Deg2, Tol3d, Tol2d, Standard_True, aFistC, aLastC); + Fit.SetMaxSegments(aMaxSegments); + Fit.Perform(F); + Standard_Real anOldTol2d = Tol2d; + Standard_Real aNewTol2d = 0; if(Fit.IsAllApproximated()) { Standard_Integer j; Standard_Integer NbCurves = Fit.NbMultiCurves(); @@ -1831,8 +1879,12 @@ Handle(Geom2d_BSplineCurve) for (j = 1; j <= NbCurves; j++) { Standard_Integer Deg = Fit.Value(j).Degree(); MaxDeg = Max ( MaxDeg, Deg); + Fit.Error(j,Tol3d, Tol2d); + aNewTol2d = Max(aNewTol2d, Tol2d); } - + // + myTolReached = Max(myTolReached, myTolerance * (aNewTol2d / anOldTol2d)); + // NbPoles = MaxDeg * NbCurves + 1; //Tops on the BSpline TColgp_Array1OfPnt2d Poles( 1, NbPoles); @@ -1884,10 +1936,9 @@ Handle(Geom2d_BSplineCurve) // try to smoother the Curve GeomAbs_C1. Standard_Boolean OK = Standard_True; - + Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d); for (Standard_Integer ij = 2; ij < NbKnots; ij++) { - OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1,Tol3d); //OCC217 - //OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1,myTolerance); + OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1, aSmoothTol); } #ifdef OCCT_DEBUG if (!OK) { @@ -1908,11 +1959,6 @@ Handle(Geom2d_BSplineCurve) ProjLib_ComputeApproxOnPolarSurface::BSpline() const { -// Modified by Sergey KHROMOV - Thu Apr 18 11:16:46 2002 End -// Standard_NoSuchObject_Raise_if -// (!myProjIsDone, -// "ProjLib_ComputeApproxOnPolarSurface:BSpline"); -// Modified by Sergey KHROMOV - Thu Apr 18 11:16:47 2002 End return myBSpline ; } @@ -1942,3 +1988,65 @@ Standard_Boolean ProjLib_ComputeApproxOnPolarSurface::IsDone() const { return myProjIsDone; } +//======================================================================= +//function : SetTolerance +//purpose : +//======================================================================= + +void ProjLib_ComputeApproxOnPolarSurface::SetTolerance(const Standard_Real theTol) + +{ + myTolerance = theTol; +} +//======================================================================= +//function : SetDegree +//purpose : +//======================================================================= +void ProjLib_ComputeApproxOnPolarSurface::SetDegree( + const Standard_Integer theDegMin, + const Standard_Integer theDegMax) +{ + myDegMin = theDegMin; + myDegMax = theDegMax; +} +//======================================================================= +//function : SetMaxSegments +//purpose : +//======================================================================= +void ProjLib_ComputeApproxOnPolarSurface::SetMaxSegments( + const Standard_Integer theMaxSegments) +{ + myMaxSegments = theMaxSegments; +} + +//======================================================================= +//function : SetBndPnt +//purpose : +//======================================================================= +void ProjLib_ComputeApproxOnPolarSurface::SetBndPnt( + const AppParCurves_Constraint theBndPnt) +{ + myBndPnt = theBndPnt; +} + +//======================================================================= +//function : SetMaxDist +//purpose : +//======================================================================= +void ProjLib_ComputeApproxOnPolarSurface::SetMaxDist( + const Standard_Real theMaxDist) +{ + myMaxDist = theMaxDist; +} + +//======================================================================= +//function : Tolerance +//purpose : +//======================================================================= + +Standard_Real ProjLib_ComputeApproxOnPolarSurface::Tolerance() const + +{ + return myTolReached; +} + diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx index 4e116eba9c..3927f2759c 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx @@ -23,6 +23,7 @@ #include #include +#include class Geom2d_BSplineCurve; class Geom2d_Curve; class Adaptor3d_HCurve; @@ -35,33 +36,89 @@ class Adaptor2d_HCurve2d; //! The result is a 2d curve. The evaluation of the //! current point of the 2d curve is done with the //! evaluation of the extrema P3d - Surface. +//! For approximation some parameters are used, including +//! required tolerance of approximation. +//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from +//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed +//! from 3d tolerance with help of U,V resolutions of surface. +//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation +//! and have nothing to do with distance between the projected curve and the surface. class ProjLib_ComputeApproxOnPolarSurface { public: DEFINE_STANDARD_ALLOC - + //! Empty constructor, it only sets some initial values for class fields. Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(); - + + //! Constructor, which performs projecting. Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol = 1.0e-4); - + + + //! Constructor, which performs projecting, using initial curve 2d InitCurve2d, which is any rough approximation of result curve. + //! Parameter Tol is 3d tolerance of approximation. Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol); + + //! Constructor, which performs projecting, using two initial curves 2d: InitCurve2d and InitCurve2dBis that are any rough approximations of result curves. + //! This constructor is used to get two pcurves for seem edge. + //! Parameter Tol is 3d tolerance of approximation. + Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor2d_HCurve2d)& InitCurve2dBis, const Handle(Adaptor3d_HCurve)& C, + const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol); + - Standard_EXPORT ProjLib_ComputeApproxOnPolarSurface(const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor2d_HCurve2d)& InitCurve2dBis, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S, const Standard_Real Tol); - + //! Set min and max possible degree of result BSpline curve2d, which is got by approximation. + //! If theDegMin/Max < 0, algorithm uses values min = 2, max = 8. + Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax); + + //! Set the parameter, which defines maximal value of parametric intervals the projected + //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default + //! value = 1000. + Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments); + + //! Set the parameter, which defines type of boundary condition between segments during approximation. + //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint. + //! Default value is AppParCurves_TangencyPoint. + Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt); + + //! Set the parameter, which defines maximal possible distance between projected curve and surface. + //! It is used only for projecting on not analytical surfaces. + //! If theMaxDist < 0, algoritm uses default value 100.*Tolerance. + //! If real distance between curve and surface more then theMaxDist, algorithm stops working. + Standard_EXPORT void SetMaxDist(const Standard_Real theMaxDist); + + //! Set the tolerance used to project + //! the curve on the surface. + //! Default value is Precision::Approximation(). + Standard_EXPORT void SetTolerance (const Standard_Real theTolerance); + + //! Method, which performs projecting, using default values of parameters or + //! they must be set by corresponding methods before using. + Standard_EXPORT void Perform (const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S); + + //! Method, which performs projecting, using default values of parameters or + //! they must be set by corresponding methods before using. + //! Parameter InitCurve2d is any rough estimation of 2d result curve. Standard_EXPORT Handle(Geom2d_BSplineCurve) Perform (const Handle(Adaptor2d_HCurve2d)& InitCurve2d, const Handle(Adaptor3d_HCurve)& C, const Handle(Adaptor3d_HSurface)& S); - + + //! Builds initial 2d curve as BSpline with degree = 1 using Extrema algoritm. + //! Method is used in method Perform(...). Standard_EXPORT Handle(Adaptor2d_HCurve2d) BuildInitialCurve2d (const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S); - + + + //! Method, which performs projecting. + //! Method is used in method Perform(...). Standard_EXPORT Handle(Geom2d_BSplineCurve) ProjectUsingInitialCurve2d (const Handle(Adaptor3d_HCurve)& Curve, const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor2d_HCurve2d)& InitCurve2d); - + + //! Returns result curve 2d. Standard_EXPORT Handle(Geom2d_BSplineCurve) BSpline() const; - + //! Returns second 2d curve. Standard_EXPORT Handle(Geom2d_Curve) Curve2d() const; Standard_EXPORT Standard_Boolean IsDone() const; + //! returns the reached Tolerance. + Standard_EXPORT Standard_Real Tolerance() const; @@ -79,6 +136,12 @@ private: Standard_Real myTolerance; Handle(Geom2d_BSplineCurve) myBSpline; Handle(Geom2d_Curve) my2ndCurve; + Standard_Real myTolReached; + Standard_Integer myDegMin; + Standard_Integer myDegMax; + Standard_Integer myMaxSegments; + Standard_Real myMaxDist; + AppParCurves_Constraint myBndPnt; }; diff --git a/src/ProjLib/ProjLib_ProjectedCurve.cxx b/src/ProjLib/ProjLib_ProjectedCurve.cxx index 03ac507ca6..136c1cf94f 100644 --- a/src/ProjLib/ProjLib_ProjectedCurve.cxx +++ b/src/ProjLib/ProjLib_ProjectedCurve.cxx @@ -42,6 +42,7 @@ #include #include #include +#include #include #include #include @@ -55,6 +56,41 @@ #include #include #include +#include +#include +//======================================================================= +//function : ComputeTolU +//purpose : +//======================================================================= + +static Standard_Real ComputeTolU(const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theTolerance) +{ + Standard_Real aTolU = theSurf->UResolution(theTolerance); + if (theSurf->IsUPeriodic()) + { + aTolU = Min(aTolU, 0.01*theSurf->UPeriod()); + } + + return aTolU; +} + +//======================================================================= +//function : ComputeTolV +//purpose : +//======================================================================= + +static Standard_Real ComputeTolV(const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theTolerance) +{ + Standard_Real aTolV = theSurf->VResolution(theTolerance); + if (theSurf->IsVPeriodic()) + { + aTolV = Min(aTolV, 0.01*theSurf->VPeriod()); + } + + return aTolV; +} //======================================================================= //function : IsoIsDeg @@ -113,18 +149,19 @@ static Standard_Boolean IsoIsDeg (const Adaptor3d_Surface& S, //======================================================================= static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve, - Standard_Boolean* IsTrimmed, - const Standard_Real dt, - const gp_Pnt& Pole, + Standard_Boolean* IsTrimmed, + const Standard_Real dt, + const gp_Pnt& Pole, Standard_Integer* SingularCase, - const Standard_Integer NumberOfSingularCase) + const Standard_Integer NumberOfSingularCase, + const Standard_Real TolConf) { Standard_Real f = myCurve->FirstParameter(); Standard_Real l = myCurve->LastParameter(); gp_Pnt P = myCurve->Value(f); - if(P.Distance(Pole) < Precision::Confusion()) { + if(P.Distance(Pole) <= TolConf) { IsTrimmed[0] = Standard_True; f = f+dt; myCurve = myCurve->Trim(f, l, Precision::Confusion()); @@ -132,7 +169,7 @@ static void TrimC3d(Handle(Adaptor3d_HCurve)& myCurve, } P = myCurve->Value(l); - if(P.Distance(Pole) < Precision::Confusion()) { + if(P.Distance(Pole) <= TolConf) { IsTrimmed[1] = Standard_True; l = l-dt; myCurve = myCurve->Trim(f, l, Precision::Confusion()); @@ -199,17 +236,24 @@ static void ExtendC2d (Handle(Geom2d_BSplineCurve)& aRes, } } gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle + Standard_Real ParOnLin = 0.; + if (theBoundDir.IsParallel(aDBnd, 100.*Precision::Angular())) + { + ParOnLin = ElCLib::Parameter(aLin, thePole); + } + else + { + Standard_Real U1x = BoundLin.Direction().X(); + Standard_Real U1y = BoundLin.Direction().Y(); + Standard_Real U2x = aLin.Direction().X(); + Standard_Real U2y = aLin.Direction().Y(); + Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X(); + Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y(); - Standard_Real U1x = BoundLin.Direction().X(); - Standard_Real U1y = BoundLin.Direction().Y(); - Standard_Real U2x = aLin.Direction().X(); - Standard_Real U2y = aLin.Direction().Y(); - Standard_Real Uo21x = aLin.Location().X() - BoundLin.Location().X(); - Standard_Real Uo21y = aLin.Location().Y() - BoundLin.Location().Y(); - - Standard_Real D = U1y*U2x-U1x*U2y; - - Standard_Real ParOnLin = (Uo21y * U1x - Uo21x * U1y)/D; //parameter of intersection point + Standard_Real D = U1y*U2x - U1x*U2y; + + ParOnLin = (Uo21y * U1x - Uo21x * U1y) / D; //parameter of intersection point + } Handle(Geom2d_Line) aSegLine = new Geom2d_Line(aLin); aSegment = (FirstOrLast == 0)? @@ -259,10 +303,13 @@ static void Project(ProjLib_Projector& P, Handle(Adaptor3d_HCurve)& C) //purpose : //======================================================================= -ProjLib_ProjectedCurve::ProjLib_ProjectedCurve() - +ProjLib_ProjectedCurve::ProjLib_ProjectedCurve() : + myTolerance(Precision::Confusion()), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { - myTolerance = Precision::Confusion(); } @@ -272,9 +319,13 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve() //======================================================================= ProjLib_ProjectedCurve::ProjLib_ProjectedCurve -(const Handle(Adaptor3d_HSurface)& S) +(const Handle(Adaptor3d_HSurface)& S) : + myTolerance(Precision::Confusion()), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { - myTolerance = Precision::Confusion(); Load(S); } @@ -286,11 +337,15 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve ProjLib_ProjectedCurve::ProjLib_ProjectedCurve (const Handle(Adaptor3d_HSurface)& S, - const Handle(Adaptor3d_HCurve)& C) + const Handle(Adaptor3d_HCurve)& C) : + myTolerance(Precision::Confusion()), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { - myTolerance = Precision::Confusion(); Load(S); - Load(C); + Perform(C); } @@ -302,11 +357,15 @@ ProjLib_ProjectedCurve::ProjLib_ProjectedCurve ProjLib_ProjectedCurve::ProjLib_ProjectedCurve (const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C, - const Standard_Real Tol) + const Standard_Real Tol) : + myTolerance(Max(Tol, Precision::Confusion())), + myDegMin(-1), myDegMax(-1), + myMaxSegments(-1), + myMaxDist(-1.), + myBndPnt(AppParCurves_TangencyPoint) { - myTolerance = Max(Tol, Precision::Confusion()); Load(S); - Load(C); + Perform(C); } @@ -320,13 +379,22 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HSurface)& S) mySurface = S ; } - //======================================================================= //function : Load //purpose : //======================================================================= -void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) +void ProjLib_ProjectedCurve::Load(const Standard_Real theTol) +{ + myTolerance = theTol; +} + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= + +void ProjLib_ProjectedCurve::Perform(const Handle(Adaptor3d_HCurve)& C) { myTolerance = Max(myTolerance, Precision::Confusion()); myCurve = C; @@ -335,6 +403,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) GeomAbs_SurfaceType SType = mySurface->GetType(); GeomAbs_CurveType CType = myCurve->GetType(); Standard_Boolean isAnalyticalSurf = Standard_True; + Standard_Boolean IsTrimmed[2] = { Standard_False, Standard_False }; + Standard_Integer SingularCase[2]; + const Standard_Real eps = 0.01; + Standard_Real TolConf = Precision::Confusion(); + Standard_Real dt = (LastPar - FirstPar) * eps; + Standard_Real U1 = 0.0, U2 = 0.0, V1 = 0.0, V2 = 0.0; + U1 = mySurface->FirstUParameter(); + U2 = mySurface->LastUParameter(); + V1 = mySurface->FirstVParameter(); + V2 = mySurface->LastVParameter(); switch (SType) { @@ -372,6 +450,28 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) // periodique en V !) P.SetInBounds(myCurve->FirstParameter()); } + else + { + const Standard_Real Vmax = M_PI / 2.; + const Standard_Real Vmin = -Vmax; + const Standard_Real minang = 1.e-5 * M_PI; + gp_Sphere aSph = mySurface->Sphere(); + Standard_Real anR = aSph.Radius(); + Standard_Real f = myCurve->FirstParameter(); + Standard_Real l = myCurve->LastParameter(); + + gp_Pnt Pf = myCurve->Value(f); + gp_Pnt Pl = myCurve->Value(l); + gp_Pnt aLoc = aSph.Position().Location(); + Standard_Real maxdist = Max(Pf.Distance(aLoc), Pl.Distance(aLoc)); + TolConf = Max(anR * minang, Abs(anR - maxdist)); + + //Surface has pole at V = Vmin and Vmax + gp_Pnt Pole = mySurface->Value(U1, Vmin); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf); + Pole = mySurface->Value(U1, Vmax); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf); + } myResult = P; } break; @@ -388,15 +488,11 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) case GeomAbs_BSplineSurface: { isAnalyticalSurf = Standard_False; - Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False}; - Standard_Integer SingularCase[2]; - Standard_Real f, l, dt; - const Standard_Real eps = 0.01; + Standard_Real f, l; f = myCurve->FirstParameter(); l = myCurve->LastParameter(); dt = (l - f) * eps; - Standard_Real U1 = 0.0, U2=0.0, V1=0.0, V2=0.0; const Adaptor3d_Surface& S = mySurface->Surface(); U1 = S.FirstUParameter(); U2 = S.LastUParameter(); @@ -407,36 +503,43 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) { //Surface has pole at U = Umin gp_Pnt Pole = mySurface->Value(U1, V1); - TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 1, TolConf); } if(IsoIsDeg(S, U2, GeomAbs_IsoU, 0., myTolerance)) { //Surface has pole at U = Umax gp_Pnt Pole = mySurface->Value(U2, V1); - TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 2, TolConf); } if(IsoIsDeg(S, V1, GeomAbs_IsoV, 0., myTolerance)) { //Surface has pole at V = Vmin gp_Pnt Pole = mySurface->Value(U1, V1); - TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 3, TolConf); } if(IsoIsDeg(S, V2, GeomAbs_IsoV, 0., myTolerance)) { //Surface has pole at V = Vmax gp_Pnt Pole = mySurface->Value(U1, V2); - TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4); + TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4, TolConf); } - ProjLib_ComputeApproxOnPolarSurface polar(myCurve, mySurface, myTolerance); + ProjLib_ComputeApproxOnPolarSurface polar; + polar.SetTolerance(myTolerance); + polar.SetDegree(myDegMin, myDegMax); + polar.SetMaxSegments(myMaxSegments); + polar.SetBndPnt(myBndPnt); + polar.SetMaxDist(myMaxDist); + polar.Perform(myCurve, mySurface); Handle(Geom2d_BSplineCurve) aRes = polar.BSpline(); if (!aRes.IsNull()) { + myTolerance = polar.Tolerance(); if( (IsTrimmed[0] || IsTrimmed[1])) { if(IsTrimmed[0]) @@ -467,10 +570,9 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) default: { isAnalyticalSurf = Standard_False; - Standard_Boolean IsTrimmed[2] = {Standard_False, Standard_False}; Standard_Real Vsingular[2] = {0.0 , 0.0}; //for surfaces of revolution - Standard_Real f = 0.0, l = 0.0, dt = 0.0; - const Standard_Real eps = 0.01; + Standard_Real f = 0.0, l = 0.0; + dt = 0.0; if(mySurface->GetType() == GeomAbs_SurfaceOfRevolution) { @@ -538,7 +640,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) } } - ProjLib_CompProjectedCurve Projector(mySurface,myCurve, myTolerance, myTolerance, 100 * myTolerance); + Standard_Real aTolU = Max(ComputeTolU(mySurface, myTolerance), Precision::Confusion()); + Standard_Real aTolV = Max(ComputeTolV(mySurface, myTolerance), Precision::Confusion()); + Standard_Real aTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV); + + Standard_Real aMaxDist = 100. * myTolerance; + if(myMaxDist > 0.) + { + aMaxDist = myMaxDist; + } + ProjLib_CompProjectedCurve Projector(mySurface,myCurve, aTolU, aTolV, aMaxDist); Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve(); HProjector->Set(Projector); @@ -559,8 +670,20 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) Standard_Boolean Only3d = Standard_False; Standard_Boolean Only2d = Standard_True; GeomAbs_Shape Continuity = GeomAbs_C1; + if(myBndPnt == AppParCurves_PassPoint) + { + Continuity = GeomAbs_C0; + } Standard_Integer MaxDegree = 14; + if(myDegMax > 0) + { + MaxDegree = myDegMax; + } Standard_Integer MaxSeg = 16; + if(myMaxSegments > 0) + { + MaxSeg = myMaxSegments; + } Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, myTolerance, Continuity, MaxDegree, MaxSeg, @@ -570,6 +693,10 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) if (!aRes.IsNull()) { + aTolU = appr.MaxError2dU(); + aTolV = appr.MaxError2dV(); + Standard_Real aNewTol2d = Sqrt(aTolU*aTolU + aTolV*aTolV); + myTolerance *= (aNewTol2d / aTol2d); if(IsTrimmed[0] || IsTrimmed[1]) { // Treatment only for surface of revolution @@ -594,6 +721,16 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) aRes->FirstParameter(), aRes->LastParameter(), FirstPar, LastPar, NewCurve2d); aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d); + if(Continuity == GeomAbs_C0) + { + // try to smoother the Curve GeomAbs_C1. + Standard_Integer aDeg = aRes->Degree(); + Standard_Boolean OK = Standard_True; + Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d); + for (Standard_Integer ij = 2; ij < aRes->NbKnots(); ij++) { + OK = OK && aRes->RemoveKnot(ij, aDeg-1, aSmoothTol); + } + } } myResult.SetBSpline(aRes); @@ -606,26 +743,64 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) if ( !myResult.IsDone() && isAnalyticalSurf) { // Use advanced analytical projector if base analytical projection failed. - ProjLib_ComputeApprox Comp( myCurve, mySurface, myTolerance); + ProjLib_ComputeApprox Comp; + Comp.SetTolerance(myTolerance); + Comp.SetDegree(myDegMin, myDegMax); + Comp.SetMaxSegments(myMaxSegments); + Comp.SetBndPnt(myBndPnt); + Comp.Perform(myCurve, mySurface); if (Comp.Bezier().IsNull() && Comp.BSpline().IsNull()) return; // advanced projector has been failed too myResult.Done(); - - // set the type - if ( SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve) + Handle(Geom2d_BSplineCurve) aRes; + if (Comp.BSpline().IsNull()) { - myResult.SetType(GeomAbs_BezierCurve); - myResult.SetBezier(Comp.Bezier()) ; + aRes = Geom2dConvert::CurveToBSplineCurve(Comp.Bezier()); } else { + aRes = Comp.BSpline(); + } + if ((IsTrimmed[0] || IsTrimmed[1])) + { + if (IsTrimmed[0]) + { + //Add segment before start of curve + Standard_Real f = myCurve->FirstParameter(); + ExtendC2d(aRes, f, -dt, U1, U2, V1, V2, 0, SingularCase[0]); + } + if (IsTrimmed[1]) + { + //Add segment after end of curve + Standard_Real l = myCurve->LastParameter(); + ExtendC2d(aRes, l, dt, U1, U2, V1, V2, 1, SingularCase[1]); + } + Handle(Geom2d_Curve) NewCurve2d; + GeomLib::SameRange(Precision::PConfusion(), aRes, + aRes->FirstParameter(), aRes->LastParameter(), + FirstPar, LastPar, NewCurve2d); + aRes = Handle(Geom2d_BSplineCurve)::DownCast(NewCurve2d); + myResult.SetBSpline(aRes); myResult.SetType(GeomAbs_BSplineCurve); - myResult.SetBSpline(Comp.BSpline()) ; + } + else + { + // set the type + if (SType == GeomAbs_Plane && CType == GeomAbs_BezierCurve) + { + myResult.SetType(GeomAbs_BezierCurve); + myResult.SetBezier(Comp.Bezier()); + } + else + { + myResult.SetType(GeomAbs_BSplineCurve); + myResult.SetBSpline(Comp.BSpline()); + } } // set the periodicity flag if (SType == GeomAbs_Plane && - CType == GeomAbs_BSplineCurve && - myCurve->IsPeriodic() ) + CType == GeomAbs_BSplineCurve && + myCurve->IsPeriodic()) { myResult.SetPeriodic(); } @@ -723,6 +898,42 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) } } +//======================================================================= +//function : SetDegree +//purpose : +//======================================================================= +void ProjLib_ProjectedCurve::SetDegree(const Standard_Integer theDegMin, + const Standard_Integer theDegMax) +{ + myDegMin = theDegMin; + myDegMax = theDegMax; +} +//======================================================================= +//function : SetMaxSegments +//purpose : +//======================================================================= +void ProjLib_ProjectedCurve::SetMaxSegments(const Standard_Integer theMaxSegments) +{ + myMaxSegments = theMaxSegments; +} + +//======================================================================= +//function : SetBndPnt +//purpose : +//======================================================================= +void ProjLib_ProjectedCurve::SetBndPnt(const AppParCurves_Constraint theBndPnt) +{ + myBndPnt = theBndPnt; +} + +//======================================================================= +//function : SetMaxDist +//purpose : +//======================================================================= +void ProjLib_ProjectedCurve::SetMaxDist(const Standard_Real theMaxDist) +{ + myMaxDist = theMaxDist; +} //======================================================================= //function : GetSurface diff --git a/src/ProjLib/ProjLib_ProjectedCurve.hxx b/src/ProjLib/ProjLib_ProjectedCurve.hxx index 0e3196d430..c788587cd3 100644 --- a/src/ProjLib/ProjLib_ProjectedCurve.hxx +++ b/src/ProjLib/ProjLib_ProjectedCurve.hxx @@ -29,6 +29,7 @@ #include #include #include +#include class Adaptor3d_HSurface; class Adaptor3d_HCurve; class Standard_OutOfRange; @@ -49,20 +50,32 @@ class Geom2d_BSplineCurve; //! Compute the 2d-curve. Try to solve the particular //! case if possible. Otherwize, an approximation is -//! done. +//! done. For approximation some parameters are used, including +//! required tolerance of approximation. +//! Tolerance is maximal possible value of 3d deviation of 3d projection of projected curve from +//! "exact" 3d projection. Since algorithm searches 2d curve on surface, required 2d tolerance is computed +//! from 3d tolerance with help of U,V resolutions of surface. +//! 3d and 2d tolerances have sence only for curves on surface, it defines precision of projecting and approximation +//! and have nothing to do with distance between the projected curve and the surface. class ProjLib_ProjectedCurve : public Adaptor2d_Curve2d { public: DEFINE_STANDARD_ALLOC - + //! Empty constructor, it only sets some initial values for class fields. Standard_EXPORT ProjLib_ProjectedCurve(); + //! Constructor with initialisation field mySurface Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S); - + + //! Constructor, which performs projecting. + //! If projecting uses approximation, default parameters are used, in particular, 3d tolerance of approximation + //! is Precision::Confusion() Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C); + //! Constructor, which performs projecting. + //! If projecting uses approximation, 3d tolerance is Tol, default parameters are used, Standard_EXPORT ProjLib_ProjectedCurve(const Handle(Adaptor3d_HSurface)& S, const Handle(Adaptor3d_HCurve)& C, const Standard_Real Tol); //! Changes the tolerance used to project @@ -72,9 +85,33 @@ public: //! Changes the Surface. Standard_EXPORT void Load (const Handle(Adaptor3d_HSurface)& S); - //! Changes the Curve. - Standard_EXPORT void Load (const Handle(Adaptor3d_HCurve)& C); + //! Performs projecting for given curve. + //! If projecting uses approximation, + //! approximation parameters can be set before by corresponding methods + //! SetDegree(...), SetMaxSegmets(...), SetBndPnt(...), SetMaxDist(...) + Standard_EXPORT void Perform (const Handle(Adaptor3d_HCurve)& C); + //! Set min and max possible degree of result BSpline curve2d, which is got by approximation. + //! If theDegMin/Max < 0, algorithm uses values that are chosen depending of types curve 3d + //! and surface. + Standard_EXPORT void SetDegree(const Standard_Integer theDegMin, const Standard_Integer theDegMax); + + //! Set the parameter, which defines maximal value of parametric intervals the projected + //! curve can be cut for approximation. If theMaxSegments < 0, algorithm uses default + //! value = 1000. + Standard_EXPORT void SetMaxSegments(const Standard_Integer theMaxSegments); + + //! Set the parameter, which defines type of boundary condition between segments during approximation. + //! It can be AppParCurves_PassPoint or AppParCurves_TangencyPoint. + //! Default value is AppParCurves_TangencyPoint; + Standard_EXPORT void SetBndPnt(const AppParCurves_Constraint theBndPnt); + + //! Set the parameter, which degines maximal possible distance between projected curve and surface. + //! It uses only for projecting on not analytical surfaces. + //! If theMaxDist < 0, algoritm uses default value 100.*Tolerance. + //! If real distance between curve and surface more then theMaxDist, algorithm stops working. + Standard_EXPORT void SetMaxDist(const Standard_Real theMaxDist); + Standard_EXPORT const Handle(Adaptor3d_HSurface)& GetSurface() const; Standard_EXPORT const Handle(Adaptor3d_HCurve)& GetCurve() const; @@ -203,8 +240,11 @@ private: Handle(Adaptor3d_HSurface) mySurface; Handle(Adaptor3d_HCurve) myCurve; ProjLib_Projector myResult; - - + Standard_Integer myDegMin; + Standard_Integer myDegMax; + Standard_Integer myMaxSegments; + Standard_Real myMaxDist; + AppParCurves_Constraint myBndPnt; };