diff --git a/src/Approx/Approx_ComputeCLine.gxx b/src/Approx/Approx_ComputeCLine.gxx index d13c01e6e3..c9e7ed838d 100644 --- a/src/Approx/Approx_ComputeCLine.gxx +++ b/src/Approx/Approx_ComputeCLine.gxx @@ -25,6 +25,8 @@ #include #include +const static Standard_Integer MAXSEGM = 1000; + //======================================================================= //function : Approx_ComputeCLine //purpose : The MultiLine will be approximated until tolerances @@ -50,7 +52,8 @@ const AppParCurves_Constraint LastC) mycut = cutting; myfirstC = FirstC; mylastC = LastC; - myMaxSegments = IntegerLast(); + myMaxSegments = MAXSEGM; + myInvOrder = Standard_True; alldone = Standard_False; Perform(Line); } @@ -77,7 +80,8 @@ const AppParCurves_Constraint LastC) mycut = cutting; myfirstC = FirstC; mylastC = LastC; - myMaxSegments = IntegerLast(); + myMaxSegments = MAXSEGM; + myInvOrder = Standard_True; } //======================================================================= @@ -244,33 +248,117 @@ Standard_Boolean Approx_ComputeCLine::Compute(const MultiLine& Line, { - Standard_Integer deg, NbPoints = 24; + const Standard_Integer NbPointsMax = 24; + const Standard_Real aMinRatio = 0.05; + const Standard_Integer aMaxDeg = 8; + // + Standard_Integer deg, NbPoints; Standard_Boolean mydone; Standard_Real Fv; - for (deg = mydegremin; deg <= mydegremax; deg++) { - - AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints); - mydone = LSquare.IsDone(); - if (mydone) { - LSquare.Error(Fv, TheTol3d, TheTol2d); - if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) { + AppParCurves_MultiCurve aPrevCurve; + Standard_Real aPrevTol3d = RealLast(), aPrevTol2d = RealLast(); + Standard_Boolean aPrevIsOk = Standard_False; + Standard_Boolean anInvOrder = myInvOrder; + if (anInvOrder && mydegremax > aMaxDeg) + { + if ((Ulast - Ufirst) / (Line.LastParameter() - Line.FirstParameter()) < aMinRatio) + { + anInvOrder = Standard_False; + } + } + if (anInvOrder) + { + for (deg = mydegremax; deg >= mydegremin; deg--) { + NbPoints = Min(2 * deg + 1, NbPointsMax); + AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints); + mydone = LSquare.IsDone(); + if (mydone) + { + LSquare.Error(Fv, TheTol3d, TheTol2d); + if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) + { + if (deg == mydegremin) + { + // Stockage de la multicurve approximee. + tolreached = Standard_True; + myMultiCurves.Append(LSquare.Value()); + myfirstparam.Append(Ufirst); + mylastparam.Append(Ulast); + Tolers3d.Append(TheTol3d); + Tolers2d.Append(TheTol2d); + return Standard_True; + } + aPrevTol3d = TheTol3d; + aPrevTol2d = TheTol2d; + aPrevCurve = LSquare.Value(); + aPrevIsOk = Standard_True; + continue; + } + else if (aPrevIsOk) + { + // Stockage de la multicurve approximee. + tolreached = Standard_True; + TheTol3d = aPrevTol3d; + TheTol2d = aPrevTol2d; + myMultiCurves.Append(aPrevCurve); + myfirstparam.Append(Ufirst); + mylastparam.Append(Ulast); + Tolers3d.Append(aPrevTol3d); + Tolers2d.Append(aPrevTol2d); + return Standard_True; + } + } + else if (aPrevIsOk) + { // Stockage de la multicurve approximee. tolreached = Standard_True; - myMultiCurves.Append(LSquare.Value()); + TheTol3d = aPrevTol3d; + TheTol2d = aPrevTol2d; + myMultiCurves.Append(aPrevCurve); myfirstparam.Append(Ufirst); mylastparam.Append(Ulast); - Tolers3d.Append(TheTol3d); - Tolers2d.Append(TheTol2d); + Tolers3d.Append(aPrevTol3d); + Tolers2d.Append(aPrevTol2d); return Standard_True; } + if (!aPrevIsOk && deg == mydegremax) + { + TheMultiCurve = LSquare.Value(); + currenttol3d = TheTol3d; + currenttol2d = TheTol2d; + aPrevTol3d = TheTol3d; + aPrevTol2d = TheTol2d; + aPrevCurve = TheMultiCurve; + break; + } } - if (deg == mydegremax) { - TheMultiCurve = LSquare.Value(); - currenttol3d = TheTol3d; - currenttol2d = TheTol2d; + } + else + { + for (deg = mydegremin; deg <= mydegremax; deg++) { + NbPoints = Min(2 * deg + 1, NbPointsMax); + AppCont_LeastSquare LSquare(Line, Ufirst, Ulast, myfirstC, mylastC, deg, NbPoints); + mydone = LSquare.IsDone(); + if (mydone) { + LSquare.Error(Fv, TheTol3d, TheTol2d); + if (TheTol3d <= mytol3d && TheTol2d <= mytol2d) { + // Stockage de la multicurve approximee. + tolreached = Standard_True; + myMultiCurves.Append(LSquare.Value()); + myfirstparam.Append(Ufirst); + mylastparam.Append(Ulast); + Tolers3d.Append(TheTol3d); + Tolers2d.Append(TheTol2d); + return Standard_True; + } + } + if (deg == mydegremax) { + TheMultiCurve = LSquare.Value(); + currenttol3d = TheTol3d; + currenttol2d = TheTol2d; + } } - } return Standard_False; } @@ -335,6 +423,15 @@ void Approx_ComputeCLine::SetMaxSegments(const Standard_Integer theMaxSegments) myMaxSegments = theMaxSegments; } +//======================================================================= +//function : SetInvOrder +//purpose : +//======================================================================= +void Approx_ComputeCLine::SetInvOrder(const Standard_Boolean theInvOrder) +{ + myInvOrder = theInvOrder; +} + //======================================================================= //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 f33f83e243..552af14087 100644 --- a/src/Approx/Approx_FitAndDivide.hxx +++ b/src/Approx/Approx_FitAndDivide.hxx @@ -64,6 +64,12 @@ public: //! Changes the max number of segments, which is allowed for cutting. Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); + //! Set inverse order of degree selection: + //! if theInvOrdr = true, current degree is chosen by inverse order - + //! from maxdegree to mindegree. + //! By default inverse order is used. + Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder); + //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user //! when more points were needed. @@ -118,6 +124,7 @@ private: AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; Standard_Integer myMaxSegments; + Standard_Boolean myInvOrder; }; diff --git a/src/Approx/Approx_FitAndDivide2d.hxx b/src/Approx/Approx_FitAndDivide2d.hxx index 829bd82fcb..c1d4283b3e 100644 --- a/src/Approx/Approx_FitAndDivide2d.hxx +++ b/src/Approx/Approx_FitAndDivide2d.hxx @@ -64,6 +64,12 @@ public: //! Changes the max number of segments, which is allowed for cutting. Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); + //! Set inverse order of degree selection: + //! if theInvOrdr = true, current degree is chosen by inverse order - + //! from maxdegree to mindegree. + //! By default inverse order is used. + Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder); + //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user //! when more points were needed. @@ -118,7 +124,7 @@ private: AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; Standard_Integer myMaxSegments; - + Standard_Boolean myInvOrder; }; diff --git a/src/BRepCheck/BRepCheck_Face.cxx b/src/BRepCheck/BRepCheck_Face.cxx index fd500c5e53..d185feb409 100644 --- a/src/BRepCheck/BRepCheck_Face.cxx +++ b/src/BRepCheck/BRepCheck_Face.cxx @@ -685,7 +685,9 @@ static Standard_Boolean Intersect(const TopoDS_Wire& wir1, for (Standard_Integer j = 1; j <= PntSeq.Length(); j++) { Standard_Real tolv = BRep_Tool::Tolerance( TopoDS::Vertex(CommonVertices(j)) ); - if (P.IsEqual( PntSeq(j), tolv )) + tolv += 1.e-8; //possible tolerance of intersection point + Standard_Real dd = P.SquareDistance(PntSeq(j)); + if (dd <= tolv * tolv) { NbCoinc++; break; diff --git a/src/BRepFill/BRepFill_ComputeCLine.hxx b/src/BRepFill/BRepFill_ComputeCLine.hxx index 5391c41aae..273515069a 100644 --- a/src/BRepFill/BRepFill_ComputeCLine.hxx +++ b/src/BRepFill/BRepFill_ComputeCLine.hxx @@ -64,6 +64,12 @@ public: //! Changes the max number of segments, which is allowed for cutting. Standard_EXPORT void SetMaxSegments (const Standard_Integer theMaxSegments); + //! Set inverse order of degree selection: + //! if theInvOrdr = true, current degree is chosen by inverse order - + //! from maxdegree to mindegree. + //! By default inverse order is used. + Standard_EXPORT void SetInvOrder(const Standard_Boolean theInvOrder); + //! returns False if at a moment of the approximation, //! the status NoApproximation has been sent by the user //! when more points were needed. @@ -118,6 +124,7 @@ private: AppParCurves_Constraint myfirstC; AppParCurves_Constraint mylastC; Standard_Integer myMaxSegments; + Standard_Boolean myInvOrder; }; diff --git a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx index 1ab9716ece..aa332b7c1c 100644 --- a/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx +++ b/src/BRepTopAdaptor/BRepTopAdaptor_FClass2d.cxx @@ -105,6 +105,8 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const Umin = Vmin = 0.0; //RealLast(); Umax = Vmax = -Umin; + Standard_Integer aNbE = 0; + Standard_Real eps = 1.e-10; Standard_Integer BadWire=0; for( FaceExplorer.Init(Face,TopAbs_WIRE); (FaceExplorer.More() && BadWire==0); FaceExplorer.Next() ) { @@ -118,6 +120,7 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const TopExp_Explorer Explorer; for( Explorer.Init(FaceExplorer.Current(),TopAbs_EDGE); Explorer.More(); Explorer.Next() ) NbEdges++; + aNbE = NbEdges; gp_Pnt Ancienpnt3d(0,0,0); Standard_Boolean Ancienpnt3dinitialise = Standard_False; @@ -394,6 +397,15 @@ BRepTopAdaptor_FClass2d::BRepTopAdaptor_FClass2d(const TopoDS_Face& aFace,const //-- FlecheU*=10.0; //-- FlecheV*=10.0; + if (aNbE == 1 && FlecheU < eps && FlecheV < eps && Abs(square) < eps) + { + TabOrien.Append(1); + } + else + { + TabOrien.Append(((square < 0.0)? 1 : 0)); + } + if(FlecheU0.0)? 1 : 0)); - TabOrien.Append(((square < 0.0)? 1 : 0)); }//if(nbpoints>3 else { diff --git a/src/ChFi3d/ChFi3d_Builder_6.cxx b/src/ChFi3d/ChFi3d_Builder_6.cxx index a43192a558..58188b7901 100644 --- a/src/ChFi3d/ChFi3d_Builder_6.cxx +++ b/src/ChFi3d/ChFi3d_Builder_6.cxx @@ -689,14 +689,36 @@ Standard_Boolean ChFi3d_Builder::StoreData(Handle(ChFiDS_SurfData)& Data, length2=Data->LastExtensionValue(); Handle(Geom_BoundedSurface) aBndSurf = Surf; - if (length1 > Precision::Confusion()) - GeomLib::ExtendSurfByLength(aBndSurf,length1,1,Standard_False,Standard_False); - if (length2 > Precision::Confusion()) - GeomLib::ExtendSurfByLength(aBndSurf,length2,1,Standard_False,Standard_True); - Surf = Handle(Geom_BSplineSurface)::DownCast (aBndSurf); + Standard_Boolean ext1 = Standard_False, ext2 = Standard_False; + Standard_Real eps = Max(tolget3d, 2. * Precision::Confusion()); + if (length1 > eps) + { + gp_Pnt P11, P21; + P11 = Surf->Pole(1, 1); + P21 = Surf->Pole(Surf->NbUPoles(), 1); + if (P11.Distance(P21) > eps) + { + //to avoid extending surface with singular boundary + GeomLib::ExtendSurfByLength(aBndSurf, length1, 1, Standard_False, Standard_False); + ext1 = Standard_True; + } + } + if (length2 > eps) + { + gp_Pnt P12, P22; + P12 = Surf->Pole(1, Surf->NbVPoles()); + P22 = Surf->Pole(Surf->NbUPoles(), Surf->NbVPoles()); + if (P12.Distance(P22) > eps) + { + //to avoid extending surface with singular boundary + GeomLib::ExtendSurfByLength(aBndSurf, length2, 1, Standard_False, Standard_True); + ext2 = Standard_True; + } + } + Surf = Handle(Geom_BSplineSurface)::DownCast(aBndSurf); //Correction of surface on extremities - if (length1 <= Precision::Confusion()) + if (!ext1) { gp_Pnt P11, P21; P11 = lin->StartPointOnFirst().Value(); @@ -704,7 +726,7 @@ Standard_Boolean ChFi3d_Builder::StoreData(Handle(ChFiDS_SurfData)& Data, Surf->SetPole(1, 1, P11); Surf->SetPole(Surf->NbUPoles(), 1, P21); } - if (length2 <= Precision::Confusion()) + if (!ext2) { gp_Pnt P12, P22; P12 = lin->EndPointOnFirst().Value(); diff --git a/src/Extrema/Extrema_ExtElC.cxx b/src/Extrema/Extrema_ExtElC.cxx index 8c81128afa..c3d08e2a98 100644 --- a/src/Extrema/Extrema_ExtElC.cxx +++ b/src/Extrema/Extrema_ExtElC.cxx @@ -674,6 +674,15 @@ Method: // ExtremaExtElC_TrigonometricRoots Sol(A1,A2,A3,A4,A5,0.,M_PI+M_PI); if (!Sol.IsDone()) { return; } + // + if (Sol.InfiniteRoots()) { + myIsPar = Standard_True; + gp_Pnt aP = ElCLib::EllipseValue(0., C2.Position(), C2.MajorRadius(), C2.MinorRadius()); + mySqDist[0] = C1.SquareDistance(aP); + myNbExt = 1; + myDone = Standard_True; + return; + } // Storage of solutions ... gp_Pnt P1,P2; diff --git a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx index 180bae2373..426d8d7981 100644 --- a/src/GeomliteTest/GeomliteTest_CurveCommands.cxx +++ b/src/GeomliteTest/GeomliteTest_CurveCommands.cxx @@ -108,10 +108,61 @@ #include #include #include + +#include +#include +#include +#include +#include + #ifdef _WIN32 Standard_IMPORT Draw_Viewer dout; #endif +//Class is used in fitcurve +class CurveEvaluator : public AppCont_Function + +{ + +public: + Handle(Adaptor3d_HCurve) myCurve; + + CurveEvaluator(const Handle(Adaptor3d_HCurve)& C) + : myCurve(C) + { + myNbPnt = 1; + myNbPnt2d = 0; + } + + Standard_Real FirstParameter() const + { + return myCurve->FirstParameter(); + } + + Standard_Real LastParameter() const + { + return myCurve->LastParameter(); + } + + Standard_Boolean Value(const Standard_Real theT, + NCollection_Array1& /*thePnt2d*/, + NCollection_Array1& thePnt) const + { + thePnt(1) = myCurve->Value(theT); + return Standard_True; + } + + Standard_Boolean D1(const Standard_Real theT, + NCollection_Array1& /*theVec2d*/, + NCollection_Array1& theVec) const + { + gp_Pnt aDummyPnt; + myCurve->D1(theT, aDummyPnt, theVec(1)); + return Standard_True; + } +}; + + //======================================================================= //function : anacurve //purpose : @@ -1672,6 +1723,99 @@ static Standard_Integer approxcurve(Draw_Interpretor& di, Standard_Integer n, co return 0; } + +//======================================================================= +//function : fitcurve +//purpose : +//======================================================================= + +static Standard_Integer fitcurve(Draw_Interpretor& di, Standard_Integer n, const char** a) +{ + if (n<3) return 1; + + Handle(Geom_Curve) GC; + GC = DrawTrSurf::GetCurve(a[2]); + if (GC.IsNull()) + return 1; + + Standard_Integer Dmin = 3; + Standard_Integer Dmax = 14; + Standard_Real Tol3d = 1.e-5; + Standard_Boolean inverse = Standard_True; + + if (n > 3) + { + Tol3d = Atof(a[3]); + } + + if (n > 4) + { + Dmax = atoi(a[4]); + } + + if (n > 5) + { + Standard_Integer inv = atoi(a[5]); + if (inv > 0) + { + inverse = Standard_True; + } + else + { + inverse = Standard_False; + } + } + + Handle(GeomAdaptor_HCurve) aGAC = new GeomAdaptor_HCurve(GC); + + CurveEvaluator aCE(aGAC); + + Approx_FitAndDivide anAppro(Dmin, Dmax, Tol3d, 0., Standard_True); + anAppro.SetInvOrder(inverse); + anAppro.Perform(aCE); + + if (!anAppro.IsAllApproximated()) + { + di << "Approximation failed \n"; + return 1; + } + Standard_Integer i; + Standard_Integer NbCurves = anAppro.NbMultiCurves(); + + Convert_CompBezierCurvesToBSplineCurve Conv; + + Standard_Real tol3d, tol2d, tolreached = 0.; + for (i = 1; i <= NbCurves; i++) { + anAppro.Error(i, tol3d, tol2d); + tolreached = Max(tolreached, tol3d); + AppParCurves_MultiCurve MC = anAppro.Value(i); + TColgp_Array1OfPnt Poles(1, MC.Degree() + 1); + MC.Curve(1, Poles); + Conv.AddCurve(Poles); + } + Conv.Perform(); + Standard_Integer NbPoles = Conv.NbPoles(); + Standard_Integer NbKnots = Conv.NbKnots(); + + TColgp_Array1OfPnt NewPoles(1, NbPoles); + TColStd_Array1OfReal NewKnots(1, NbKnots); + TColStd_Array1OfInteger NewMults(1, NbKnots); + + Conv.KnotsAndMults(NewKnots, NewMults); + Conv.Poles(NewPoles); + + BSplCLib::Reparametrize(GC->FirstParameter(), + GC->LastParameter(), + NewKnots); + Handle(Geom_BSplineCurve) TheCurve = new Geom_BSplineCurve(NewPoles, NewKnots, NewMults, Conv.Degree()); + + DrawTrSurf::Set(a[1], TheCurve); + di << a[1] << ": tolreached = " << tolreached << "\n"; + + return 0; + +} + //======================================================================= //function : newbspline //purpose : reduce the multiplicity of the knots to their minimum @@ -2060,6 +2204,8 @@ void GeomliteTest::CurveCommands(Draw_Interpretor& theCommands) __FILE__, approxcurveonsurf,g); + theCommands.Add("fitcurve", "fitcurve result curve [tol [maxdeg [inverse]]]", __FILE__, fitcurve, g); + theCommands.Add("length", "length curve [Tol]", __FILE__, length, g); diff --git a/src/IntTools/IntTools_EdgeEdge.cxx b/src/IntTools/IntTools_EdgeEdge.cxx index 38c36465d7..78ef6ab78d 100644 --- a/src/IntTools/IntTools_EdgeEdge.cxx +++ b/src/IntTools/IntTools_EdgeEdge.cxx @@ -35,6 +35,7 @@ #include #include #include +#include static void BndBuildBox(const BRepAdaptor_Curve& theBAC, @@ -224,6 +225,24 @@ void IntTools_EdgeEdge::Perform() } } // + if ((myCurve1.GetType() <= GeomAbs_Parabola && myCurve2.GetType() <= GeomAbs_Parabola) && + (myCurve1.GetType() == GeomAbs_Line || myCurve2.GetType() == GeomAbs_Line)) + { + //Improvement of performance for cases of searching common parts between line + //and analytical curve. This code allows to define that edges have no + //common parts more fast, then regular algorithm (FindSolution(...)) + //Check minimal distance between edges + BRepExtrema_DistShapeShape aMinDist(myEdge1, myEdge2, Extrema_ExtFlag_MIN); + if (aMinDist.IsDone()) + { + Standard_Real d = aMinDist.Value(); + if (d > 1.1 * myTol) + { + return; + } + } + } + IntTools_SequenceOfRanges aRanges1, aRanges2; // //3.2. Find ranges containig solutions diff --git a/src/ProjLib/ProjLib_ComputeApprox.cxx b/src/ProjLib/ProjLib_ComputeApprox.cxx index 5090998187..e71fe844a6 100644 --- a/src/ProjLib/ProjLib_ComputeApprox.cxx +++ b/src/ProjLib/ProjLib_ComputeApprox.cxx @@ -1011,6 +1011,15 @@ void ProjLib_ComputeApprox::Perform (CType != GeomAbs_OtherCurve) ; Standard_Boolean simplecase = SurfIsAnal && CurvIsAnal; + if (CType == GeomAbs_BSplineCurve || CType == GeomAbs_BezierCurve) + { + Standard_Integer aNbKnots = 1; + if (CType == GeomAbs_BSplineCurve) + { + aNbKnots = C->NbKnots(); + } + simplecase = simplecase && C->Degree() <= 2 && aNbKnots <= 2; + } if (CType == GeomAbs_BSplineCurve && SType == GeomAbs_Plane ) { @@ -1111,12 +1120,12 @@ void ProjLib_ComputeApprox::Perform #endif //----------- - Standard_Integer Deg1 = 8, Deg2; - if(simplecase) { - Deg2 = 10; + Standard_Integer Deg1 = 5, Deg2; + if (simplecase) { + Deg2 = 8; } else { - Deg2 = 12; + Deg2 = 10; } if(myDegMin > 0) { @@ -1188,6 +1197,10 @@ void ProjLib_ComputeApprox::Perform C->LastParameter(), NewKnots); + // Set NewKnots(NbKnots) exactly C->LastParameter() + // to avoid problems if trim is used. + NewKnots(NbKnots) = C->LastParameter(); + // 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.) diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx index c104aa09ee..14a5f98616 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.cxx @@ -482,7 +482,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface() myDegMin(-1), myDegMax(-1), myMaxSegments(-1), myMaxDist(-1.), - myBndPnt(AppParCurves_TangencyPoint) + myBndPnt(AppParCurves_TangencyPoint), + myDist(0.) { } @@ -502,7 +503,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface myDegMin(-1), myDegMax(-1), myMaxSegments(-1), myMaxDist(-1.), - myBndPnt(AppParCurves_TangencyPoint) + myBndPnt(AppParCurves_TangencyPoint), + myDist(0.) { myBSpline = Perform(theInitialCurve2d, theCurve, theSurface); } @@ -522,7 +524,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface myDegMin(-1), myDegMax(-1), myMaxSegments(-1), myMaxDist(-1.), - myBndPnt(AppParCurves_TangencyPoint) + myBndPnt(AppParCurves_TangencyPoint), + myDist(0.) { const Handle(Adaptor2d_HCurve2d) anInitCurve2d; myBSpline = Perform(anInitCurve2d, theCurve, theSurface); @@ -545,7 +548,8 @@ ProjLib_ComputeApproxOnPolarSurface::ProjLib_ComputeApproxOnPolarSurface myDegMin(-1), myDegMax(-1), myMaxSegments(-1), myMaxDist(-1.), - myBndPnt(AppParCurves_TangencyPoint) + myBndPnt(AppParCurves_TangencyPoint), + myDist(0.) { // InitialCurve2d and InitialCurve2dBis are two pcurves of the sewing Handle(Geom2d_BSplineCurve) bsc = @@ -1079,6 +1083,7 @@ Handle(Adaptor2d_HCurve2d) else { myProjIsDone = Standard_False; Standard_Real Dist2Min = 1.e+200, u = 0., v = 0.; + myDist = 0.; gp_Pnt pntproj; TColgp_SequenceOfPnt2d Sols; @@ -1253,7 +1258,7 @@ Handle(Adaptor2d_HCurve2d) // U0 and V0 are the points in the initialized period // (period with u and v), // U1 and V1 are the points for construction of poles - + myDist = Dist2Min; for ( i = 2 ; i <= NbOfPnts ; i++) if(myProjIsDone) { myProjIsDone = Standard_False; @@ -1267,6 +1272,10 @@ Handle(Adaptor2d_HCurve2d) if (aLocateExtPS.SquareDistance() < DistTol3d2) { //OCC217 //if (aLocateExtPS.SquareDistance() < Tol3d * Tol3d) { + if (aLocateExtPS.SquareDistance() > myDist) + { + myDist = aLocateExtPS.SquareDistance(); + } (aLocateExtPS.Point()).Parameter(U0,V0); U1 = U0 + usens*uperiod; V1 = V0 + vsens*vperiod; @@ -1291,6 +1300,10 @@ Handle(Adaptor2d_HCurve2d) } if (LocalMinSqDist < DistTol3d2) { + if (LocalMinSqDist > myDist) + { + myDist = LocalMinSqDist; + } Standard_Real LocalU, LocalV; aGlobalExtr.Point(imin).Parameter(LocalU, LocalV); if (uperiod > 0. && Abs(U0 - LocalU) >= uperiod/2.) @@ -1363,6 +1376,10 @@ Handle(Adaptor2d_HCurve2d) if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d2) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { + if (locext.SquareDistance() > myDist) + { + myDist = locext.SquareDistance(); + } (locext.Point()).Parameter(u,v); if((aUsup - U0) > (U0 - aUinf)) usens--; @@ -1390,7 +1407,11 @@ Handle(Adaptor2d_HCurve2d) if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d2) { //OCC217 //if (locext.SquareDistance() < Tol3d * Tol3d) { - (locext.Point()).Parameter(u,v); + if (locext.SquareDistance() > myDist) + { + myDist = locext.SquareDistance(); + } + (locext.Point()).Parameter(u, v); if((aVsup - V0) > (V0 - aVinf)) vsens--; else @@ -1419,7 +1440,11 @@ Handle(Adaptor2d_HCurve2d) if (locext.IsDone()) if (locext.SquareDistance() < DistTol3d2) { //if (locext.SquareDistance() < Tol3d * Tol3d) { - (locext.Point()).Parameter(u,v); + if (locext.SquareDistance() > myDist) + { + myDist = locext.SquareDistance(); + } + (locext.Point()).Parameter(u, v); if((Usup - U0) > (U0 - Uinf)) usens--; else @@ -1447,7 +1472,11 @@ Handle(Adaptor2d_HCurve2d) } if (Dist2Min < DistTol3d2) { //if (Dist2Min < Tol3d * Tol3d) { - (ext.Point(aGoodValue)).Parameter(u,v); + if (Dist2Min > myDist) + { + myDist = Dist2Min; + } + (ext.Point(aGoodValue)).Parameter(u, v); if(uperiod) { if((U0 - u) > (2*uperiod/3)) { usens++; @@ -1862,8 +1891,18 @@ Handle(Geom2d_BSplineCurve) aLastC = myBndPnt; } + if (myDist > 10.*Tol3d) + { + aFistC = AppParCurves_PassPoint; + aLastC = AppParCurves_PassPoint; + } + Approx_FitAndDivide2d Fit(Deg1, Deg2, Tol3d, Tol2d, Standard_True, aFistC, aLastC); Fit.SetMaxSegments(aMaxSegments); + if (InitCurve2d->GetType() == GeomAbs_Line) + { + Fit.SetInvOrder(Standard_False); + } Fit.Perform(F); Standard_Real anOldTol2d = Tol2d; @@ -1936,6 +1975,10 @@ Handle(Geom2d_BSplineCurve) Standard_Boolean OK = Standard_True; Standard_Real aSmoothTol = Max(Precision::Confusion(), aNewTol2d); + if (myBndPnt == AppParCurves_PassPoint) + { + aSmoothTol *= 10.; + } for (Standard_Integer ij = 2; ij < NbKnots; ij++) { OK = OK && Dummy->RemoveKnot(ij,MaxDeg-1, aSmoothTol); } diff --git a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx index 3927f2759c..393c8c68db 100644 --- a/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx +++ b/src/ProjLib/ProjLib_ComputeApproxOnPolarSurface.hxx @@ -142,7 +142,7 @@ private: Standard_Integer myMaxSegments; Standard_Real myMaxDist; AppParCurves_Constraint myBndPnt; - + Standard_Real myDist; }; diff --git a/src/ProjLib/ProjLib_ProjectOnPlane.cxx b/src/ProjLib/ProjLib_ProjectOnPlane.cxx index 61375aa3ed..b059fcadfa 100644 --- a/src/ProjLib/ProjLib_ProjectOnPlane.cxx +++ b/src/ProjLib/ProjLib_ProjectOnPlane.cxx @@ -317,8 +317,14 @@ static void PerformApprox (const Handle(Adaptor3d_HCurve)& C, Standard_Integer Deg1, Deg2; Deg1 = 8; Deg2 = 8; - Approx_FitAndDivide Fit(F,Deg1,Deg2,Precision::Approximation(), + Approx_FitAndDivide Fit(Deg1,Deg2,Precision::Approximation(), Precision::PApproximation(),Standard_True); + Fit.SetMaxSegments(100); + Fit.Perform(F); + if (!Fit.IsAllApproximated()) + { + return; + } Standard_Integer i; Standard_Integer NbCurves = Fit.NbMultiCurves(); Standard_Integer MaxDeg = 0; @@ -347,9 +353,8 @@ static void PerformApprox (const Handle(Adaptor3d_HCurve)& C, MC.Curve(1, LocalPoles); //Augmentation eventuelle du degre - Standard_Integer Inc = MaxDeg - MC.Degree(); - if ( Inc > 0) { - BSplCLib::IncreaseDegree(Inc, Poles, BSplCLib::NoWeights(), + if (MaxDeg > MC.Degree() ) { + BSplCLib::IncreaseDegree(MaxDeg, LocalPoles, BSplCLib::NoWeights(), TempPoles, BSplCLib::NoWeights()); //mise a jour des poles de la PCurve for (Standard_Integer j = 1 ; j <= MaxDeg + 1; j++) { diff --git a/src/QABugs/QABugs_20.cxx b/src/QABugs/QABugs_20.cxx index 6d92a0e549..09653f6e70 100644 --- a/src/QABugs/QABugs_20.cxx +++ b/src/QABugs/QABugs_20.cxx @@ -3098,6 +3098,132 @@ static Standard_Integer QAEndsWith(Draw_Interpretor& di, Standard_Integer n, con return 1; } +//Class is used in OCC30435 +#include +#include +class CurveEvaluator : public AppCont_Function + +{ + +public: + Handle(Adaptor3d_HCurve) myCurve; + + CurveEvaluator(const Handle(Adaptor3d_HCurve)& C) + : myCurve(C) + { + myNbPnt = 1; + myNbPnt2d = 0; + } + + Standard_Real FirstParameter() const + { + return myCurve->FirstParameter(); + } + + Standard_Real LastParameter() const + { + return myCurve->LastParameter(); + } + + Standard_Boolean Value(const Standard_Real theT, + NCollection_Array1& /*thePnt2d*/, + NCollection_Array1& thePnt) const + { + thePnt(1) = myCurve->Value(theT); + return Standard_True; + } + + Standard_Boolean D1(const Standard_Real theT, + NCollection_Array1& /*theVec2d*/, + NCollection_Array1& theVec) const + { + gp_Pnt aDummyPnt; + myCurve->D1(theT, aDummyPnt, theVec(1)); + return Standard_True; + } +}; + +#include +#include +#include +static Standard_Integer OCC30435(Draw_Interpretor& di, Standard_Integer, const char** a) +{ + + Handle(Geom_Curve) GC; + GC = DrawTrSurf::GetCurve(a[2]); + if (GC.IsNull()) + return 1; + + Standard_Integer Dmin = 3; + Standard_Integer Dmax = 12; + Standard_Real Tol3d = 1.e-7; + Standard_Boolean inverse = Standard_True; + + + Standard_Integer inv = atoi(a[3]); + if (inv > 0) + { + inverse = Standard_True; + } + else + { + inverse = Standard_False; + } + + Standard_Integer maxit = atoi(a[4]); + + Handle(GeomAdaptor_HCurve) aGAC = new GeomAdaptor_HCurve(GC); + + CurveEvaluator aCE(aGAC); + + Approx_FitAndDivide anAppro(Dmin, Dmax, Tol3d, 0., Standard_True); + anAppro.SetInvOrder(inverse); + Standard_Integer i; + for (i = 1; i <= maxit; ++i) + anAppro.Perform(aCE); + + if (!anAppro.IsAllApproximated()) + { + di << "Approximation failed \n"; + return 1; + } + Standard_Integer NbCurves = anAppro.NbMultiCurves(); + + Convert_CompBezierCurvesToBSplineCurve Conv; + + Standard_Real tol3d, tol2d, tolreached = 0.; + for (i = 1; i <= NbCurves; i++) { + anAppro.Error(i, tol3d, tol2d); + tolreached = Max(tolreached, tol3d); + AppParCurves_MultiCurve MC = anAppro.Value(i); + TColgp_Array1OfPnt Poles(1, MC.Degree() + 1); + MC.Curve(1, Poles); + Conv.AddCurve(Poles); + } + Conv.Perform(); + Standard_Integer NbPoles = Conv.NbPoles(); + Standard_Integer NbKnots = Conv.NbKnots(); + + TColgp_Array1OfPnt NewPoles(1, NbPoles); + TColStd_Array1OfReal NewKnots(1, NbKnots); + TColStd_Array1OfInteger NewMults(1, NbKnots); + + Conv.KnotsAndMults(NewKnots, NewMults); + Conv.Poles(NewPoles); + + BSplCLib::Reparametrize(GC->FirstParameter(), + GC->LastParameter(), + NewKnots); + Handle(Geom_BSplineCurve) TheCurve = new Geom_BSplineCurve(NewPoles, NewKnots, NewMults, Conv.Degree()); + + DrawTrSurf::Set(a[1], TheCurve); + di << a[1] << ": tolreached = " << tolreached << "\n"; + + return 0; + +} + + void QABugs::Commands_20(Draw_Interpretor& theCommands) { const char *group = "QABugs"; @@ -3138,6 +3264,7 @@ void QABugs::Commands_20(Draw_Interpretor& theCommands) { theCommands.Add("OCC29807", "OCC29807 surface1 surface2 u1 v1 u2 v2", __FILE__, OCC29807, group); theCommands.Add("OCC29311", "OCC29311 shape counter nbiter: check performance of OBB calculation", __FILE__, OCC29311, group); theCommands.Add("OCC30391", "OCC30391 result face LenBeforeUfirst LenAfterUlast LenBeforeVfirst LenAfterVlast", __FILE__, OCC30391, group); + theCommands.Add("OCC30435", "OCC30435 result curve inverse nbit", __FILE__, OCC30435, group); theCommands.Add("QAStartsWith", "QAStartsWith string startstring", diff --git a/tests/bugs/mesh/bug30008_2 b/tests/bugs/mesh/bug30008_2 index 7daf3f0f66..e7997c15bc 100644 --- a/tests/bugs/mesh/bug30008_2 +++ b/tests/bugs/mesh/bug30008_2 @@ -19,7 +19,7 @@ nurbsconvert result result incmesh result 0.15 -a 20 tricheck result -checktrinfo result -tri 193 -nod 147 -defl 0.042090809832482222 -tol_abs_defl 1.0e-7 +checktrinfo result -tri 193 -nod 147 -defl 0.04209 -tol_abs_defl 1.0e-6 vinit diff --git a/tests/bugs/modalg_7/bug27711_3 b/tests/bugs/modalg_7/bug27711_3 index bf3a0afc64..d76d1cd245 100644 --- a/tests/bugs/modalg_7/bug27711_3 +++ b/tests/bugs/modalg_7/bug27711_3 @@ -1,6 +1,3 @@ -puts "TODO CR27711 Linux: Tcl Exception: tolerance ang : 0.01" -puts "TODO CR27711 Linux: TEST INCOMPLETE" - puts "========" puts "OCC27711" puts "========" diff --git a/tests/de/step_4/D9 b/tests/de/step_4/D9 index b824324113..8bc1f9c450 100644 --- a/tests/de/step_4/D9 +++ b/tests/de/step_4/D9 @@ -6,11 +6,11 @@ set filename test-m020306-v1.stp set ref_data { DATA : Faulties = 0 ( 0 ) Warnings = 0 ( 0 ) Summary = 0 ( 0 ) -TPSTAT : Faulties = 0 ( 0 ) Warnings = 151 ( 114 ) Summary = 151 ( 114 ) +TPSTAT : Faulties = 0 ( 0 ) Warnings = 153 ( 114 ) Summary = 153 ( 114 ) CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) NBSHAPES : Solid = 1 ( 1 ) Shell = 1 ( 1 ) Face = 742 ( 742 ) STATSHAPE : Solid = 1 ( 1 ) Shell = 1 ( 1 ) Face = 742 ( 742 ) FreeWire = 0 ( 0 ) -TOLERANCE : MaxTol = 0.008481946718 ( 0.01609778278 ) AvgTol = 0.000132185171 ( 0.0003164960473 ) +TOLERANCE : MaxTol = 0.008481946718 ( 0.01167623167 ) AvgTol = 0.000132472064 ( 0.0003097606769 ) LABELS : N0Labels = 1 ( 1 ) N1Labels = 0 ( 0 ) N2Labels = 0 ( 0 ) TotalLabels = 1 ( 1 ) NameLabels = 1 ( 1 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 ) NCOLORS : NColors = 0 ( 0 ) diff --git a/tests/de/step_4/E1 b/tests/de/step_4/E1 index 449a5797b3..fc7ab98fb3 100644 --- a/tests/de/step_4/E1 +++ b/tests/de/step_4/E1 @@ -7,7 +7,7 @@ TPSTAT : Faulties = 0 ( 0 ) Warnings = 61 ( 157 ) Summary = 61 ( 157 CHECKSHAPE : Wires = 0 ( 0 ) Faces = 0 ( 0 ) Shells = 0 ( 0 ) Solids = 0 ( 0 ) NBSHAPES : Solid = 1 ( 1 ) Shell = 1 ( 1 ) Face = 956 ( 956 ) STATSHAPE : Solid = 1 ( 1 ) Shell = 1 ( 1 ) Face = 956 ( 956 ) FreeWire = 0 ( 0 ) -TOLERANCE : MaxTol = 0.008481946718 ( 0.01609778278 ) AvgTol = 0.0001239210368 ( 0.0003823229569 ) +TOLERANCE : MaxTol = 0.008481946718 ( 0.05394823207 ) AvgTol = 0.0001239210367 ( 0.0004089750747 ) LABELS : N0Labels = 1 ( 1 ) N1Labels = 0 ( 0 ) N2Labels = 0 ( 0 ) TotalLabels = 1 ( 1 ) NameLabels = 1 ( 1 ) ColorLabels = 0 ( 0 ) LayerLabels = 0 ( 0 ) PROPS : Centroid = 0 ( 0 ) Volume = 0 ( 0 ) Area = 0 ( 0 ) NCOLORS : NColors = 0 ( 0 ) diff --git a/tests/lowalgos/intss/bug27263 b/tests/lowalgos/intss/bug27263 index f6c316ede9..9471b1eb4d 100644 --- a/tests/lowalgos/intss/bug27263 +++ b/tests/lowalgos/intss/bug27263 @@ -7,7 +7,7 @@ puts "" ####################################################################### set MaxTol 1.e-7 -set GoodNbCurv 1 +set GoodNbCurv 2 restore [locate_data_file bug27262_cmpd.brep] b explode b @@ -30,5 +30,6 @@ if {${NbCurv} != ${GoodNbCurv}} { } checklength c_1 -l 2.9620641619623407 +checklength c_2 -l 3.1050603628884668 checkview -screenshot -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/perf/moddata/bug30435 b/tests/perf/moddata/bug30435 new file mode 100644 index 0000000000..934405e6b9 --- /dev/null +++ b/tests/perf/moddata/bug30435 @@ -0,0 +1,46 @@ +puts "========" +puts "BUG30435" +puts "Improving performance of Approx_ComputeCLine" +puts "========" +puts "" + +pload QAcommands +cone con 0 0 0 0 0 -1 1 0 0 -30 0 +2dbeziercurve b 4 0 0 15 15 35 -15 50 1. +approxcurveonsurf cc b con 1.e-7 1 12 1000 +clear con +clpoles cc + +set time0 "" +set time1 "" + +dchrono t0 restart +OCC30435 r0 cc 0 50 +dchrono t0 stop +set inf0 [dchrono t0 counter OCC30435] + +regexp {COUNTER OCC30435: ([-0-9.+eE]+)} $inf0 full0 time0 + +dchrono t1 restart +OCC30435 r1 cc 1 50 +dchrono t1 stop +set inf1 [dchrono t1 counter OCC30435_1] + +regexp {COUNTER OCC30435_1: ([-0-9.+eE]+)} $inf1 full1 time1 + +if { $time1 > $time0 } { + puts "Error : optimized algorithm works slowly then initial one" +} else { + puts "Performance ratio is [expr $time0/$time1]" +} + +clpoles r0 +clpoles r1 +smallview +fit +xwd $imagedir/${test_image}.png + + + + +