From f04de1335ce21a0a880f828a496d755427cfcf54 Mon Sep 17 00:00:00 2001 From: aml Date: Fri, 13 Sep 2019 11:47:17 +0300 Subject: [PATCH] 0030932: Modeling Algorithms - Invalid result on 2d curve on surface approximation New method generating 3D curve is added when 2D curve is linear isoline. --- src/Approx/Approx_CurveOnSurface.cxx | 266 ++++++++++++++++-- src/Approx/Approx_CurveOnSurface.hxx | 69 ++++- src/BRepAlgo/BRepAlgo_NormalProjection.cxx | 5 +- src/BRepFill/BRepFill_Sweep.cxx | 5 +- src/Draft/Draft_Modification_1.cxx | 5 +- src/GeomInt/GeomInt_IntSS_1.cxx | 5 +- src/GeomPlate/GeomPlate_BuildPlateSurface.cxx | 7 +- src/GeomProjLib/GeomProjLib.cxx | 4 +- .../GeometryTest_CurveCommands.cxx | 5 +- .../GeomliteTest_CurveCommands.cxx | 5 +- src/ProjLib/ProjLib_ProjectedCurve.cxx | 5 +- tests/bugs/moddata_3/bug30932 | 20 ++ 12 files changed, 347 insertions(+), 54 deletions(-) create mode 100644 tests/bugs/moddata_3/bug30932 diff --git a/src/Approx/Approx_CurveOnSurface.cxx b/src/Approx/Approx_CurveOnSurface.cxx index 0c4fae4751..9bc11d4d5f 100644 --- a/src/Approx/Approx_CurveOnSurface.cxx +++ b/src/Approx/Approx_CurveOnSurface.cxx @@ -27,8 +27,10 @@ #include #include #include +#include #include #include +#include #include #include #include @@ -300,6 +302,10 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, } } +//============================================================================= +//function : Approx_CurveOnSurface +//purpose : Constructor +//============================================================================= Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D, const Handle(Adaptor3d_HSurface)& Surf, const Standard_Real First, @@ -310,14 +316,75 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, const Standard_Integer MaxSegments, const Standard_Boolean only3d, const Standard_Boolean only2d) +: myC2D(C2D), + mySurf(Surf), + myFirst(First), + myLast(Last), + myTol(Tol), + myIsDone(Standard_False), + myHasResult(Standard_False), + myError3d(0.0), + myError2dU(0.0), + myError2dV(0.0) + { + Perform(MaxSegments, MaxDegree, S, only3d, only2d); + } + +//============================================================================= +//function : Approx_CurveOnSurface +//purpose : Constructor +//============================================================================= + Approx_CurveOnSurface::Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& theC2D, + const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Real theTol) +: myC2D(theC2D), + mySurf(theSurf), + myFirst(theFirst), + myLast(theLast), + myTol(theTol), + myIsDone(Standard_False), + myHasResult(Standard_False), + myError3d(0.0), + myError2dU(0.0), + myError2dV(0.0) +{ +} + +//============================================================================= +//function : Perform +//purpose : +//============================================================================= +void Approx_CurveOnSurface::Perform(const Standard_Integer theMaxSegments, + const Standard_Integer theMaxDegree, + const GeomAbs_Shape theContinuity, + const Standard_Boolean theOnly3d, + const Standard_Boolean theOnly2d) { myIsDone = Standard_False; - if(only3d && only2d) throw Standard_ConstructionError(); - GeomAbs_Shape Order = S; + myHasResult = Standard_False; + myError2dU = 0.0; + myError2dV = 0.0; + myError3d = 0.0; - Handle( Adaptor2d_HCurve2d ) TrimmedC2D = C2D->Trim( First, Last, Precision::PConfusion() ); + if(theOnly3d && theOnly2d) throw Standard_ConstructionError(); - Adaptor3d_CurveOnSurface COnS( TrimmedC2D, Surf ); + Handle( Adaptor2d_HCurve2d ) TrimmedC2D = myC2D->Trim( myFirst, myLast, Precision::PConfusion() ); + + Standard_Boolean isU, isForward; + Standard_Real aParam; + if (theOnly3d && isIsoLine(TrimmedC2D, isU, aParam, isForward)) + { + if (buildC3dOnIsoLine(TrimmedC2D, isU, aParam, isForward)) + { + myIsDone = Standard_True; + myHasResult = Standard_True; + return; + } + } + + Adaptor3d_CurveOnSurface COnS( TrimmedC2D, mySurf ); Handle(Adaptor3d_HCurveOnSurface) HCOnS = new Adaptor3d_HCurveOnSurface(); HCOnS->Set(COnS); @@ -327,37 +394,34 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, Handle(TColStd_HArray1OfReal) ThreeDTol; // create evaluators and choose appropriate one - Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, First, Last); - Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, First, Last); - Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, First, Last); + Approx_CurveOnSurface_Eval3d Eval3dCvOnSurf (HCOnS, myFirst, myLast); + Approx_CurveOnSurface_Eval2d Eval2dCvOnSurf ( TrimmedC2D, myFirst, myLast); + Approx_CurveOnSurface_Eval EvalCvOnSurf (HCOnS, TrimmedC2D, myFirst, myLast); AdvApprox_EvaluatorFunction* EvalPtr; - if ( only3d ) EvalPtr = &Eval3dCvOnSurf; - else if ( only2d ) EvalPtr = &Eval2dCvOnSurf; + if ( theOnly3d ) EvalPtr = &Eval3dCvOnSurf; + else if ( theOnly2d ) EvalPtr = &Eval2dCvOnSurf; else EvalPtr = &EvalCvOnSurf; // Initialization for 2d approximation - if(!only3d) { + if(!theOnly3d) { Num1DSS = 2; OneDTol = new TColStd_HArray1OfReal(1,Num1DSS); Standard_Real TolU, TolV; - TolU = Surf->UResolution(Tol)/2; - TolV = Surf->VResolution(Tol)/2; + TolU = mySurf->UResolution(myTol)/2; + TolV = mySurf->VResolution(myTol)/2; OneDTol->SetValue(1,TolU); OneDTol->SetValue(2,TolV); } - if(!only2d) { + if(!theOnly2d) { Num3DSS=1; ThreeDTol = new TColStd_HArray1OfReal(1,Num3DSS); - ThreeDTol->Init(Tol/2); + ThreeDTol->Init(myTol/2); } - myError2dU = 0; - myError2dV = 0; - myError3d = 0; Standard_Integer NbInterv_C2 = HCOnS->NbIntervals(GeomAbs_C2); TColStd_Array1OfReal CutPnts_C2(1, NbInterv_C2 + 1); @@ -369,8 +433,8 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, AdvApprox_PrefAndRec CutTool(CutPnts_C2,CutPnts_C3); AdvApprox_ApproxAFunction aApprox (Num1DSS, Num2DSS, Num3DSS, OneDTol, TwoDTolNul, ThreeDTol, - First, Last, Order, - MaxDegree, MaxSegments, + myFirst, myLast, theContinuity, + theMaxDegree, theMaxSegments, *EvalPtr, CutTool); myIsDone = aApprox.IsDone(); @@ -381,14 +445,14 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, Handle(TColStd_HArray1OfInteger) Mults = aApprox.Multiplicities(); Standard_Integer Degree = aApprox.Degree(); - if(!only2d) + if(!theOnly2d) { TColgp_Array1OfPnt Poles(1,aApprox.NbPoles()); aApprox.Poles(1,Poles); myCurve3d = new Geom_BSplineCurve(Poles, Knots->Array1(), Mults->Array1(), Degree); myError3d = aApprox.MaxError(3, 1); } - if(!only3d) + if(!theOnly3d) { TColgp_Array1OfPnt2d Poles2d(1,aApprox.NbPoles()); TColStd_Array1OfReal Poles1dU(1,aApprox.NbPoles()); @@ -404,8 +468,6 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, } } -// } - } Standard_Boolean Approx_CurveOnSurface::IsDone() const @@ -443,3 +505,161 @@ void Approx_CurveOnSurface_Eval2d::Evaluate (Standard_Integer *Dimension, return myError2dV; } +//============================================================================= +//function : isIsoLine +//purpose : +//============================================================================= +Standard_Boolean Approx_CurveOnSurface::isIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D, + Standard_Boolean& theIsU, + Standard_Real& theParam, + Standard_Boolean& theIsForward) const +{ + // These variables are used to check line state (vertical or horizontal). + Standard_Boolean isAppropriateType = Standard_False; + gp_Pnt2d aLoc2d; + gp_Dir2d aDir2d; + + // Test type. + const GeomAbs_CurveType aType = theC2D->GetType(); + if (aType == GeomAbs_Line) + { + gp_Lin2d aLin2d = theC2D->Line(); + aLoc2d = aLin2d.Location(); + aDir2d = aLin2d.Direction(); + isAppropriateType = Standard_True; + } + else if (aType == GeomAbs_BSplineCurve) + { + Handle(Geom2d_BSplineCurve) aBSpline2d = theC2D->BSpline(); + if (aBSpline2d->Degree() != 1 || aBSpline2d->NbPoles() != 2) + return Standard_False; // Not a line or uneven parameterization. + + aLoc2d = aBSpline2d->Pole(1); + + // Vector should be non-degenerated. + gp_Vec2d aVec2d(aBSpline2d->Pole(1), aBSpline2d->Pole(2)); + if (aVec2d.SquareMagnitude() < Precision::Confusion()) + return Standard_False; // Degenerated spline. + aDir2d = aVec2d; + + isAppropriateType = Standard_True; + } + else if (aType == GeomAbs_BezierCurve) + { + Handle(Geom2d_BezierCurve) aBezier2d = theC2D->Bezier(); + if (aBezier2d->Degree() != 1 || aBezier2d->NbPoles() != 2) + return Standard_False; // Not a line or uneven parameterization. + + aLoc2d = aBezier2d->Pole(1); + + // Vector should be non-degenerated. + gp_Vec2d aVec2d(aBezier2d->Pole(1), aBezier2d->Pole(2)); + if (aVec2d.SquareMagnitude() < Precision::Confusion()) + return Standard_False; // Degenerated spline. + aDir2d = aVec2d; + + isAppropriateType = Standard_True; + } + + if (!isAppropriateType) + return Standard_False; + + // Check line to be vertical or horizontal. + if (aDir2d.IsParallel(gp::DX2d(), Precision::Angular())) + { + // Horizontal line. V = const. + theIsU = Standard_False; + theParam = aLoc2d.Y(); + theIsForward = aDir2d.Dot(gp::DX2d()) > 0.0; + return Standard_True; + } + else if (aDir2d.IsParallel(gp::DY2d(), Precision::Angular())) + { + // Vertical line. U = const. + theIsU = Standard_True; + theParam = aLoc2d.X(); + theIsForward = aDir2d.Dot(gp::DY2d()) > 0.0; + return Standard_True; + } + + return Standard_False; +} + +#include + +//============================================================================= +//function : buildC3dOnIsoLine +//purpose : +//============================================================================= +Standard_Boolean Approx_CurveOnSurface::buildC3dOnIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D, + const Standard_Boolean theIsU, + const Standard_Real theParam, + const Standard_Boolean theIsForward) +{ + // Convert adapter to the appropriate type. + Handle(GeomAdaptor_HSurface) aGeomAdapter = Handle(GeomAdaptor_HSurface)::DownCast(mySurf); + if (aGeomAdapter.IsNull()) + return Standard_False; + + if (mySurf->GetType() == GeomAbs_Sphere) + return Standard_False; + + // Extract isoline + Handle(Geom_Surface) aSurf = aGeomAdapter->ChangeSurface().Surface(); + Handle(Geom_Curve) aC3d; + + gp_Pnt2d aF2d = theC2D->Value(theC2D->FirstParameter()); + gp_Pnt2d aL2d = theC2D->Value(theC2D->LastParameter()); + + if (theIsU) + { + aC3d = aSurf->UIso(theParam); + aC3d = new Geom_TrimmedCurve(aC3d, aF2d.Y(), aL2d.Y()); + } + else + { + aC3d = aSurf->VIso(theParam); + aC3d = new Geom_TrimmedCurve(aC3d, aF2d.X(), aL2d.X()); + } + + // Convert arbitrary curve type to the b-spline. + myCurve3d = GeomConvert::CurveToBSplineCurve(aC3d, Convert_QuasiAngular); + if (!theIsForward) + myCurve3d->Reverse(); + + // Rebuild parameterization for the 3d curve to have the same parameterization with + // a two-dimensional curve. + TColStd_Array1OfReal aKnots = myCurve3d->Knots(); + BSplCLib::Reparametrize(theC2D->FirstParameter(), theC2D->LastParameter(), aKnots); + myCurve3d->SetKnots(aKnots); + + // Evaluate error. + myError3d = 0.0; + + const Standard_Real aParF = myFirst; + const Standard_Real aParL = myLast; + const Standard_Integer aNbPnt = 23; + for(Standard_Integer anIdx = 0; anIdx <= aNbPnt; ++anIdx) + { + const Standard_Real aPar = aParF + ((aParL - aParF) * anIdx) / aNbPnt; + + const gp_Pnt2d aPnt2d = theC2D->Value(aPar); + + const gp_Pnt aPntC3D = myCurve3d->Value(aPar); + const gp_Pnt aPntC2D = mySurf->Value(aPnt2d.X(), aPnt2d.Y()); + + const Standard_Real aSqDeviation = aPntC3D.SquareDistance(aPntC2D); + myError3d = Max(aSqDeviation, myError3d); + } + + myError3d = Sqrt(myError3d); + + // Target tolerance is not obtained. This situation happens for isolines on the sphere. + // OCCT is unable to convert it keeping original parameterization, while the geometric + // form of the result is entirely identical. In that case, it is better to utilize + // a general-purpose approach. + if (myError3d > myTol) + return Standard_False; + + return Standard_True; +} diff --git a/src/Approx/Approx_CurveOnSurface.hxx b/src/Approx/Approx_CurveOnSurface.hxx index ce5cf4be86..b14b41cbf6 100644 --- a/src/Approx/Approx_CurveOnSurface.hxx +++ b/src/Approx/Approx_CurveOnSurface.hxx @@ -40,9 +40,22 @@ public: DEFINE_STANDARD_ALLOC - + //! This constructor calls perform method. This constructor is deprecated. + Standard_DEPRECATED("This constructor is deprecated. Use other constructor and perform method instead.") Standard_EXPORT Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& C2D, const Handle(Adaptor3d_HSurface)& Surf, const Standard_Real First, const Standard_Real Last, const Standard_Real Tol, const GeomAbs_Shape Continuity, const Standard_Integer MaxDegree, const Standard_Integer MaxSegments, const Standard_Boolean Only3d = Standard_False, const Standard_Boolean Only2d = Standard_False); - + + //! This constructor does not call perform method. + //! @param theC2D 2D Curve to be approximated in 3D. + //! @param theSurf Surface where 2D curve is located. + //! @param theFirst First parameter of resulting curve. + //! @param theFirst Last parameter of resulting curve. + //! @param theTol Computation tolerance. + Standard_EXPORT Approx_CurveOnSurface(const Handle(Adaptor2d_HCurve2d)& theC2D, + const Handle(Adaptor3d_HSurface)& theSurf, + const Standard_Real theFirst, + const Standard_Real theLast, + const Standard_Real theTol); + Standard_EXPORT Standard_Boolean IsDone() const; Standard_EXPORT Standard_Boolean HasResult() const; @@ -59,18 +72,64 @@ public: //! 2d Curve Standard_EXPORT Standard_Real MaxError2dV() const; - - + //! Constructs the 3d curve. Input parameters are ignored when the input curve is + //! U-isoline or V-isoline. + //! @param theMaxSegments Maximal number of segments in the resulting spline. + //! @param theMaxDegree Maximal degree of the result. + //! @param theContinuity Resulting continuity. + //! @param theOnly3d Determines building only 3D curve. + //! @param theOnly2d Determines building only 2D curve. + Standard_EXPORT void Perform(const Standard_Integer theMaxSegments, + const Standard_Integer theMaxDegree, + const GeomAbs_Shape theContinuity, + const Standard_Boolean theOnly3d = Standard_False, + const Standard_Boolean theOnly2d = Standard_False); protected: + //! Checks whether the 2d curve is a isoline. It can be represented by b-spline, bezier, + //! or geometric line. This line should have natural parameterization. + //! @param theC2D Trimmed curve to be checked. + //! @param theIsU Flag indicating that line is u const. + //! @param theParam Line parameter. + //! @param theIsForward Flag indicating forward parameterization on a isoline. + //! @return Standard_True when 2d curve is a line and Standard_False otherwise. + Standard_Boolean isIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D, + Standard_Boolean& theIsU, + Standard_Real& theParam, + Standard_Boolean& theIsForward) const; + //! Builds 3D curve for a isoline. This method takes corresponding isoline from + //! the input surface. + //! @param theC2D Trimmed curve to be approximated. + //! @param theIsU Flag indicating that line is u const. + //! @param theParam Line parameter. + //! @param theIsForward Flag indicating forward parameterization on a isoline. + //! @return Standard_True when 3d curve is built and Standard_False otherwise. + Standard_Boolean buildC3dOnIsoLine(const Handle(Adaptor2d_HCurve2d) theC2D, + const Standard_Boolean theIsU, + const Standard_Real theParam, + const Standard_Boolean theIsForward); - +private: + Approx_CurveOnSurface& operator= (const Approx_CurveOnSurface&); private: + //! Input curve. + const Handle(Adaptor2d_HCurve2d) myC2D; + //! Input surface. + const Handle(Adaptor3d_HSurface) mySurf; + + //! First parameter of the result. + const Standard_Real myFirst; + + //! Last parameter of the result. + const Standard_Real myLast; + + //! Tolerance. + Standard_Real myTol; Handle(Geom2d_BSplineCurve) myCurve2d; Handle(Geom_BSplineCurve) myCurve3d; diff --git a/src/BRepAlgo/BRepAlgo_NormalProjection.cxx b/src/BRepAlgo/BRepAlgo_NormalProjection.cxx index 69cf2921c7..2899cf674f 100644 --- a/src/BRepAlgo/BRepAlgo_NormalProjection.cxx +++ b/src/BRepAlgo/BRepAlgo_NormalProjection.cxx @@ -363,9 +363,8 @@ void BRepAlgo_NormalProjection::SetDefaultParams() #ifdef OCCT_DEBUG_CHRONO InitChron(chr_approx); #endif - Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d, - myContinuity, myMaxDegree, myMaxSeg, - Only3d, Only2d); + Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d); + appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d); #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_approx,t_approx); approx_count++; diff --git a/src/BRepFill/BRepFill_Sweep.cxx b/src/BRepFill/BRepFill_Sweep.cxx index 1f2553be9b..0169c813f9 100644 --- a/src/BRepFill/BRepFill_Sweep.cxx +++ b/src/BRepFill/BRepFill_Sweep.cxx @@ -330,8 +330,9 @@ static Standard_Boolean SameParameter(TopoDS_Edge& E, if (!HasPCurves(E)) { Handle(Geom2dAdaptor_HCurve) HC2d = new Geom2dAdaptor_HCurve( Pcurv ); - Approx_CurveOnSurface AppCurve(HC2d, S, HC2d->FirstParameter(), HC2d->LastParameter(), - Precision::Confusion(), GeomAbs_C1, 10, 10, Standard_True); + Approx_CurveOnSurface AppCurve(HC2d, S, HC2d->FirstParameter(), HC2d->LastParameter(), + Precision::Confusion()); + AppCurve.Perform(10, 10, GeomAbs_C1, Standard_True); if (AppCurve.IsDone() && AppCurve.HasResult()) { C3d = AppCurve.Curve3d(); diff --git a/src/Draft/Draft_Modification_1.cxx b/src/Draft/Draft_Modification_1.cxx index 27ec1793a6..d31e0c8869 100644 --- a/src/Draft/Draft_Modification_1.cxx +++ b/src/Draft/Draft_Modification_1.cxx @@ -2169,9 +2169,8 @@ static Standard_Real SmartParameter(Draft_EdgeInfo& Einf, Standard_Real Udeb, Ufin; ProjCurve.Bounds(1, Udeb, Ufin); Standard_Integer MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3); - Approx_CurveOnSurface appr( HProjector, hsur2, Udeb, Ufin, Tol, - GeomAbs_C1, 10, MaxSeg, - Standard_False, Standard_False ); + Approx_CurveOnSurface appr(HProjector, hsur2, Udeb, Ufin, Tol); + appr.Perform(MaxSeg, 10, GeomAbs_C1, Standard_False, Standard_False); Einf.ChangeSecondPC() = appr.Curve2d(); Einf.ChangeGeometry() = appr.Curve3d(); Einf.SetNewGeometry( Standard_True ); diff --git a/src/GeomInt/GeomInt_IntSS_1.cxx b/src/GeomInt/GeomInt_IntSS_1.cxx index 5cac732ca3..12a1dbc2d1 100644 --- a/src/GeomInt/GeomInt_IntSS_1.cxx +++ b/src/GeomInt/GeomInt_IntSS_1.cxx @@ -1031,9 +1031,8 @@ void GeomInt_IntSS::TreatRLine(const Handle(IntPatch_RLine)& theRL, //approximation of curve on surface. Standard_Integer aMaxDeg = 8; Standard_Integer aMaxSeg = 1000; - Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion(), - GeomAbs_C1, aMaxDeg, aMaxSeg, - Standard_True, Standard_False); + Approx_CurveOnSurface anApp(anAHC2d, aGAHS, tf, tl, Precision::Confusion()); + anApp.Perform(aMaxSeg, aMaxDeg, GeomAbs_C1, Standard_True, Standard_False); if(!anApp.HasResult()) return; diff --git a/src/GeomPlate/GeomPlate_BuildPlateSurface.cxx b/src/GeomPlate/GeomPlate_BuildPlateSurface.cxx index 4db59a6cf5..6d730ef132 100644 --- a/src/GeomPlate/GeomPlate_BuildPlateSurface.cxx +++ b/src/GeomPlate/GeomPlate_BuildPlateSurface.cxx @@ -300,10 +300,9 @@ Handle(Geom2d_Curve) GeomPlate_BuildPlateSurface::ProjectCurve(const Handle(Ada Projector.Bounds(1, Udeb, Ufin); MaxSeg = 20 + HProjector->NbIntervals(GeomAbs_C3); - Approx_CurveOnSurface appr(HProjector, hsur, Udeb, Ufin, myTol3d, - Continuity, MaxDegree, MaxSeg, - Standard_False, Standard_True); - + Approx_CurveOnSurface appr(HProjector, hsur, Udeb, Ufin, myTol3d); + appr.Perform(MaxSeg, MaxDegree, Continuity, Standard_False, Standard_True); + Curve2d = appr.Curve2d(); } #if DRAW diff --git a/src/GeomProjLib/GeomProjLib.cxx b/src/GeomProjLib/GeomProjLib.cxx index d8c61cd84a..4dd52f1328 100644 --- a/src/GeomProjLib/GeomProjLib.cxx +++ b/src/GeomProjLib/GeomProjLib.cxx @@ -340,8 +340,8 @@ Handle(Geom_Curve) GeomProjLib::Project( const Handle(Geom_Curve)& C, Standard_Real f,l; Proj.Bounds(1,f,l); Handle(Adaptor2d_HCurve2d) HC2d = Proj.Trim(f,l,TolU); - Approx_CurveOnSurface Approx(HC2d, HS, f, l, Tol, - GeomAbs_C2,14,16,Standard_True); + Approx_CurveOnSurface Approx(HC2d, HS, f, l, Tol); + Approx.Perform(16, 14, GeomAbs_C2, Standard_True); // ici, on a toujours un type BSpline. if (Approx.IsDone() && Approx.HasResult()) diff --git a/src/GeometryTest/GeometryTest_CurveCommands.cxx b/src/GeometryTest/GeometryTest_CurveCommands.cxx index 94175827e8..8feb96c538 100644 --- a/src/GeometryTest/GeometryTest_CurveCommands.cxx +++ b/src/GeometryTest/GeometryTest_CurveCommands.cxx @@ -367,9 +367,8 @@ static Standard_Integer gproject(Draw_Interpretor& di, Standard_Integer n, const return 0; } else { - Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d, - myContinuity, myMaxDegree, myMaxSeg, - Only3d, Only2d); + Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d); + appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d); if(!Only3d) { PCur2d = appr.Curve2d(); di << " Error in 2d is " << appr.MaxError2dU() diff --git a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx index a9e411f08c..74a90ba054 100644 --- a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx +++ b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx @@ -1552,9 +1552,8 @@ static Standard_Integer approxcurveonsurf(Draw_Interpretor& di, Standard_Integer Handle(Geom2dAdaptor_HCurve) A2d = new (Geom2dAdaptor_HCurve)(curve2d); Handle(GeomAdaptor_HSurface) AS = new (GeomAdaptor_HSurface)(Surf); - Approx_CurveOnSurface App(A2d, AS, A2d->FirstParameter(), A2d->LastParameter(), - Tol, Continuity, MaxDeg, MaxSeg, - Standard_True, Standard_False); + Approx_CurveOnSurface App(A2d, AS, A2d->FirstParameter(), A2d->LastParameter(), Tol); + App.Perform(MaxSeg, MaxDeg, Continuity, Standard_True, Standard_False); if(App.HasResult()) { Handle(Geom_BSplineCurve) BSCurve = App.Curve3d(); diff --git a/src/ProjLib/ProjLib_ProjectedCurve.cxx b/src/ProjLib/ProjLib_ProjectedCurve.cxx index 136c1cf94f..2d5b2a869c 100644 --- a/src/ProjLib/ProjLib_ProjectedCurve.cxx +++ b/src/ProjLib/ProjLib_ProjectedCurve.cxx @@ -685,9 +685,8 @@ void ProjLib_ProjectedCurve::Perform(const Handle(Adaptor3d_HCurve)& C) MaxSeg = myMaxSegments; } - Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, - myTolerance, Continuity, MaxDegree, MaxSeg, - Only3d, Only2d); + Approx_CurveOnSurface appr(HProjector, mySurface, Udeb, Ufin, myTolerance); + appr.Perform(MaxSeg, MaxDegree, Continuity, Only3d, Only2d); Handle(Geom2d_BSplineCurve) aRes = appr.Curve2d(); diff --git a/tests/bugs/moddata_3/bug30932 b/tests/bugs/moddata_3/bug30932 new file mode 100644 index 0000000000..9e362caa2d --- /dev/null +++ b/tests/bugs/moddata_3/bug30932 @@ -0,0 +1,20 @@ +puts "================" +puts "0030932: Modeling Algorithms - Invalid result on 2d curve on surface approximation" +puts "================" +puts "" + +# Prepare data. +restore [locate_data_file bug30932_c2d] c2d +restore [locate_data_file bug30932_sur] sur + +# Approximate. +approxcurveonsurf res c2d sur + +# Length check. +checklength res -l 150.02782767924231 + +# Visual check. +axo; +don res; +fit; +checkview -screenshot -2d -path ${imagedir}/${test_image}.png