diff --git a/src/BRepAlgo/BRepAlgo_NormalProjection.cxx b/src/BRepAlgo/BRepAlgo_NormalProjection.cxx index 2a289ebab0..f94dab3b00 100644 --- a/src/BRepAlgo/BRepAlgo_NormalProjection.cxx +++ b/src/BRepAlgo/BRepAlgo_NormalProjection.cxx @@ -355,6 +355,10 @@ void BRepAlgo_NormalProjection::SetDefaultParams() #endif Approx_CurveOnSurface appr(HPCur, hsur, Udeb, Ufin, myTol3d); appr.Perform(myMaxSeg, myMaxDegree, myContinuity, Only3d, Only2d); + + if (appr.MaxError3d() > 1.e3 * myTol3d) + continue; + #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_approx,t_approx); approx_count++; diff --git a/src/GeometryTest/GeometryTest_CurveCommands.cxx b/src/GeometryTest/GeometryTest_CurveCommands.cxx index 1692201516..fc26d2d158 100644 --- a/src/GeometryTest/GeometryTest_CurveCommands.cxx +++ b/src/GeometryTest/GeometryTest_CurveCommands.cxx @@ -261,134 +261,135 @@ static Standard_Integer to3d (Draw_Interpretor& , Standard_Integer n, const char static Standard_Integer gproject(Draw_Interpretor& di, Standard_Integer n, const char** a) { - - char newname[1024]; - char* temp = newname; - char newname1[10]; - char* temp1 = newname1; - char name[100]; - Standard_Integer ONE = 1; + TCollection_AsciiString newname; + TCollection_AsciiString newname1; - if (n == 3) - Sprintf(name,"p"); - else if (n == 4) { - Sprintf(name,"%s",a[1]); - ONE = 2; + if (n < 4) + { + di << "gproject waits 3 or more arguments\n"; + return 1; } - else { - di << "gproject wait 2 or 3 arguments\n"; - return 1; - } - Handle(Geom_Curve) Cur = DrawTrSurf::GetCurve(a[ONE]); - Handle(Geom_Surface) Sur = DrawTrSurf::GetSurface(a[ONE+1]); + TCollection_AsciiString name = a[1]; + + Handle(Geom_Curve) Cur = DrawTrSurf::GetCurve(a[2]); + Handle(Geom_Surface) Sur = DrawTrSurf::GetSurface(a[3]); if (Cur.IsNull() || Sur.IsNull()) return 1; Handle(GeomAdaptor_Curve) hcur = new GeomAdaptor_Curve(Cur); Handle(GeomAdaptor_Surface) hsur = new GeomAdaptor_Surface(Sur); + Standard_Integer index = 4; + Standard_Real aTol3d = 1.e-6; + Standard_Real aMaxDist = -1.0; - Standard_Real myTol3d = 1.e-6; - GeomAbs_Shape myContinuity = GeomAbs_C2; - Standard_Integer myMaxDegree = 14, myMaxSeg = 16; + if (n > 4 && a[4][0] != '-') + { + aTol3d = Draw::Atof(a[4]); + index = 5; + if (n > 5 && a[5][0] != '-') + { + aMaxDist = Draw::Atof(a[5]); + index = 6; + } + } - Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve (hsur, hcur, myTol3d/10, myTol3d/10); + Handle(ProjLib_HCompProjectedCurve) HProjector = new ProjLib_HCompProjectedCurve(aTol3d, hsur, hcur, aMaxDist); ProjLib_CompProjectedCurve& Projector = *HProjector; - Standard_Integer k; - Standard_Real Udeb, Ufin, UIso, VIso; - Standard_Boolean Only2d, Only3d; - gp_Pnt2d P2d, Pdeb, Pfin; - gp_Pnt P; - Handle(Adaptor2d_Curve2d) HPCur; - Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection + GeomAbs_Shape aContinuity = GeomAbs_C2; + Standard_Integer aMaxDegree, aMaxSeg; + Standard_Boolean aProj2d; + Standard_Boolean aProj3d; - for(k = 1; k <= Projector.NbCurves(); k++){ - Sprintf(newname,"%s_%d",name,k); - Sprintf(newname1,"%s2d_%d",name,k); - if(Projector.IsSinglePnt(k, P2d)){ -// std::cout<<"Part "<D0(P2d.X(), P2d.Y(), P); - DrawTrSurf::Set(temp, P); - DrawTrSurf::Set(temp1, P2d); - di< 25 ? 25 : aMaxDegree; + Projector.SetMaxDegree(aMaxDegree); + } + else if (a[index][1] == 's') + { + aMaxSeg = Draw::Atoi(a[index + 1]); + Projector.SetMaxSeg(aMaxSeg); + } + else if (!strcmp(a[index], "-2d")) + { + aProj2d = Draw::Atoi(a[index + 1]) > 0 ? Standard_True : Standard_False; + Projector.SetProj2d(aProj2d); + } + else if (!strcmp(a[index], "-3d")) + { + aProj3d = Draw::Atoi(a[index + 1]) > 0 ? Standard_True : Standard_False; + Projector.SetProj3d(aProj3d); + } + + index += 2; + } + + Projector.Perform(); + + for (Standard_Integer k = 1; k <= Projector.NbCurves(); k++) { + newname = name + "_" + TCollection_AsciiString(k); + newname1 = name + "2d_" + TCollection_AsciiString(k); + + if (Projector.ResultIsPoint(k)) + { + if (Projector.GetProj2d()) + { + DrawTrSurf::Set(newname1.ToCString(), Projector.GetResult2dP(k)); + di << newname1 << " is pcurve\n"; + } + if (Projector.GetProj3d()) + { + DrawTrSurf::Set(newname.ToCString(), Projector.GetResult3dP(k)); + di << newname << " is 3d projected curve\n"; + } } else { - Only2d = Only3d = Standard_False; - Projector.Bounds(k, Udeb, Ufin); - gp_Dir2d Dir; // Only for isoparametric projection - - if (Projector.IsUIso(k, UIso)) { -// std::cout<<"Part "< Ufin) { - Dir = gp_Dir2d(0, -1); - Udeb = - Udeb; - Ufin = - Ufin; - } - else Dir = gp_Dir2d(0, 1); - PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(UIso, 0), Dir), Udeb, Ufin); - HPCur = new Geom2dAdaptor_Curve(PCur2d); - Only3d = Standard_True; + if (Projector.GetProj2d()) + { + DrawTrSurf::Set(newname1.ToCString(), Projector.GetResult2dC(k)); + + di << newname1 << " is pcurve\n"; + di << " Tolerance reached in 2d is " << Projector.GetResult2dUApproxError(k) + << "; " << Projector.GetResult2dVApproxError(k) << "\n"; } - else if(Projector.IsVIso(k, VIso)) { -// std::cout<<"Part "< Ufin) { - Dir = gp_Dir2d(-1, 0); - Udeb = - Udeb; - Ufin = - Ufin; - } - else Dir = gp_Dir2d(1, 0); - PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(0, VIso), Dir), Udeb, Ufin); - HPCur = new Geom2dAdaptor_Curve(PCur2d); - Only3d = Standard_True; - } - else HPCur = HProjector; - - if(Projector.MaxDistance(k) <= myTol3d) - Only2d = Standard_True; - - if(Only2d && Only3d) { - Handle(Geom_Curve) OutCur = new Geom_TrimmedCurve (GeomAdaptor::MakeCurve (*hcur), Ufin, Udeb); - DrawTrSurf::Set(temp, OutCur); - DrawTrSurf::Set(temp1, PCur2d); - di< #include #include +#include #include #include #include #include #include #include +#include #include #include #include @@ -39,13 +41,21 @@ #include #include #include +#include #include #include +#include +#include +#include #include +#include #include +#include #include #include +#include + #define FuncTol 1.e-10 IMPLEMENT_STANDARD_RTTIEXT(ProjLib_CompProjectedCurve, Adaptor2d_Curve2d) @@ -537,7 +547,8 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point, const Standard_Real TolU, const Standard_Real TolV, Standard_Real& U, - Standard_Real& V) + Standard_Real& V, + Standard_Real theMaxDist) { ProjLib_PrjResolve aPrjPS (*C, *S, 1); @@ -549,6 +560,11 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point, aExtPS.Perform(Point); Standard_Integer argmin = 0; + Standard_Real aMaxDist = theMaxDist; + if (aMaxDist > 0.) + { + aMaxDist *= aMaxDist; + } if (aExtPS.IsDone() && aExtPS.NbExt()) { Standard_Integer i, Nend; @@ -556,6 +572,10 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point, Nend = aExtPS.NbExt(); for(i = 1; i <= Nend; i++) { + if (aMaxDist > 0. && aMaxDist < aExtPS.SquareDistance(i)) + { + continue; + } Extrema_POnSurf POnS = aExtPS.Point(i); POnS.Parameter(ParU, ParV); aPrjPS.Perform(t, ParU, ParV, gp_Pnt2d(TolU, TolV), @@ -582,9 +602,9 @@ static Standard_Boolean InitialPoint(const gp_Pnt& Point, ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve() : myNbCurves(0), + myMaxDist (0.0), myTolU (0.0), - myTolV (0.0), - myMaxDist (0.0) + myTolV (0.0) { } @@ -598,13 +618,19 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve const Handle(Adaptor3d_Curve)& theCurve, const Standard_Real theTolU, const Standard_Real theTolV) -: mySurface (theSurface), - myCurve (theCurve), - myNbCurves(0), - mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()), - myTolU (theTolU), - myTolV (theTolV), - myMaxDist (-1.0) +: mySurface (theSurface), + myCurve (theCurve), + myNbCurves (0), + mySequence (new ProjLib_HSequenceOfHSequenceOfPnt()), + myTol3d (1.e-6), + myContinuity(GeomAbs_C2), + myMaxDegree (14), + myMaxSeg (16), + myProj2d (Standard_True), + myProj3d (Standard_False), + myMaxDist (-1.0), + myTolU (theTolU), + myTolV (theTolV) { Init(); } @@ -620,17 +646,51 @@ ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve const Standard_Real theTolU, const Standard_Real theTolV, const Standard_Real theMaxDist) -: mySurface (theSurface), - myCurve (theCurve), - myNbCurves(0), - mySequence(new ProjLib_HSequenceOfHSequenceOfPnt()), - myTolU (theTolU), - myTolV (theTolV), - myMaxDist (theMaxDist) +: mySurface (theSurface), + myCurve (theCurve), + myNbCurves (0), + mySequence (new ProjLib_HSequenceOfHSequenceOfPnt()), + myTol3d (1.e-6), + myContinuity(GeomAbs_C2), + myMaxDegree (14), + myMaxSeg (16), + myProj2d (Standard_True), + myProj3d (Standard_False), + myMaxDist (theMaxDist), + myTolU (theTolU), + myTolV (theTolV) { Init(); } +//======================================================================= +//function : ProjLib_CompProjectedCurve +//purpose : +//======================================================================= + +ProjLib_CompProjectedCurve::ProjLib_CompProjectedCurve + (const Standard_Real theTol3d, + const Handle(Adaptor3d_Surface)& theSurface, + const Handle(Adaptor3d_Curve)& theCurve, + const Standard_Real theMaxDist) +: mySurface (theSurface), + myCurve (theCurve), + myNbCurves (0), + mySequence (new ProjLib_HSequenceOfHSequenceOfPnt()), + myTol3d (theTol3d), + myContinuity(GeomAbs_C2), + myMaxDegree (14), + myMaxSeg (16), + myProj2d (Standard_True), + myProj3d (Standard_False), + myMaxDist (theMaxDist) +{ + myTolU = Max(Precision::PConfusion(), mySurface->UResolution(theTol3d)); + myTolV = Max(Precision::PConfusion(), mySurface->VResolution(theTol3d)); + + Init(); +} + //======================================================================= //function : ShallowCopy //purpose : @@ -774,7 +834,7 @@ void ProjLib_CompProjectedCurve::Init() InitChron(chr_init_point); #endif // PConfusion - use geometric tolerances in extrema / optimization. - initpoint=InitialPoint(CPoint, t,myCurve,mySurface, Precision::PConfusion(), Precision::PConfusion(), U, V); + initpoint=InitialPoint(CPoint, t, myCurve, mySurface, myTolU, myTolV, U, V, myMaxDist); #ifdef OCCT_DEBUG_CHRONO ResultChron(chr_init_point,t_init_point); init_point_count++; @@ -1164,6 +1224,239 @@ void ProjLib_CompProjectedCurve::Init() } } } + +//======================================================================= +//function : Perform +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::Perform() +{ + if (myNbCurves == 0) + return; + + Standard_Boolean approx2d = myProj2d; + Standard_Boolean approx3d = myProj3d; + Standard_Real Udeb, Ufin, UIso, VIso; + gp_Pnt2d P2d, Pdeb, Pfin; + gp_Pnt P; + Handle(Adaptor2d_Curve2d) HPCur; + Handle(Adaptor3d_Surface) HS = mySurface->ShallowCopy(); // For expand bounds of surface + Handle(Geom2d_Curve) PCur2d; // Only for isoparametric projection + Handle(Geom_Curve) PCur3d; + + if (myProj2d == Standard_True) + { + myResult2dPoint = new TColgp_HArray1OfPnt2d(1, myNbCurves); + myResult2dCurve = new TColGeom2d_HArray1OfCurve(1, myNbCurves); + } + + if (myProj3d == Standard_True) + { + myResult3dPoint = new TColgp_HArray1OfPnt(1, myNbCurves); + myResult3dCurve = new TColGeom_HArray1OfCurve(1, myNbCurves); + } + + myResultIsPoint = new TColStd_HArray1OfBoolean(1, myNbCurves); + myResultIsPoint->Init(Standard_False); + + myResult3dApproxError = new TColStd_HArray1OfReal(1, myNbCurves); + myResult3dApproxError->Init(0.0); + + myResult2dUApproxError = new TColStd_HArray1OfReal(1, myNbCurves); + myResult2dUApproxError->Init(0.0); + + myResult2dVApproxError = new TColStd_HArray1OfReal(1, myNbCurves); + myResult2dVApproxError->Init(0.0); + + for (Standard_Integer k = 1; k <= myNbCurves; k++) + { + if (IsSinglePnt(k, P2d)) // Part k of the projection is punctual + { + GetSurface()->D0(P2d.X(), P2d.Y(), P); + if (myProj2d == Standard_True) + { + myResult2dPoint->SetValue(k, P2d); + } + if (myProj3d == Standard_True) + { + myResult3dPoint->SetValue(k, P); + } + myResultIsPoint->SetValue(k, Standard_True); + } + else + { + Bounds(k, Udeb, Ufin); + gp_Dir2d Dir; // Only for isoparametric projection + + if (IsUIso(k, UIso)) // Part k of the projection is U-isoparametric curve + { + approx2d = Standard_False; + + D0(Udeb, Pdeb); + D0(Ufin, Pfin); + Udeb = Pdeb.Y(); + Ufin = Pfin.Y(); + if (Udeb > Ufin) + { + Dir = gp_Dir2d(0, -1); + Udeb = -Udeb; + Ufin = -Ufin; + } + else Dir = gp_Dir2d(0, 1); + PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(UIso, 0), Dir), Udeb, Ufin); + HPCur = new Geom2dAdaptor_Curve(PCur2d); + } + else if (IsVIso(k, VIso)) // Part k of the projection is V-isoparametric curve + { + approx2d = Standard_False; + + D0(Udeb, Pdeb); + D0(Ufin, Pfin); + Udeb = Pdeb.X(); + Ufin = Pfin.X(); + if (Udeb > Ufin) + { + Dir = gp_Dir2d(-1, 0); + Udeb = -Udeb; + Ufin = -Ufin; + } + else Dir = gp_Dir2d(1, 0); + PCur2d = new Geom2d_TrimmedCurve(new Geom2d_Line(gp_Pnt2d(0, VIso), Dir), Udeb, Ufin); + HPCur = new Geom2dAdaptor_Curve(PCur2d); + } + else + { + if (!mySurface->IsUPeriodic()) + { + Standard_Real U1, U2; + Standard_Real dU = 10. * myTolU; + + U1 = mySurface->FirstUParameter(); + U2 = mySurface->LastUParameter(); + U1 -= dU; + U2 += dU; + + HS = HS->UTrim(U1, U2, 0.0); + } + + if (!mySurface->IsVPeriodic()) + { + Standard_Real V1, V2; + Standard_Real dV = 10. * myTolV; + + V1 = mySurface->FirstVParameter(); + V2 = mySurface->LastVParameter(); + V1 -= dV; + V2 += dV; + + HS = HS->VTrim(V1, V2, 0.0); + } + + Handle(ProjLib_CompProjectedCurve) HP = Handle(ProjLib_CompProjectedCurve)::DownCast(this->ShallowCopy()); + HP->Load(HS); + HPCur = HP; + } + + if (approx2d || approx3d) + { + Standard_Boolean only2d, only3d; + if (approx2d && approx3d) + { + only2d = !approx2d; + only3d = !approx3d; + } + else + { + only2d = approx2d; + only3d = approx3d; + } + + Approx_CurveOnSurface appr(HPCur, HS, Udeb, Ufin, myTol3d); + appr.Perform(myMaxSeg, myMaxDegree, myContinuity, only3d, only2d); + + if (approx2d) + { + PCur2d = appr.Curve2d(); + myResult2dUApproxError->SetValue(k, appr.MaxError2dU()); + myResult2dVApproxError->SetValue(k, appr.MaxError2dV()); + } + + if (approx3d) + { + PCur3d = appr.Curve3d(); + myResult3dApproxError->SetValue(k, appr.MaxError3d()); + } + } + + if (myProj2d == Standard_True) + { + myResult2dCurve->SetValue(k, PCur2d); + } + + if (myProj3d == Standard_True) + { + myResult3dCurve->SetValue(k, PCur3d); + } + } + } +} + +//======================================================================= +//function : SetTol3d +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetTol3d(const Standard_Real theTol3d) +{ + myTol3d = theTol3d; +} + +//======================================================================= +//function : SetContinuity +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetContinuity(const GeomAbs_Shape theContinuity) +{ + myContinuity = theContinuity; +} + +//======================================================================= +//function : SetMaxDegree +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetMaxDegree(const Standard_Integer theMaxDegree) +{ + if (theMaxDegree < 1) return; + myMaxDegree = theMaxDegree; +} + +//======================================================================= +//function : SetMaxSeg +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetMaxSeg(const Standard_Integer theMaxSeg) +{ + if (theMaxSeg < 1) return; + myMaxSeg = theMaxSeg; +} + +//======================================================================= +//function : SetProj3d +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetProj3d(const Standard_Boolean theProj3d) +{ + myProj3d = theProj3d; +} + +//======================================================================= +//function : SetProj2d +//purpose : +//======================================================================= +void ProjLib_CompProjectedCurve::SetProj2d(const Standard_Boolean theProj2d) +{ + myProj2d = theProj2d; +} + //======================================================================= //function : Load //purpose : @@ -1379,7 +1672,7 @@ void ProjLib_CompProjectedCurve::D0(const Standard_Real U,gp_Pnt2d& P) const ProjLib_PrjResolve aPrjPS (*myCurve, *mySurface, 1); aPrjPS.Perform(U, U0, V0, gp_Pnt2d(myTolU, myTolV), gp_Pnt2d(mySurface->FirstUParameter(), mySurface->FirstVParameter()), - gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter())); + gp_Pnt2d(mySurface->LastUParameter(), mySurface->LastVParameter()), FuncTol); if (aPrjPS.IsDone()) P = aPrjPS.Solution(); else @@ -1627,7 +1920,7 @@ void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const Solver.Perform((Tl + Tr)/2, CutPntsU(k), V, gp_Pnt2d(Tol, myTolV), gp_Pnt2d(Tl, mySurface->FirstVParameter()), - gp_Pnt2d(Tr, mySurface->LastVParameter())); + gp_Pnt2d(Tr, mySurface->LastVParameter()), FuncTol); // if(Solver.IsDone()) { @@ -1693,7 +1986,7 @@ void ProjLib_CompProjectedCurve::BuildIntervals(const GeomAbs_Shape S) const Solver.Perform((Tl + Tr)/2, U, CutPntsV(k), gp_Pnt2d(Tol, myTolV), gp_Pnt2d(Tl, mySurface->FirstUParameter()), - gp_Pnt2d(Tr, mySurface->LastUParameter())); + gp_Pnt2d(Tr, mySurface->LastUParameter()), FuncTol); // if(Solver.IsDone()) { @@ -1795,6 +2088,91 @@ GeomAbs_CurveType ProjLib_CompProjectedCurve::GetType() const return GeomAbs_OtherCurve; } +//======================================================================= +//function : ResultIsPoint +//purpose : +//======================================================================= + +Standard_Boolean ProjLib_CompProjectedCurve::ResultIsPoint(const Standard_Integer theIndex) const +{ + return myResultIsPoint->Value(theIndex); +} + +//======================================================================= +//function : GetResult2dUApproxError +//purpose : +//======================================================================= + +Standard_Real ProjLib_CompProjectedCurve::GetResult2dUApproxError(const Standard_Integer theIndex) const +{ + return myResult2dUApproxError->Value(theIndex); +} + +//======================================================================= +//function : GetResult2dVApproxError +//purpose : +//======================================================================= + +Standard_Real ProjLib_CompProjectedCurve::GetResult2dVApproxError(const Standard_Integer theIndex) const +{ + return myResult2dVApproxError->Value(theIndex); +} + +//======================================================================= +//function : GetResult3dApproxError +//purpose : +//======================================================================= + +Standard_Real ProjLib_CompProjectedCurve::GetResult3dApproxError(const Standard_Integer theIndex) const +{ + return myResult3dApproxError->Value(theIndex); +} + +//======================================================================= +//function : GetResult2dC +//purpose : +//======================================================================= + +Handle(Geom2d_Curve) ProjLib_CompProjectedCurve::GetResult2dC(const Standard_Integer theIndex) const +{ + return myResult2dCurve->Value(theIndex); +} + +//======================================================================= +//function : GetResult3dC +//purpose : +//======================================================================= + +Handle(Geom_Curve) ProjLib_CompProjectedCurve::GetResult3dC(const Standard_Integer theIndex) const +{ + return myResult3dCurve->Value(theIndex); +} + + +//======================================================================= +//function : GetResult2dP +//purpose : +//======================================================================= + +gp_Pnt2d ProjLib_CompProjectedCurve::GetResult2dP(const Standard_Integer theIndex) const +{ + Standard_TypeMismatch_Raise_if(!myResultIsPoint->Value(theIndex), + "ProjLib_CompProjectedCurve : result is not a point 2d"); + return myResult2dPoint->Value(theIndex); +} + +//======================================================================= +//function : GetResult3dP +//purpose : +//======================================================================= + +gp_Pnt ProjLib_CompProjectedCurve::GetResult3dP(const Standard_Integer theIndex) const +{ + Standard_TypeMismatch_Raise_if(!myResultIsPoint->Value(theIndex), + "ProjLib_CompProjectedCurve : result is not a point 3d"); + return myResult3dPoint->Value(theIndex); +} + //======================================================================= //function : UpdateTripleByTrapCriteria //purpose : @@ -1834,7 +2212,7 @@ void ProjLib_CompProjectedCurve::UpdateTripleByTrapCriteria(gp_Pnt &thePoint) co Standard_Real U,V; Standard_Boolean isDone = InitialPoint(myCurve->Value(thePoint.X()), thePoint.X(), myCurve, mySurface, - Precision::PConfusion(), Precision::PConfusion(), U, V); + Precision::PConfusion(), Precision::PConfusion(), U, V, myMaxDist); if (!isDone) return; diff --git a/src/ProjLib/ProjLib_CompProjectedCurve.hxx b/src/ProjLib/ProjLib_CompProjectedCurve.hxx index 0838670521..8c5fa21640 100644 --- a/src/ProjLib/ProjLib_CompProjectedCurve.hxx +++ b/src/ProjLib/ProjLib_CompProjectedCurve.hxx @@ -20,8 +20,15 @@ #include #include #include +#include +#include +#include +#include +#include #include #include +#include +#include #include #include #include @@ -44,6 +51,13 @@ public: //! equal then MaxDist. //! if MaxDist < 0 then algorithm works as above. Standard_EXPORT ProjLib_CompProjectedCurve(const Handle(Adaptor3d_Surface)& S, const Handle(Adaptor3d_Curve)& C, const Standard_Real TolU, const Standard_Real TolV, const Standard_Real MaxDist); + + //! this constructor tries to optimize the search using the + //! assumption that maximum distance between surface and curve less or + //! equal then MaxDist. + //! if MaxDist < 0 then algorithm try to find all solutions + //! Tolerances of parameters are calculated automatically. + Standard_EXPORT ProjLib_CompProjectedCurve(const Standard_Real Tol3d, const Handle(Adaptor3d_Surface)& S, const Handle(Adaptor3d_Curve)& C, const Standard_Real MaxDist = -1.0); //! Shallow copy of adaptor Standard_EXPORT virtual Handle(Adaptor2d_Curve2d) ShallowCopy() const Standard_OVERRIDE; @@ -54,6 +68,35 @@ public: //! included in this set of points. Standard_EXPORT void Init(); + //! Performs projecting for given curve. + //! If projecting uses approximation, + //! approximation parameters can be set before by corresponding methods + //! SetTol3d(...), SeContinuity(...), SetMaxDegree(...), SetMaxSeg(...) + Standard_EXPORT void Perform(); + + //! Set the parameter, which defines 3d tolerance of approximation. + Standard_EXPORT void SetTol3d(const Standard_Real theTol3d); + + //! Set the parameter, which defines curve continuity. + //! Default value is GeomAbs_C2; + Standard_EXPORT void SetContinuity(const GeomAbs_Shape theContinuity); + + //! Set max possible degree of result BSpline curve2d, which is got by approximation. + //! If MaxDegree < 0, algorithm uses values that are chosen depending of types curve 3d + //! and surface. + Standard_EXPORT void SetMaxDegree(const Standard_Integer theMaxDegree); + + //! Set the parameter, which defines maximal value of parametric intervals the projected + //! curve can be cut for approximation. If MaxSeg < 0, algorithm uses default + //! value = 16. + Standard_EXPORT void SetMaxSeg(const Standard_Integer theMaxSeg); + + //! Set the parameter, which defines necessity of 2d results. + Standard_EXPORT void SetProj2d(const Standard_Boolean theProj2d); + + //! Set the parameter, which defines necessity of 3d results. + Standard_EXPORT void SetProj3d(const Standard_Boolean theProj3d); + //! Changes the surface. Standard_EXPORT void Load (const Handle(Adaptor3d_Surface)& S); @@ -143,6 +186,44 @@ public: //! Parabola, BezierCurve, BSplineCurve, OtherCurve. Standard_EXPORT GeomAbs_CurveType GetType() const Standard_OVERRIDE; + //! Returns true if result of projecting of the curve interval + //! with number Index is point. + Standard_EXPORT Standard_Boolean ResultIsPoint(const Standard_Integer theIndex) const; + + //! Returns the error of approximation of U parameter 2d-curve as a result + //! projecting of the curve interval with number Index. + Standard_EXPORT Standard_Real GetResult2dUApproxError(const Standard_Integer theIndex) const; + + //! Returns the error of approximation of V parameter 2d-curve as a result + //! projecting of the curve interval with number Index. + Standard_EXPORT Standard_Real GetResult2dVApproxError(const Standard_Integer theIndex) const; + + //! Returns the error of approximation of 3d-curve as a result + //! projecting of the curve interval with number Index. + Standard_EXPORT Standard_Real GetResult3dApproxError(const Standard_Integer theIndex) const; + + //! Returns the resulting 2d-curve of projecting + //! of the curve interval with number Index. + Standard_EXPORT Handle(Geom2d_Curve) GetResult2dC(const Standard_Integer theIndex) const; + + //! Returns the resulting 3d-curve of projecting + //! of the curve interval with number Index. + Standard_EXPORT Handle(Geom_Curve) GetResult3dC(const Standard_Integer theIndex) const; + + //! Returns the resulting 2d-point of projecting + //! of the curve interval with number Index. + Standard_EXPORT gp_Pnt2d GetResult2dP(const Standard_Integer theIndex) const; + + //! Returns the resulting 3d-point of projecting + //! of the curve interval with number Index. + Standard_EXPORT gp_Pnt GetResult3dP(const Standard_Integer theIndex) const; + + //! Returns the parameter, which defines necessity of only 2d results. + Standard_Boolean GetProj2d() const { return myProj2d; } + + //! Returns the parameter, which defines necessity of only 3d results. + Standard_Boolean GetProj3d() const { return myProj3d; } + private: //! This method performs check possibility of optimization traps and tries to go out from them. @@ -157,14 +238,29 @@ private: Handle(Adaptor3d_Curve) myCurve; Standard_Integer myNbCurves; Handle(ProjLib_HSequenceOfHSequenceOfPnt) mySequence; - Standard_Real myTolU; - Standard_Real myTolV; - Standard_Real myMaxDist; Handle(TColStd_HArray1OfBoolean) myUIso; Handle(TColStd_HArray1OfBoolean) myVIso; Handle(TColStd_HArray1OfBoolean) mySnglPnts; Handle(TColStd_HArray1OfReal) myMaxDistance; Handle(TColStd_HArray1OfReal) myTabInt; + Standard_Real myTol3d; + GeomAbs_Shape myContinuity; + Standard_Integer myMaxDegree; + Standard_Integer myMaxSeg; + Standard_Boolean myProj2d; + Standard_Boolean myProj3d; + Standard_Real myMaxDist; + Standard_Real myTolU; + Standard_Real myTolV; + + Handle(TColStd_HArray1OfBoolean) myResultIsPoint; + Handle(TColStd_HArray1OfReal) myResult2dUApproxError; + Handle(TColStd_HArray1OfReal) myResult2dVApproxError; + Handle(TColStd_HArray1OfReal) myResult3dApproxError; + Handle(TColgp_HArray1OfPnt) myResult3dPoint; + Handle(TColgp_HArray1OfPnt2d) myResult2dPoint; + Handle(TColGeom_HArray1OfCurve) myResult3dCurve; + Handle(TColGeom2d_HArray1OfCurve) myResult2dCurve; }; DEFINE_STANDARD_HANDLE(ProjLib_CompProjectedCurve, Adaptor2d_Curve2d) diff --git a/src/ProjLib/ProjLib_PrjResolve.cxx b/src/ProjLib/ProjLib_PrjResolve.cxx index abd0f3ea8d..2ab6b58fd7 100644 --- a/src/ProjLib/ProjLib_PrjResolve.cxx +++ b/src/ProjLib/ProjLib_PrjResolve.cxx @@ -81,7 +81,7 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_ // if (!S1.IsDone()) { return; } // } // else { - math_NewtonFunctionSetRoot SR (F, Tol, 1.e-10); + math_NewtonFunctionSetRoot SR (F, Tol, FuncTol); SR.Perform(F, Start, BInf, BSup); // if (!SR.IsDone()) { return; } if (!SR.IsDone()) @@ -100,8 +100,8 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_ Standard_Real ExtraU , ExtraV; // if(!StrictInside) { - ExtraU = Tol2d.X(); - ExtraV = Tol2d.Y(); + ExtraU = 2. * Tol2d.X(); + ExtraV = 2. * Tol2d.Y(); // } if (mySolution.X() > Inf.X() - Tol2d.X() && mySolution.X() < Inf.X()) mySolution.SetX(Inf.X()); if (mySolution.X() > Sup.X() && mySolution.X() < Sup.X() + Tol2d.X()) mySolution.SetX(Sup.X()); @@ -119,7 +119,9 @@ ProjLib_PrjResolve::ProjLib_PrjResolve(const Adaptor3d_Curve& C,const Adaptor3d_ F.Value(X, FVal); - if ((FVal(1)*FVal(1) + FVal(2)*FVal(2)) > FuncTol) myDone = Standard_False; + if (!SR.IsDone()) { + if ((FVal(1)*FVal(1) + FVal(2)*FVal(2)) > FuncTol) myDone = Standard_False; + } } diff --git a/tests/bugs/modalg_5/bug25980 b/tests/bugs/modalg_5/bug25980 index 30ea9566af..1d711a815b 100644 --- a/tests/bugs/modalg_5/bug25980 +++ b/tests/bugs/modalg_5/bug25980 @@ -1,5 +1,3 @@ -puts "REQUIRED All: Projection Failed" - puts "========" puts "OCC25980" puts "========" @@ -13,7 +11,6 @@ restore [locate_data_file s1t.draw] s set bug_info [catch {project x c s}] -# Projection should fail due to big distance of projection at curve beginning -if {$bug_info == 0} { +if {$bug_info == 1} { puts "ERROR: OCC25980 is reproduced." } diff --git a/tests/bugs/modalg_7/bug24185 b/tests/bugs/modalg_7/bug24185 index 671537ef6d..6868c32de6 100644 --- a/tests/bugs/modalg_7/bug24185 +++ b/tests/bugs/modalg_7/bug24185 @@ -1,5 +1,3 @@ -puts "TODO OCC24185 ALL: Error : The length of result shape is" - puts "========" puts "OCC24185" puts "========" @@ -11,7 +9,7 @@ puts "" restore [locate_data_file bug24185_face.brep] f restore [locate_data_file bug24185_wire.brep] w -nproject result w f +nproject result w f 1.e-4 1 checkshape result checkprops result -l 11.06 diff --git a/tests/bugs/moddata_3/bug30046 b/tests/bugs/moddata_3/bug30046 new file mode 100644 index 0000000000..3e422bbafd --- /dev/null +++ b/tests/bugs/moddata_3/bug30046 @@ -0,0 +1,65 @@ +puts "================" +puts "0030046: Modeling Data - Cannot find necessary projection of the curve" +puts "================" +puts "" + +set BugNumber OCC30046 + +restore [locate_data_file bug30046_cur.brep] c +restore [locate_data_file bug30046_sur.brep] s + +gproject result c s 1.e-3 -2d 1 -3d 1 +gproject result_maxdist c s 1.e-7 2. -2d 1 -3d 1 + +regexp {is ([-0-9.+eE]+)} [length result2d_1] full ll +set len_result2d $ll + +regexp {is ([-0-9.+eE]+)} [length result_maxdist2d_1] full ll +set len_result_maxdist2d $ll + +if {$len_result2d < $len_result_maxdist2d} { + puts "Faulty ${BugNumber}: length of a 2d projection, built with a smaller tolerance, must be less"; +} + +regexp {is ([-0-9.+eE]+)} [length result_1] full ll +set len_result $ll + +regexp {is ([-0-9.+eE]+)} [length result_maxdist_1] full ll +set len_result_maxdist $ll + +if {$len_result < $len_result_maxdist} { + puts "Faulty ${BugNumber}: length of a 3d projection, built with a smaller tolerance, must be less"; +} + +set tol_abs 1.0e-4 +set tol_rel 0.0001 + +set bounds_result2d_1 [gbounding result2d_1] +regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $bounds_result2d_1 full v1_x v1_y v2_x v2_y + +set expected_v1_x 0.050141663706179646 +checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel} + +set expected_v1_y 0.00039517687539122789 +checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel} + +set expected_v2_x 0.24709337491832356 +checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel} + +set expected_v2_y 0.00044697332650299172 +checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel} + +set bounds_result_maxdist_1 [gbounding result_maxdist2d_1] +regexp { *([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+) +([-0-9.+eE]+)} $bounds_result_maxdist_1 full v1_x v1_y v2_x v2_y + +set expected_v1_x 0.050141663706179958 +checkreal "v1_x" ${v1_x} ${expected_v1_x} ${tol_abs} ${tol_rel} + +set expected_v1_y 0.00039517687539122805 +checkreal "v1_y" ${v1_y} ${expected_v1_y} ${tol_abs} ${tol_rel} + +set expected_v2_x 0.24708119728076677 +checkreal "v2_x" ${v2_x} ${expected_v2_x} ${tol_abs} ${tol_rel} + +set expected_v2_y 0.00044696841766235214 +checkreal "v2_y" ${v2_y} ${expected_v2_y} ${tol_abs} ${tol_rel} \ No newline at end of file