From 1e34ad2459ed7f0c650ea3e18faef5ccf2633dce Mon Sep 17 00:00:00 2001 From: ifv Date: Tue, 26 Sep 2017 16:27:03 +0300 Subject: [PATCH] CEVT-06-001 : Projection algorithm improvement to ensure imprinting of a curve on surface Adaptation for OCCT7.1.0 of commit for CR28909 --- src/Approx/Approx_ComputeCLine.gxx | 26 +- src/Approx/Approx_FitAndDivide.hxx | 4 + src/Approx/Approx_FitAndDivide2d.hxx | 4 + src/BOPTools/BOPTools_AlgoTools2D.cxx | 52 +++- src/BRepFill/BRepFill_ComputeCLine.hxx | 5 +- src/ProjLib/ProjLib.cxx | 70 +++++ src/ProjLib/ProjLib.hxx | 12 +- src/ProjLib/ProjLib_ComputeApprox.cxx | 199 +++++++++--- src/ProjLib/ProjLib_ComputeApprox.hxx | 45 ++- .../ProjLib_ComputeApproxOnPolarSurface.cxx | 287 ++++++++++++------ .../ProjLib_ComputeApproxOnPolarSurface.hxx | 81 ++++- src/ProjLib/ProjLib_ProjectedCurve.cxx | 209 ++++++++++--- src/ProjLib/ProjLib_ProjectedCurve.hxx | 54 +++- 13 files changed, 838 insertions(+), 210 deletions(-) diff --git a/src/Approx/Approx_ComputeCLine.gxx b/src/Approx/Approx_ComputeCLine.gxx index f2fc63c460..9e21aad47b 100644 --- a/src/Approx/Approx_ComputeCLine.gxx +++ b/src/Approx/Approx_ComputeCLine.gxx @@ -50,6 +50,7 @@ Approx_ComputeCLine::Approx_ComputeCLine mycut = cutting; myfirstC = FirstC; mylastC = LastC; + myMaxSegments = IntegerLast(); alldone = Standard_False; Perform(Line); } @@ -76,6 +77,7 @@ Approx_ComputeCLine::Approx_ComputeCLine mycut = cutting; myfirstC = FirstC; mylastC = LastC; + myMaxSegments = IntegerLast(); } //======================================================================= @@ -91,9 +93,11 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) Standard_Real thetol3d = Precision::Confusion(), thetol2d = Precision::Confusion(); UFirst = Line.FirstParameter(); ULast = Line.LastParameter(); - Standard_Real TolU = (ULast-UFirst)*1.e-05; + Standard_Real TolU = Max((ULast-UFirst)*1.e-05, Precision::PApproximation()); Standard_Real myfirstU = UFirst; Standard_Real mylastU = ULast; + Standard_Integer aMaxSegments = 0; + Standard_Integer aMaxSegments1 = myMaxSegments - 1; if (!mycut) { @@ -126,7 +130,8 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) // Calcul de la partie a approximer. myfirstU = mylastU; mylastU = ULast; - if (Abs(ULast-myfirstU) <= RealEpsilon()) + if (Abs(ULast-myfirstU) <= RealEpsilon() + || aMaxSegments >= myMaxSegments) { Finish = Standard_True; alldone = Standard_True; @@ -155,11 +160,15 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) // Calcul des parametres sur ce nouvel intervalle. Ok = Compute(Line, myfirstU, mylastU, thetol3d, thetol2d); + if(Ok) + { + aMaxSegments++; + } //cout << myfirstU << " - " << mylastU << " tol : " << thetol3d << " " << thetol2d << endl; // is new decision better? - if (!Ok && Abs(myfirstU-mylastU) <= TolU) + if (!Ok && (Abs(myfirstU-mylastU) <= TolU || aMaxSegments >= aMaxSegments1)) { Ok = Standard_True; // stop interval cutting, approx the rest part @@ -176,6 +185,7 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) tolreached = Standard_False; // helas myMultiCurves.Append(KeptMultiCurve); + aMaxSegments++; Tolers3d.Append (KeptT3d); Tolers2d.Append (KeptT2d); myfirstparam.Append (KeptUfirst); @@ -303,6 +313,16 @@ void Approx_ComputeCLine::SetConstraints(const AppParCurves_Constraint FirstC, 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; +} + //======================================================================= //function : IsAllApproximated //purpose : returns False if at a moment of the approximation, 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 bdef984b15..ada5cbcca8 100644 --- a/src/BOPTools/BOPTools_AlgoTools2D.cxx +++ b/src/BOPTools/BOPTools_AlgoTools2D.cxx @@ -57,6 +57,7 @@ #include #include #include +#include #include #include #include @@ -64,6 +65,7 @@ #include #include #include +#include static Standard_Boolean CheckEdgeLength (const TopoDS_Edge& ); @@ -626,6 +628,9 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace aBAHS=new GeomAdaptor_HSurface(aGAS); aBAHC=new GeomAdaptor_HCurve(aC3D, aT1, aT2); // + 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 (aGAS.GetType() == GeomAbs_SurfaceOfRevolution) { Standard_Real aTR; @@ -640,27 +645,42 @@ void BOPTools_AlgoTools2D::MakePCurveOnFace aTolR = aProj1.GetTolerance(); } else { - Standard_Real aTR = Precision::Confusion();//1.e-7; - if (TolReached2d > aTR) { - aTR = Min(0.0001, Max(.01 * TolReached2d, aTR)); + ProjLib_ProjectedCurve aProjCurv(aBAHS); + Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1; + Standard_Real aMaxDist = -1; + AppParCurves_Constraint aBndPnt = AppParCurves_NoConstraint; + if ((TolReached2d >= 10. * aTR) && (TolReached2d <= aMaxTol || isAnaSurf)) + { + aTR = Min(aMaxTol, 0.1*TolReached2d); + aMaxSegments = 100; + aMaxDist = 1.e3*TolReached2d; + if (!isAnaSurf) + { + aBndPnt = AppParCurves_PassPoint; + } } - - ProjLib_ProjectedCurve aProjCurv(aBAHS, aBAHC, aTR);// 1 - BOPTools_AlgoTools2D::MakePCurveOfType(aProjCurv, aC2D); + 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 - BOPTools_AlgoTools2D::MakePCurveOfType(aProjCurvAgain, aC2D); + 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 - BOPTools_AlgoTools2D::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 e536aacd8b..36ee34ddbc 100644 --- a/src/ProjLib/ProjLib.cxx +++ b/src/ProjLib/ProjLib.cxx @@ -39,6 +39,16 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //======================================================================= //function : Project @@ -234,3 +244,63 @@ gp_Lin2d ProjLib::Project(const gp_Torus& To, const gp_Circ& Ci) ProjLib_Torus Proj( To, Ci); return Proj.Line(); } + +//======================================================================= +//function : MakePCurveOfType +//purpose : +//======================================================================= +void ProjLib::MakePCurveOfType + (const ProjLib_ProjectedCurve& PC, + Handle(Geom2d_Curve)& C2D) +{ + + switch (PC.GetType()) { + + case GeomAbs_Line : + C2D = new Geom2d_Line(PC.Line()); + break; + case GeomAbs_Circle : + C2D = new Geom2d_Circle(PC.Circle()); + break; + case GeomAbs_Ellipse : + C2D = new Geom2d_Ellipse(PC.Ellipse()); + break; + case GeomAbs_Parabola : + C2D = new Geom2d_Parabola(PC.Parabola()); + break; + case GeomAbs_Hyperbola : + C2D = new Geom2d_Hyperbola(PC.Hyperbola()); + break; + case GeomAbs_BSplineCurve : + C2D = PC.BSpline(); + break; + case GeomAbs_BezierCurve : + case GeomAbs_OtherCurve : + default : + Standard_NotImplemented::Raise + ("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 a06c3dfde4..f533479643 100644 --- a/src/ProjLib/ProjLib.hxx +++ b/src/ProjLib/ProjLib.hxx @@ -20,6 +20,7 @@ #include #include #include +#include class gp_Pnt2d; class gp_Pln; @@ -54,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 @@ -128,6 +129,15 @@ public: Standard_EXPORT static gp_Lin2d Project (const gp_Torus& To, const gp_Circ& Ci); + //! 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 b93d33784c..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 @@ -42,6 +43,7 @@ #include #include #include +#include //#define DRAW #ifdef DRAW @@ -115,7 +117,7 @@ static gp_Pnt2d Function_Value(const Standard_Real U, break; } default: - Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value"); + throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value"); } if ( UCouture) { @@ -195,7 +197,33 @@ static Standard_Boolean Function_D1( const Standard_Real U, return Standard_True; } +//======================================================================= +//function : Function_ComputeStep +//purpose : +//======================================================================= +static Standard_Real Function_ComputeStep( + const Handle(Adaptor3d_HCurve)& myCurve, + const Standard_Real R) +{ + Standard_Real Step0 = .1; + Standard_Real W1, W2; + W1 = myCurve->FirstParameter(); + W2 = myCurve->LastParameter(); + Standard_Real L = GCPnts_AbscissaPoint::Length(myCurve->Curve()); + Standard_Integer nbp = RealToInt(L / (R*M_PI_4)) + 1; + nbp = Max(nbp, 3); + Standard_Real Step = (W2 - W1) / (nbp - 1); + if (Step > Step0) + { + Step = Step0; + nbp = RealToInt((W2 - W1) / Step) + 1; + nbp = Max(nbp, 3); + Step = (W2 - W1) / (nbp - 1); + } + return Step; + +} //======================================================================= //function : Function_SetUVBounds //purpose : @@ -272,15 +300,21 @@ static void Function_SetUVBounds(Standard_Real& myU1, Standard_Real U1, V1, U , V, Delta = 0., d = 0., pmin = W1, pmax = W1, dmax = 0., Uf, Ul; ElSLib::Parameters( Cone, P1, U1, V1); ElSLib::Parameters( Cone, P2, Ul, V1); - myU1 = U1; myU2 = U1; Uf = U1; - Standard_Real Step = .1; - Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1); - if(myCurve->GetType() == GeomAbs_Line) + const gp_Ax1& anAx1 = Cone.Axis(); + gp_Lin aLin(anAx1); + Standard_Real R = (aLin.Distance(P1) + aLin.Distance(P2) + aLin.Distance(P)) / 3.; + Standard_Real Step; + myU1 = U1; myU2 = U1; Uf = U1; + if (myCurve->GetType() == GeomAbs_Line) + { + Standard_Integer nbp = 3; + Step = (W2 - W1) / (nbp - 1); + } + else { - nbp = 3; + Step = Function_ComputeStep(myCurve, R); } - nbp = Max(nbp, 3); - Step = (W2 - W1) / (nbp - 1); + // Standard_Boolean isclandper = (!(myCurve->IsClosed()) && !(myCurve->IsPeriodic())); Standard_Boolean isFirst = Standard_True; for(Standard_Real par = W1 + Step; par <= W2; par += Step) @@ -402,11 +436,10 @@ static void Function_SetUVBounds(Standard_Real& myU1, else { Standard_Real U1, V1, U , V; ElSLib::Parameters( Cylinder, P1, U1, V1); - Standard_Real Step = .1, Delta = 0.; + Standard_Real R = Cylinder.Radius(); + Standard_Real Delta = 0., Step; Standard_Real eps = M_PI, dmax = 0., d = 0.; - Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1); - nbp = Max(nbp, 3); - Step = (W2 - W1) / (nbp - 1); + Step = Function_ComputeStep(myCurve, R); myU1 = U1; myU2 = U1; Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step; for(Standard_Real par = W1 + Step; par <= plim; par += Step) { @@ -655,11 +688,10 @@ static void Function_SetUVBounds(Standard_Real& myU1, else { Standard_Real U1, V1, U , V; ElSLib::Parameters( SP, P1, U1, V1); - Standard_Real Step = .1, Delta = 0.; + Standard_Real R = SP.Radius(); + Standard_Real Delta = 0., Step; Standard_Real eps = M_PI, dmax = 0., d = 0.; - Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1); - nbp = Max(nbp, 3); - Step = (W2 - W1) / (nbp - 1); + Step = Function_ComputeStep(myCurve, R); myU1 = U1; myU2 = U1; Standard_Real pmin = W1, pmax = W1, plim = W2+.1*Step; for(Standard_Real par = W1 + Step; par <= plim; par += Step) { @@ -710,13 +742,12 @@ static void Function_SetUVBounds(Standard_Real& myU1, // case GeomAbs_Torus:{ gp_Torus TR = mySurface->Torus(); - Standard_Real U1, V1, U , V; + Standard_Real U1, V1, U , V, dU, dV; ElSLib::Parameters( TR, P1, U1, V1); - Standard_Real Step = .1, DeltaU = 0., DeltaV = 0.; - Standard_Real eps = M_PI, dmaxU = 0., dU = 0., dmaxV = 0., dV = 0.; - Standard_Integer nbp = (Standard_Integer)((W2 - W1) / Step + 1); - nbp = Max(nbp, 3); - Step = (W2 - W1) / (nbp - 1); + Standard_Real R = TR.MinorRadius(); + Standard_Real DeltaU = 0., DeltaV = 0., Step; + Standard_Real eps = M_PI, dmaxU = 0., dmaxV = 0.; + Step = Function_ComputeStep(myCurve, R); myU1 = U1; myU2 = U1; myV1 = V1; myV2 = V1; Standard_Real pminU = W1, pmaxU = W1, pminV = W1, pmaxV = W1, @@ -926,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 @@ -935,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) && @@ -1055,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()) { @@ -1085,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); } @@ -1111,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.) @@ -1127,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(); @@ -1183,7 +1264,7 @@ ProjLib_ComputeApprox::ProjLib_ComputeApprox break; } default: - Standard_NoSuchObject::Raise("ProjLib_ComputeApprox::Value"); + throw Standard_NoSuchObject("ProjLib_ComputeApprox::Value"); } Standard_Boolean ToMirror = Standard_False; Standard_Real du = 0., dv = 0.; @@ -1224,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 4b410a518d..14185a3504 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -284,7 +284,7 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, break; } default: - Standard_NoSuchObject::Raise("ProjLib_ComputeApproxOnPolarSurface::Value"); + throw Standard_NoSuchObject("ProjLib_ComputeApproxOnPolarSurface::Value"); } return gp_Pnt2d(S, T); } @@ -363,7 +363,7 @@ static gp_Pnt2d Function_Value(const Standard_Real theU, } else { - Standard_NoSuchObject::Raise(""); + throw Standard_NoSuchObject ("ProjLib_ComputeApproxOnPolarSurface::ProjectUsingInitialCurve2d() - unknown surface type"); } // Try to run simple search with initial point (U0, V0). @@ -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); @@ -885,6 +926,7 @@ Handle(Adaptor2d_HCurve2d) Standard_Integer NbOfPnts = 61; GCPnts_QuasiUniformAbscissa QUA(Curve->GetCurve(),NbOfPnts); + NbOfPnts = QUA.NbPoints(); TColgp_Array1OfPnt Pts(1,NbOfPnts); TColStd_Array1OfReal Param(1,NbOfPnts); Standard_Integer i, j; @@ -1031,7 +1073,7 @@ Handle(Adaptor2d_HCurve2d) break; } default: - Standard_NoSuchObject::Raise("ProjLib_ComputeApproxOnPolarSurface::BuildInitialCurve2d"); + throw Standard_NoSuchObject("ProjLib_ComputeApproxOnPolarSurface::BuildInitialCurve2d"); } } else { @@ -1054,7 +1096,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 +1112,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 +1134,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 +1164,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 +1192,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 +1266,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 +1291,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 +1363,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 +1390,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 +1419,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 +1447,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 +1532,6 @@ Handle(Adaptor2d_HCurve2d) // Modified by Sergey KHROMOV - Thu Apr 18 10:58:02 2002 End } - - - //======================================================================= //function : ProjLib_ProjectUsingInitialCurve2d //purpose : @@ -1501,24 +1540,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 +1582,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 +1615,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 +1631,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 +1660,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 +1671,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 +1713,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 +1731,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 +1760,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 +1771,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 +1803,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 +1842,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 +1880,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 +1937,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 +1960,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 +1989,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 8dd1817065..656e99be76 100644 --- a/src/ProjLib/ProjLib_ProjectedCurve.cxx +++ b/src/ProjLib/ProjLib_ProjectedCurve.cxx @@ -55,6 +55,39 @@ #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 @@ -250,7 +283,7 @@ static void Project(ProjLib_Projector& P, Handle(Adaptor3d_HCurve)& C) case GeomAbs_OtherCurve: // try the approximation break; default: - Standard_NoSuchObject::Raise(" "); + throw Standard_NoSuchObject(" "); } } @@ -259,10 +292,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 +308,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 +326,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 +346,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 +368,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; @@ -431,12 +488,19 @@ void ProjLib_ProjectedCurve::Load(const Handle(Adaptor3d_HCurve)& C) TrimC3d(myCurve, IsTrimmed, dt, Pole, SingularCase, 4); } - 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]) @@ -538,7 +602,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 +632,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 +655,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 +683,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,7 +705,12 @@ 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(); @@ -723,6 +827,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 @@ -786,8 +926,7 @@ Standard_Real ProjLib_ProjectedCurve::LastParameter() const GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const { - Standard_NotImplemented::Raise(""); - return GeomAbs_C0; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Continuity() - method is not implemented"); } @@ -798,8 +937,7 @@ GeomAbs_Shape ProjLib_ProjectedCurve::Continuity() const Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const { - Standard_NotImplemented::Raise(""); - return 0; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::NbIntervals() - method is not implemented"); } @@ -812,7 +950,7 @@ Standard_Integer ProjLib_ProjectedCurve::NbIntervals(const GeomAbs_Shape ) const void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal& , const GeomAbs_Shape ) const { - Standard_NotImplemented::Raise(""); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Intervals() - method is not implemented"); } @@ -823,8 +961,7 @@ void ProjLib_ProjectedCurve::Intervals(TColStd_Array1OfReal& , Standard_Boolean ProjLib_ProjectedCurve::IsClosed() const { - Standard_NotImplemented::Raise(""); - return Standard_True; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::IsClosed() - method is not implemented"); } @@ -846,8 +983,7 @@ Standard_Boolean ProjLib_ProjectedCurve::IsPeriodic() const Standard_Real ProjLib_ProjectedCurve::Period() const { - Standard_NotImplemented::Raise(""); - return 0.; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Period() - method is not implemented"); } @@ -858,8 +994,7 @@ Standard_Real ProjLib_ProjectedCurve::Period() const gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const { - Standard_NotImplemented::Raise(""); - return gp_Pnt2d(0.,0.); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Value() - method is not implemented"); } @@ -870,7 +1005,7 @@ gp_Pnt2d ProjLib_ProjectedCurve::Value(const Standard_Real ) const void ProjLib_ProjectedCurve::D0(const Standard_Real , gp_Pnt2d& ) const { - Standard_NotImplemented::Raise(""); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D0() - method is not implemented"); } @@ -883,7 +1018,7 @@ void ProjLib_ProjectedCurve::D1(const Standard_Real , gp_Pnt2d& , gp_Vec2d& ) const { - Standard_NotImplemented::Raise(""); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D1() - method is not implemented"); } @@ -897,7 +1032,7 @@ void ProjLib_ProjectedCurve::D2(const Standard_Real , gp_Vec2d& , gp_Vec2d& ) const { - Standard_NotImplemented::Raise(""); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D2() - method is not implemented"); } @@ -912,7 +1047,7 @@ void ProjLib_ProjectedCurve::D3(const Standard_Real, gp_Vec2d&, gp_Vec2d&) const { - Standard_NotImplemented::Raise(""); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::D3() - method is not implemented"); } @@ -924,8 +1059,7 @@ void ProjLib_ProjectedCurve::D3(const Standard_Real, gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real, const Standard_Integer) const { - Standard_NotImplemented::Raise(""); - return gp_Vec2d(0.,0.); + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::DN() - method is not implemented"); } @@ -936,8 +1070,7 @@ gp_Vec2d ProjLib_ProjectedCurve::DN(const Standard_Real, Standard_Real ProjLib_ProjectedCurve::Resolution(const Standard_Real) const { - Standard_NotImplemented::Raise(""); - return 0.; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Resolution() - method is not implemented"); } @@ -1117,7 +1250,5 @@ Handle(Adaptor2d_HCurve2d) ProjLib_ProjectedCurve::Trim const Standard_Real , const Standard_Real ) const { - Standard_NotImplemented::Raise(""); - return NULL ; + throw Standard_NotImplemented ("ProjLib_ProjectedCurve::Trim() - method is not implemented"); } - 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; }; -- 2.39.5