From 680338d6f39081ad2191ceb43aaa066927f108cd Mon Sep 17 00:00:00 2001 From: ifv Date: Fri, 25 May 2018 15:21:04 +0300 Subject: [PATCH] 0027651: Add projection support in sewing pcurves handling 1. BRepLib.hxx, BRepLib_1.cxx - implementation of method SetPCurve(...), which can build new pcurve by projection, if pcurve to be set is not satisfied by tolerance criterium. 2. BRepBuilderAPI_Sewing.cxx - modification of method SameParameterEdge(...) using new method SetPCurve(...) 3. BRepTest/BRepTest_BasicCommands.cxx - implementation Draw command SetPCurve 4. Approx_ComputeCLine.gxx, BRepOffsetAPI_DraftAngle.cxx, ProjLib_ProjectedCurve.cxx - small modification to fix regression. 5. Modification of tests according to current behavior of sewing algorithm. 6. Test case added bugs/modalg_6/bug27651 7. dox/user_guides/draw_test_harness/draw_test_harness.md Documentation update. --- .../draw_test_harness/draw_test_harness.md | 15 +- src/Approx/Approx_ComputeCLine.gxx | 4 +- src/BRepBuilderAPI/BRepBuilderAPI_Sewing.cxx | 149 ++++--- src/BRepLib/BRepLib.hxx | 28 ++ src/BRepLib/BRepLib_1.cxx | 391 +++++++++++++++++- .../BRepOffsetAPI_DraftAngle.cxx | 16 +- src/BRepTest/BRepTest_BasicCommands.cxx | 28 ++ src/ProjLib/ProjLib_ProjectedCurve.cxx | 2 +- tests/bugs/modalg_2/bug22770_13 | 2 +- tests/bugs/modalg_2/bug22770_15 | 2 +- tests/bugs/modalg_2/bug22804 | 2 +- tests/bugs/modalg_4/bug714 | 2 +- tests/bugs/modalg_5/bug25175 | 2 +- tests/bugs/modalg_6/bug27651 | 32 ++ tests/bugs/xde/bug547_2 | 2 +- tests/lowalgos/intss/bug26684_1 | 2 +- tests/lowalgos/intss/bug27263 | 2 +- tests/sewing/tol_100/D3 | 2 +- tests/sewing/tol_100/I5 | 4 +- tests/sewing/tol_100/J1 | 2 +- tests/sewing/tol_100/J2 | 2 +- 21 files changed, 615 insertions(+), 76 deletions(-) create mode 100644 tests/bugs/modalg_6/bug27651 diff --git a/dox/user_guides/draw_test_harness/draw_test_harness.md b/dox/user_guides/draw_test_harness/draw_test_harness.md index b5ae421a01..230bcc053f 100644 --- a/dox/user_guides/draw_test_harness/draw_test_harness.md +++ b/dox/user_guides/draw_test_harness/draw_test_harness.md @@ -6093,6 +6093,7 @@ This group of commands is used to create topology from shapes and to extract sha * To create faces, use the **mkplane**, **mkface** commands. * To extract the geometry from edges or faces, use the **mkcurve** and **mkface** commands. * To extract the 2d curves from edges or faces, use the **pcurve** command. + * To add/set the 2d curves to edges of face, use the **addpcurve** or **setpcurve** command. @subsubsection occt_draw_7_2_1 vertex @@ -6415,14 +6416,16 @@ vertex v2 10 0 0 edge e v1 v2 ~~~~~ -@subsubsection occt_draw_7_2_9 pcurve +@subsubsection occt_draw_7_2_9 pcurve, addpcurve, setpcurve Syntax: ~~~~~ pcurve [name edgename] facename +addpcurve edge 2dcurve face [tol (default 1.e-7)] +setpcurve edge 2dcurve face [tol (default 1.e-4)] ~~~~~ - +**pcurve** Extracts the 2d curve of an edge on a face. If only the face is specified, the command extracts all the curves and colors them according to their orientation. This is useful in checking to see if the edges in a face are correctly oriented, i.e. they turn counter-clockwise. To make curves visible, use a fitted 2d view. **Example:** @@ -6436,6 +6439,14 @@ pcurve p 2dfit ~~~~~ +**addpcurve**, +Add given pcurve to edge of face, update edge tolerance. + +**setpcurve** +Add given pcurve to edge, if pcurve cannot be set with tolerance less then tol, +algorithm builds new pcurve by projecting edge on face and sets it. + + @subsubsection occt_draw_7_2_10 chfi2d Syntax: diff --git a/src/Approx/Approx_ComputeCLine.gxx b/src/Approx/Approx_ComputeCLine.gxx index c9e7ed838d..f35eed4deb 100644 --- a/src/Approx/Approx_ComputeCLine.gxx +++ b/src/Approx/Approx_ComputeCLine.gxx @@ -178,10 +178,12 @@ void Approx_ComputeCLine::Perform(const MultiLine& Line) Standard_Boolean aStopCutting = Standard_False; if (aNbCut >= aNbComp) { - if (aNbCut > aNbImp) + if (aNbCut > aNbImp + 1) { aStopCutting = Standard_True; } + aNbCut = 0; + aNbImp = 0; } // is new decision better? if (!Ok && (Abs(myfirstU - mylastU) <= TolU || aMaxSegments >= aMaxSegments1 || aStopCutting )) diff --git a/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.cxx b/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.cxx index aa9fb08a1f..07639cec0b 100644 --- a/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.cxx +++ b/src/BRepBuilderAPI/BRepBuilderAPI_Sewing.cxx @@ -587,6 +587,7 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs // Sort input edges TopoDS_Edge edge1, edge2; + Standard_Real aTolMax = Precision::Infinite(); if (firstCall) { // Take the longest edge as first Standard_Real f, l; @@ -600,11 +601,13 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs edge1 = edgeLast; edge2 = edgeFirst; whichSec = 2; + aTolMax = len2 / 2.; } else { edge1 = edgeFirst; edge2 = edgeLast; whichSec = 1; + aTolMax = len1 / 2.; } } else { @@ -747,7 +750,7 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs TopLoc_Location loc2; Handle(Geom_Surface) surf2; - //Handle(Geom2d_Curve) c2d2, c2d21; + Handle(Geom2d_Curve) c2d2edge; // Standard_Real firstOld, lastOld; TopTools_ListIteratorOfListOfShape itf2; @@ -755,6 +758,7 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs else itf2.Initialize(listFacesFirst); Standard_Boolean isResEdge = Standard_False; TopoDS_Face fac2; + Standard_Boolean isSeam2edge = Standard_False; for (; itf2.More(); itf2.Next()) { Handle(Geom2d_Curve) c2d2, c2d21; Standard_Real firstOld, lastOld; @@ -763,6 +767,7 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs surf2 = BRep_Tool::Surface(fac2, loc2); Standard_Boolean isSeam2 = ((IsUClosedSurface(surf2,edge2,loc2) || IsVClosedSurface(surf2,edge2,loc2)) && BRep_Tool::IsClosed(TopoDS::Edge(edge2),fac2)); + isSeam2edge = isSeam2; if (isSeam2) { if (!myNonmanifold) return TopoDS_Edge(); TopoDS_Shape aTmpShape = edge2.Reversed(); //for porting @@ -770,7 +775,6 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs } c2d2 = BRep_Tool::CurveOnSurface(edge2, fac2, firstOld, lastOld); if (c2d2.IsNull() && c2d21.IsNull()) continue; - if (!c2d21.IsNull()) { c2d21 = Handle(Geom2d_Curve)::DownCast(c2d21->Copy()); if (!secForward) { @@ -800,7 +804,9 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs c2d2 = SameRange(c2d2,firstOld,lastOld,first,last); if (c2d2.IsNull()) continue; - + // + c2d2edge = c2d2; + // // Add second PCurve Standard_Boolean isSeam = Standard_False; TopAbs_Orientation Ori = TopAbs_FORWARD; @@ -890,6 +896,20 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs } Standard_Real tolReached = Precision::Infinite(); Standard_Boolean isSamePar = Standard_False; + // Save initial tolerances of edge before SameParameter + Standard_Real aToledge = BRep_Tool::Tolerance(edge); + TopoDS_Vertex aV1edge, aV2edge; + TopExp::Vertices(edge, aV1edge, aV2edge); + Standard_Real aTolV1 = Precision::Confusion(), aTolV2 = Precision::Confusion(); + // + if (!aV1edge.IsNull()) + { + aTolV1 = BRep_Tool::Tolerance(aV1edge); + } + if (!aV2edge.IsNull()) + { + aTolV2 = BRep_Tool::Tolerance(aV2edge); + } try { if( isResEdge) @@ -903,23 +923,23 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs } } - catch(Standard_Failure const&) + catch(Standard_Failure) { isSamePar = Standard_False; } - if (firstCall && ( !isResEdge || !isSamePar || tolReached > myTolerance)) { + if (firstCall && (!isResEdge || !isSamePar || tolReached > myTolerance)) { Standard_Integer whichSecn = whichSec; // Try to merge on the second section Standard_Boolean second_ok = Standard_False; - TopoDS_Edge s_edge = SameParameterEdge(edgeFirst,edgeLast,listFacesFirst,listFacesLast, - secForward,whichSecn,Standard_False); - if( !s_edge.IsNull()) + TopoDS_Edge s_edge = SameParameterEdge(edgeFirst, edgeLast, listFacesFirst, listFacesLast, + secForward, whichSecn, Standard_False); + if (!s_edge.IsNull()) { - Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge); - second_ok = ( BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached ); - if( second_ok) + Standard_Real tolReached_2 = BRep_Tool::Tolerance(s_edge); + second_ok = (BRep_Tool::SameParameter(s_edge) && tolReached_2 < tolReached); + if (second_ok) { edge = s_edge; whichSec = whichSecn; @@ -929,56 +949,73 @@ TopoDS_Edge BRepBuilderAPI_Sewing::SameParameterEdge(const TopoDS_Edge& edgeFirs if (!second_ok && !edge.IsNull()) { - GeomAdaptor_Curve c3dAdapt(c3d); - - // Discretize edge curve - Standard_Integer i, j, nbp = 23; - Standard_Real deltaT = (last3d - first3d) / (nbp -1); - TColgp_Array1OfPnt c3dpnt(1,nbp); - for (i = 1; i <= nbp; i++) - c3dpnt(i) = c3dAdapt.Value(first3d + (i-1)*deltaT); - - Standard_Real dist = 0., maxTol = -1.0; - Standard_Boolean more = Standard_True; - - for (j = 1; more; j++) { - Handle(Geom2d_Curve) c2d2; - BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j); - - more = !c2d2.IsNull(); - if (more) { - Handle(Geom_Surface) aS = surf2; - if(!loc2.IsIdentity()) - aS = Handle(Geom_Surface)::DownCast(surf2->Transformed ( loc2 )); - - Standard_Real dist2 = 0.; - deltaT = (last - first) / (nbp - 1); - for (i = 1; i <= nbp; i++) { - gp_Pnt2d aP2d = c2d2->Value(first + (i -1)*deltaT); - gp_Pnt aP2(0.,0.,0.); - aS->D0(aP2d.X(),aP2d.Y(), aP2); - gp_Pnt aP1 = c3dpnt(i); - dist = aP2.SquareDistance(aP1); - if (dist > dist2) - dist2 = dist; - } - maxTol = Max(sqrt(dist2) * (1. + 1e-7), Precision::Confusion()); - } + Handle(Geom2d_Curve) aProjCurve; + Standard_Real aTolReached_3 = RealLast(); + if (!isSeam2edge && myTolerance < aTolMax) + { + static_cast(edge.TShape().get())->Tolerance(aToledge); + static_cast(aV1edge.TShape().get())->Tolerance(aTolV1); + static_cast(aV2edge.TShape().get())->Tolerance(aTolV2); + + BRepLib::SetPCurve(edge, c2d2edge, fac2, myTolerance, + aTolReached_3, aProjCurve); } - if (maxTol >= 0. && maxTol < tolReached) + else { - if (tolReached > MaxTolerance()) - { - // Set tolerance directly to overwrite too large tolerance - static_cast(edge.TShape().get())->Tolerance(maxTol); + // + GeomAdaptor_Curve c3dAdapt(c3d); + + // Discretize edge curve + Standard_Integer i, j, nbp = 23; + Standard_Real deltaT = (last3d - first3d) / (nbp - 1); + TColgp_Array1OfPnt c3dpnt(1, nbp); + for (i = 1; i <= nbp; i++) + c3dpnt(i) = c3dAdapt.Value(first3d + (i - 1)*deltaT); + + Standard_Real dist = 0., maxTol = -1.0; + Standard_Boolean more = Standard_True; + + for (j = 1; more; j++) { + Handle(Geom2d_Curve) c2d2; + BRep_Tool::CurveOnSurface(edge, c2d2, surf2, loc2, first, last, j); + + more = !c2d2.IsNull(); + if (more) { + Handle(Geom_Surface) aS = surf2; + if (!loc2.IsIdentity()) + aS = Handle(Geom_Surface)::DownCast(surf2->Transformed(loc2)); + + Standard_Real dist2 = 0.; + deltaT = (last - first) / (nbp - 1); + for (i = 1; i <= nbp; i++) { + gp_Pnt2d aP2d = c2d2->Value(first + (i - 1)*deltaT); + gp_Pnt aP2(0., 0., 0.); + aS->D0(aP2d.X(), aP2d.Y(), aP2); + gp_Pnt aP1 = c3dpnt(i); + dist = aP2.SquareDistance(aP1); + if (dist > dist2) + dist2 = dist; + } + maxTol = Max(sqrt(dist2) * (1. + 1e-7), Precision::Confusion()); + } } - else + if (maxTol >= 0. && maxTol < tolReached) { - // just update tolerance with computed distance - aBuilder.UpdateEdge(edge, maxTol); + if (tolReached > MaxTolerance()) + { + // Set tolerance directly to overwrite too large tolerance + static_cast(edge.TShape().get())->Tolerance(maxTol); + } + else + { + // just update tolerance with computed distance + aBuilder.UpdateEdge(edge, maxTol); + aBuilder.UpdateVertex(aV1edge, maxTol); + aBuilder.UpdateVertex(aV2edge, maxTol); + } } + aBuilder.SameParameter(edge, Standard_True); } - aBuilder.SameParameter(edge,Standard_True); } } @@ -4744,7 +4781,7 @@ void BRepBuilderAPI_Sewing::SameParameterShape() BRepLib::SameParameter(sec, BRep_Tool::Tolerance(sec)); } - catch (Standard_Failure const&) { + catch (Standard_Failure) { #ifdef OCCT_DEBUG std::cout << "Fail: BRepBuilderAPI_Sewing::SameParameterShape exception in BRepLib::SameParameter" << std::endl; #endif diff --git a/src/BRepLib/BRepLib.hxx b/src/BRepLib/BRepLib.hxx index 5bd8823082..b8039cf702 100644 --- a/src/BRepLib/BRepLib.hxx +++ b/src/BRepLib/BRepLib.hxx @@ -114,6 +114,34 @@ public: //! return False if one of the computation failed. Standard_EXPORT static Standard_Boolean BuildCurves3d (const TopoDS_Shape& S); + //! Sets a pcurve theC for the edge theE on the face theF. + //! Setting pcurve can include calling sameparameter algorithm. + //! theMaxTol is the maximal tolerance allowed for pcurve. + //! If given pcurve cannot be set with tolerance less then theMaxtol, + //! algorithm builds new pcurve by projecting edge on face and sets curve, + //! which provides minimal tolerance. If projecting was done, algorithm sets + //! result of projecting in theProjCurve + //! Algorithm sets in theTolReached tolerance of edge after setting pcurve. + Standard_EXPORT static void SetPCurve(const TopoDS_Edge& theE, + const Handle(Geom2d_Curve)& theC, + const TopoDS_Face& theF, const Standard_Real theMaxTol, + Standard_Real& theTolReached, Handle(Geom2d_Curve)& theProjCurve); + + //! Sets the pcurve theC1, theC2 for the edge theE on the closed face theF. + //! Setting pcurve can include calling sameparameter algorithm. + //! theMaxTol is the maximal tolerance allowed for pcurve. + //! If given pcurve cannot be set with tolerance less then theMaxtol, + //! algorithm builds new pcurves by projecting edge on face and sets curves, + //! which provides minimal tolerance. If projecting was done, algorithm sets + //! result of projecting in theProjCurve1 and theProjCurve2. + //! Algorithm sets in theTolReached tolerance of edge after setting pcurve. + Standard_EXPORT static void SetPCurve(const TopoDS_Edge& theE, + const Handle(Geom2d_Curve)& theC1, const Handle(Geom2d_Curve)& theC2, + const TopoDS_Face& theF, const Standard_Real theMaxTol, + Standard_Real& theTolReached, + Handle(Geom2d_Curve)& theProjCurve1, + Handle(Geom2d_Curve)& theProjCurve2); + //! Builds pcurve of edge on face if the surface is plane, and updates the edge. Standard_EXPORT static void BuildPCurveForEdgeOnPlane(const TopoDS_Edge& theE, const TopoDS_Face& theF); diff --git a/src/BRepLib/BRepLib_1.cxx b/src/BRepLib/BRepLib_1.cxx index 5fe6d8c177..af3ebc36ca 100644 --- a/src/BRepLib/BRepLib_1.cxx +++ b/src/BRepLib/BRepLib_1.cxx @@ -21,7 +21,20 @@ #include #include #include - +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include //======================================================================= // function: findNearestValidPoint // purpose : Starting from the appointed end of the curve, find the nearest @@ -282,3 +295,379 @@ void BRepLib::BuildPCurveForEdgeOnPlane(const TopoDS_Edge& aE, aC2D = BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2, &isStored); bToUpdate = !isStored && !aC2D.IsNull(); } +//======================================================================= +//function : CompTol +//purpose : +//======================================================================= +static Standard_Real CompTol(const Handle(Geom_Curve)& theC3D, + const Handle(Geom2d_Curve)& theC2D, + const Handle(Geom_Surface)& theS, + const Standard_Real theFirstPar, + const Standard_Real theLastPar) +{ + Standard_Real aTolRange = Max(Precision::PConfusion(), + 0.001 * (theLastPar - theFirstPar)); + GeomLib_CheckCurveOnSurface aCheckDist(theC3D, theS, theFirstPar, theLastPar, aTolRange); + aCheckDist.Perform(theC2D); + Standard_Real aTolR = 0.; + if (aCheckDist.IsDone()) + { + aTolR = aCheckDist.MaxDistance(); + } + else + { + const Standard_Integer aNbPnts = 23; + TColStd_Array1OfReal aPars(1, aNbPnts); + Standard_Integer i; + Standard_Real t, dt = (theLastPar - theFirstPar) / (aNbPnts - 1); + aPars(1) = theFirstPar; + aPars(aNbPnts) = theLastPar; + for (i = 2, t = theFirstPar + dt; i < aNbPnts; ++i, t += dt) + { + aPars(i) = t; + } + Handle(Geom2dAdaptor_HCurve) aG2dAHC = new Geom2dAdaptor_HCurve(theC2D); + GeomAdaptor_Curve aGAC(theC3D); + Handle(GeomAdaptor_HSurface) aGAHS = new GeomAdaptor_HSurface(theS); + Adaptor3d_CurveOnSurface aConS(aG2dAHC, aGAHS); + GeomLib::EvalMaxParametricDistance(aConS, aGAC, 1., aPars, aTolR); + aTolR *= 1.5; //possible deflection + } + + return aTolR; +} +//======================================================================= +//function : UpdateTol +//purpose : +//======================================================================= +static void UpdateTol(const TopoDS_Edge& theE, const Standard_Real theTol) +{ + BRep_Builder aBB; + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(theE, aV1, aV2); + if (!aV1.IsNull()) + { + aBB.UpdateVertex(aV1, theTol); + } + if (!aV2.IsNull()) + { + aBB.UpdateVertex(aV2, theTol); + } + aBB.UpdateEdge(theE, theTol); +} + +//======================================================================= +//function : SetPCurve +//purpose : +//======================================================================= +void BRepLib::SetPCurve(const TopoDS_Edge& theE, + const Handle(Geom2d_Curve)& theC, + const TopoDS_Face& theF, + const Standard_Real theMaxTol, + Standard_Real& theTolReached, Handle(Geom2d_Curve)& theProjCurve) +{ + Standard_Real aSMTol = Precision::PConfusion(); + Standard_Real aTol = BRep_Tool::Tolerance(theE); + BRep_Builder aBB; + Standard_Real fr, lr, f, l; + BRep_Tool::Range(theE, fr, lr); + Handle(Geom2d_Curve) aC = theC; + f = theC->FirstParameter(); + l = theC->LastParameter(); + if (!(Precision::IsInfinite(f) || Precision::IsInfinite(l))) + { + GeomLib::SameRange(aSMTol, theC, f, l, fr, lr, aC); + } + aBB.UpdateEdge(theE, aC, theF, aTol); + Handle(Geom_Surface) anS = BRep_Tool::Surface(theF); + Handle(Geom_Curve) aC3D = BRep_Tool::Curve(theE, f, l); + Standard_Real aTol1 = CompTol(aC3D, aC, anS, fr, lr); + if (aTol1 <= aTol) + { + theTolReached = aTol1; + aBB.SameParameter(theE, Standard_True); + return; + } + else if (theMaxTol < aTol && aTol1 < 2.*aTol) + { + theTolReached = aTol1; + UpdateTol(theE, theTolReached); + return; + } + aBB.SameParameter(theE, Standard_False); + Standard_Real aNewTol = -1; + BRepLib::SameParameter(theE, aTol, aNewTol, Standard_True); + if (aNewTol > 0) + { + //Set old tolerance for edge, which has been changed by sameparameter + static_cast(theE.TShape().get())->Tolerance(aTol); + } + if (aNewTol > 0.) + { + aC = BRep_Tool::CurveOnSurface(theE, theF, f, l); + aNewTol = CompTol(aC3D, aC, anS, fr, lr); + if (aNewTol < theMaxTol) + { + aBB.SameParameter(theE, Standard_True); + theTolReached = aNewTol; + UpdateTol(theE, theTolReached); + return ; + } + } + //Projection + Handle(BRepAdaptor_HSurface) aBAHS = + new BRepAdaptor_HSurface(BRepAdaptor_Surface(theF, Standard_False)); + Handle(BRepAdaptor_HCurve) aBAHC = new BRepAdaptor_HCurve(theE); + ProjLib_ProjectedCurve aProjCurv(aBAHS); + Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1; + Standard_Real aMaxDist = Max(1.e3 * theMaxTol, aNewTol); + Standard_Real aTR = Precision::Confusion(); + Standard_Real aMaxTol = 1.e3 * aTR; //0.0001 + Standard_Boolean isAnaSurf = ProjLib::IsAnaSurf(aBAHS); + AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint; + if (theMaxTol >= aMaxTol || aNewTol > 10. * theMaxTol) + { + aTR = aMaxTol; + if (aNewTol >= 1.) + { + aTR = Min(10. * aTR, theMaxTol); + } + if (!isAnaSurf ) + { + aBndPnt = AppParCurves_PassPoint; + } + } + // + theTolReached = RealLast(); + aProjCurv.Load(aTR); + aProjCurv.SetDegree(aDegMin, aDegMax); + aProjCurv.SetMaxSegments(aMaxSegments); + aProjCurv.SetBndPnt(aBndPnt); + aProjCurv.SetMaxDist(aMaxDist); + aProjCurv.Perform(aBAHC); + ProjLib::MakePCurveOfType(aProjCurv, theProjCurve); + if (!theProjCurve.IsNull()) + { + Standard_Real pf = theProjCurve->FirstParameter(), + pl = theProjCurve->LastParameter(); + if (!(Precision::IsInfinite(pf) || Precision::IsInfinite(pl))) + { + if (Abs(pf - fr) > aSMTol || Abs(pl - lr) > aSMTol) + { + aC.Nullify(); + GeomLib::SameRange(aSMTol, theProjCurve, pf, pl, fr, lr, aC); + if (!aC.IsNull() && theProjCurve != aC) + { + theProjCurve = aC; + } + } + } + Standard_Real aTolR = CompTol(aC3D, theProjCurve, anS, fr, lr); + // + if ((aNewTol > 0. && aTolR < aNewTol) || aNewTol < 0.) + { + theTolReached = aTolR; + // + //Set new pcurve + aBB.UpdateEdge(theE, theProjCurve, theF, theTolReached); + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } + else + { + if (aNewTol > 0.) + { + theTolReached = aNewTol; + } + else + { + theTolReached = aTol1; + } + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } + } + else + { + if (aNewTol > 0.) + { + theTolReached = aNewTol; + } + else + { + theTolReached = aTol1; + } + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } +} +//======================================================================= +//function : SetPCurve +//purpose : +//======================================================================= +void BRepLib::SetPCurve(const TopoDS_Edge& theE, + const Handle(Geom2d_Curve)& theC1, const Handle(Geom2d_Curve)& theC2, + const TopoDS_Face& theF, + const Standard_Real theMaxTol, + Standard_Real& theTolReached, + Handle(Geom2d_Curve)& theProjCurve1, + Handle(Geom2d_Curve)& theProjCurve2) +{ + Standard_Real aSMTol = Precision::PConfusion(); + Standard_Real aTol = BRep_Tool::Tolerance(theE); + BRep_Builder aBB; + Standard_Real fr, lr, f, l; + BRep_Tool::Range(theE, fr, lr); + Handle(Geom2d_Curve) aC1 = theC1, aC2 = theC2; + f = theC1->FirstParameter(); + l = theC1->LastParameter(); + if (!(Precision::IsInfinite(f) || Precision::IsInfinite(l))) + { + GeomLib::SameRange(aSMTol, theC1, f, l, fr, lr, aC1); + } + f = theC2->FirstParameter(); + l = theC2->LastParameter(); + if (!(Precision::IsInfinite(f) || Precision::IsInfinite(l))) + { + GeomLib::SameRange(aSMTol, theC2, f, l, fr, lr, aC2); + } + aBB.UpdateEdge(theE, aC1, aC2, theF, aTol); + Handle(Geom_Surface) anS = BRep_Tool::Surface(theF); + Handle(Geom_Curve) aC3D = BRep_Tool::Curve(theE, f, l); + Standard_Real aTol1 = CompTol(aC3D, aC1, anS, fr, lr); + aTol1 = Max(aTol1, CompTol(aC3D, aC2, anS, fr, lr)); + if (aTol1 <= aTol) + { + theTolReached = aTol1; + aBB.SameParameter(theE, Standard_True); + return; + } + aBB.SameParameter(theE, Standard_False); + Standard_Real aNewTol = -1; + BRepLib::SameParameter(theE, aTol, aNewTol, Standard_False); + if (aNewTol > 0) + { + //Set old tolerance for edge, which has been changed by sameparameter + static_cast(theE.TShape().get())->Tolerance(aTol); + } + if (aNewTol > 0. && aNewTol < theMaxTol) + { + TopoDS_Vertex aV1, aV2; + TopExp::Vertices(theE, aV1, aV2); + if (!aV1.IsNull()) + { + aBB.UpdateVertex(aV1, aNewTol); + } + if (!aV2.IsNull()) + { + aBB.UpdateVertex(aV2, aNewTol); + } + theTolReached = aNewTol; + return; + } + //Projection + Handle(BRepAdaptor_HSurface) aBAHS = new BRepAdaptor_HSurface(theF); + Handle(BRepAdaptor_HCurve) aBAHC = new BRepAdaptor_HCurve(theE); + ProjLib_ProjectedCurve aProjCurv(aBAHS); + Standard_Integer aDegMin = -1, aDegMax = -1, aMaxSegments = -1; + Standard_Real aMaxDist = Max(1.e3 * theMaxTol, aNewTol); + Standard_Real aTR = Precision::Confusion(); + Standard_Real aMaxTol = 1.e3 * aTR; //0.0001 + Standard_Boolean isAnaSurf = ProjLib::IsAnaSurf(aBAHS); + AppParCurves_Constraint aBndPnt = AppParCurves_TangencyPoint; + if (theMaxTol >= aMaxTol || aNewTol > 10. * theMaxTol) + { + aTR = aMaxTol; + if (aNewTol >= 1.) + { + aTR = Min(10. * aTR, theMaxTol); + } + if (!isAnaSurf) + { + aBndPnt = AppParCurves_PassPoint; + } + } + // + theTolReached = RealLast(); + aProjCurv.Load(aTR); + aProjCurv.SetDegree(aDegMin, aDegMax); + aProjCurv.SetMaxSegments(aMaxSegments); + aProjCurv.SetBndPnt(aBndPnt); + aProjCurv.SetMaxDist(aMaxDist); + aProjCurv.Perform(aBAHC); + Handle(Geom2d_Curve) aCProj; + ProjLib::MakePCurveOfType(aProjCurv, aCProj); + if (!aCProj.IsNull()) + { + Standard_Real pf = aCProj->FirstParameter(), + pl = aCProj->LastParameter(); + if (!(Precision::IsInfinite(pf) || Precision::IsInfinite(pl))) + { + if (Abs(pf - fr) > aSMTol || Abs(pl - lr) > aSMTol) + { + aC1.Nullify(); + GeomLib::SameRange(aSMTol, aCProj, pf, pl, fr, lr, aC1); + if (!aC1.IsNull() && aCProj != aC1) + { + aCProj = aC1; + } + } + } + Standard_Real aTolR = CompTol(aC3D, aCProj, anS, fr, lr); + // + if ((aNewTol > 0. && aTolR < aNewTol) || aNewTol < 0.) + { + theTolReached = aTolR; + // + gp_Pnt2d aP1, aP2, aPProj; + Handle(Geom2d_Curve) aPC = BRep_Tool::CurveOnSurface(theE, theF, f, l); + aP1 = aPC->Value(f); + aPC = BRep_Tool::CurveOnSurface(TopoDS::Edge(theE.Reversed()), theF, f, l); + aP2 = aPC->Value(f); + aPProj = aCProj->Value(f); + Standard_Real Dist1, Dist2; + Dist1 = aPProj.Distance(aP1); + Dist2 = aPProj.Distance(aP2); + if (Dist1 < Dist2) { + theProjCurve1 = aCProj; + Handle(Geom2d_Geometry) GG = aCProj->Translated(aP1, aP2); + theProjCurve2 = Handle(Geom2d_Curve)::DownCast(GG); + } + else { + theProjCurve2 = aCProj; + Handle(Geom2d_Geometry) GG = aCProj->Translated(aP2, aP1); + theProjCurve1 = Handle(Geom2d_BSplineCurve)::DownCast(GG); + } + //Set new pcurves + aBB.UpdateEdge(theE, theProjCurve1, theProjCurve2, theF, aTolR); + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } + else + { + if (aNewTol > 0.) + { + theTolReached = aNewTol; + } + else + { + theTolReached = aTol1; + } + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } + } + else + { + if (aNewTol > 0.) + { + theTolReached = aNewTol; + } + else + { + theTolReached = aTol1; + } + UpdateTol(theE, theTolReached); + aBB.SameParameter(theE, Standard_True); + } +} \ No newline at end of file diff --git a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx index 50eadac75b..149729d2ae 100644 --- a/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx +++ b/src/BRepOffsetAPI/BRepOffsetAPI_DraftAngle.cxx @@ -960,7 +960,7 @@ void BRepOffsetAPI_DraftAngle::CorrectVertexTol() anExp.Init(myShape, TopAbs_EDGE); for(; anExp.More(); anExp.Next()) { - const TopoDS_Shape& anE = anExp.Current(); + const TopoDS_Edge& anE = TopoDS::Edge(anExp.Current()); //Skip old (not modified) edges if(anInitEdges.Contains(anE)) continue; @@ -971,7 +971,7 @@ void BRepOffsetAPI_DraftAngle::CorrectVertexTol() // aNewEdges.Add(anE); // - Standard_Real anETol = BRep_Tool::Tolerance(TopoDS::Edge(anE)); + Standard_Real anETol = BRep_Tool::Tolerance(anE); TopoDS_Iterator anIter(anE); for(; anIter.More(); anIter.Next()) { @@ -997,6 +997,18 @@ void BRepOffsetAPI_DraftAngle::CorrectVertexTol() } else { + gp_Pnt aVPnt = BRep_Tool::Pnt(aVtx); + Standard_Real f, l; + TopLoc_Location anL; + const Handle(Geom_Curve)& aECrv = BRep_Tool::Curve(TopoDS::Edge(anE), anL, f, l); + Standard_Real aVPar = BRep_Tool::Parameter(aVtx, anE); + gp_Pnt aCP = aECrv->Value(aVPar); + if (!anL.IsIdentity()) + { + aCP.Transform(anL.Transformation()); + } + Standard_Real aD = aVPnt.Distance(aCP); + aBB.UpdateVertex(aVtx, aD); aBB.UpdateVertex(aVtx, anETol + Epsilon(anETol)); } } diff --git a/src/BRepTest/BRepTest_BasicCommands.cxx b/src/BRepTest/BRepTest_BasicCommands.cxx index 3e104a3333..f07940b722 100644 --- a/src/BRepTest/BRepTest_BasicCommands.cxx +++ b/src/BRepTest/BRepTest_BasicCommands.cxx @@ -110,6 +110,30 @@ static Standard_Integer addpcurve(Draw_Interpretor& , Standard_Integer n, const return 0; } +//======================================================================= +// setpcurve +//======================================================================= + +static Standard_Integer setpcurve(Draw_Interpretor&, Standard_Integer n, const char** a) +{ + if (n < 4) return 1; + TopoDS_Shape E = DBRep::Get(a[1]); + if (E.IsNull()) return 1; + Handle(Geom2d_Curve) PC = DrawTrSurf::GetCurve2d(a[2]); + TopoDS_Shape F = DBRep::Get(a[3]); + Standard_Real tol = 1.e-4; + if (n > 4) { + tol = Draw::Atof(a[4]); + } + //BRep_Builder BB; + //BB.UpdateEdge(TopoDS::Edge(E), PC, TopoDS::Face(F), tol); + Standard_Real tolreached; + Handle(Geom2d_Curve) ProjC; + BRepLib::SetPCurve(TopoDS::Edge(E), PC, TopoDS::Face(F), tol, + tolreached, ProjC); + DBRep::Set(a[1], E); + return 0; +} //======================================================================= // transform @@ -1402,6 +1426,10 @@ void BRepTest::BasicCommands(Draw_Interpretor& theCommands) "addpcurve edge 2dcurve face [tol (default 1.e-7)]", __FILE__, addpcurve,g); + theCommands.Add("setpcurve", + "addpcurve edge 2dcurve face [tol (default 1.e-4)]", + __FILE__, + setpcurve, g); theCommands.Add("reset", "reset name1 name2 ..., remove location", diff --git a/src/ProjLib/ProjLib_ProjectedCurve.cxx b/src/ProjLib/ProjLib_ProjectedCurve.cxx index 2d5b2a869c..c5135f1c31 100644 --- a/src/ProjLib/ProjLib_ProjectedCurve.cxx +++ b/src/ProjLib/ProjLib_ProjectedCurve.cxx @@ -237,7 +237,7 @@ static void ExtendC2d (Handle(Geom2d_BSplineCurve)& aRes, } gp_Lin2d BoundLin(thePole, theBoundDir); //one of the bounds of rectangle Standard_Real ParOnLin = 0.; - if (theBoundDir.IsParallel(aDBnd, 100.*Precision::Angular())) + if (theBoundDir.IsParallel(aDBnd, Precision::PConfusion())) { ParOnLin = ElCLib::Parameter(aLin, thePole); } diff --git a/tests/bugs/modalg_2/bug22770_13 b/tests/bugs/modalg_2/bug22770_13 index 92e6237160..fbe4ce43e4 100755 --- a/tests/bugs/modalg_2/bug22770_13 +++ b/tests/bugs/modalg_2/bug22770_13 @@ -32,7 +32,7 @@ checkprops result -s 1.8847e+07 checkshape result checknbshapes result -vertex 964 -edge 1222 -wire 273 -face 259 -shell 18 -solid 0 -compsolid 0 -compound 1 -shape 2737 -checkmaxtol result -ref 0.046734236640099257 +checkmaxtol result -ref 0.0451323239933289 checknbshapes result -shell 18 checkfreebounds result 926 checkview -display result -3d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_2/bug22770_15 b/tests/bugs/modalg_2/bug22770_15 index 22c4fb2242..47dab4893b 100755 --- a/tests/bugs/modalg_2/bug22770_15 +++ b/tests/bugs/modalg_2/bug22770_15 @@ -32,7 +32,7 @@ checkprops result -s 1.8847e+07 checkshape result checknbshapes result -vertex 964 -edge 1222 -wire 273 -face 259 -shell 18 -solid 0 -compsolid 0 -compound 1 -shape 2737 -checkmaxtol result -ref 0.046734236640099257 +checkmaxtol result -ref 0.0451323239933289 checknbshapes result -shell 18 checkfreebounds result 926 checkview -display result -3d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_2/bug22804 b/tests/bugs/modalg_2/bug22804 index 8b794093dc..f04776407b 100755 --- a/tests/bugs/modalg_2/bug22804 +++ b/tests/bugs/modalg_2/bug22804 @@ -28,7 +28,7 @@ if { ${minTolerance} > ${VertexTolerance} } { checkreal "Min tolerance" ${minTolerance} ${oTolerance} 0 0.001 -checkmaxtol result -ref 2352.4465999220711 +checkmaxtol result -ref 291.20622363265852 checknbshapes result -shell 1 checkfreebounds result 5 diff --git a/tests/bugs/modalg_4/bug714 b/tests/bugs/modalg_4/bug714 index 3c3d2265e3..23c27621ea 100755 --- a/tests/bugs/modalg_4/bug714 +++ b/tests/bugs/modalg_4/bug714 @@ -29,7 +29,7 @@ if { $ve1 != $ve2 || $ed1 != $ed2 || $we1 != $we2} { puts "OK OCC714: SEWING operation was made PROPERLY" } -checkmaxtol result -ref 0.25619311354638169 +checkmaxtol result -ref 0.17654971008905099 checknbshapes result -shell 1 checkfreebounds result 0 diff --git a/tests/bugs/modalg_5/bug25175 b/tests/bugs/modalg_5/bug25175 index 0912b2591e..ee7c73ee82 100644 --- a/tests/bugs/modalg_5/bug25175 +++ b/tests/bugs/modalg_5/bug25175 @@ -12,7 +12,7 @@ igesread [locate_data_file bug25175_3.igs] a * sewing result 0.1 a -checkmaxtol result -ref 0.40493352048584974 +checkmaxtol result -ref 0.21794517334615857 checknbshapes result -shell 1 checkfreebounds result 0 diff --git a/tests/bugs/modalg_6/bug27651 b/tests/bugs/modalg_6/bug27651 new file mode 100644 index 0000000000..64f47f30da --- /dev/null +++ b/tests/bugs/modalg_6/bug27651 @@ -0,0 +1,32 @@ +puts "========" +puts "0027651: Modeling Algorithms - Add projection support in sewing pcurves handling" +puts "========" +puts "" + + +restore [locate_data_file bug27531.brep] aS +sewing result 0.2 aS + +# check result shape for validity. +checkshape result + +# Check distances +set MAX_DIST 3.0 +explode result E +explode result F + +set log [xdistef result_3 result_1] +regexp {Max Distance = +([-0-9.+eE]+); Parameter} ${log} full aDist +if { $aDist > $MAX_DIST} { + puts "Error: First pcurve is too far from 3d curve" +} else { + puts "OK: First pcurve is OK." +} + +set log [xdistef result_3 result_2] +regexp {Max Distance = +([-0-9.+eE]+); Parameter} ${log} full aDist +if { $aDist > $MAX_DIST} { + puts "Error: Second pcurve is too far from 3d curve" +} else { + puts "OK: Second pcurve is OK." +} diff --git a/tests/bugs/xde/bug547_2 b/tests/bugs/xde/bug547_2 index 59d1d4fd3c..7e9311dd7a 100755 --- a/tests/bugs/xde/bug547_2 +++ b/tests/bugs/xde/bug547_2 @@ -29,7 +29,7 @@ if { ${face2} > ${face1} || ${edge2} > ${edge1} || ${vert2} > ${vert1} } { puts "Tolerance valed. Function FixShape works CORRECTLY" } -checkmaxtol result -ref 1.59071e+000 +checkmaxtol result -ref 0.17775413987830679 checknbshapes result -shell 1 checkfreebounds result 227 diff --git a/tests/lowalgos/intss/bug26684_1 b/tests/lowalgos/intss/bug26684_1 index 3479f5ff90..7c3e6c3a44 100644 --- a/tests/lowalgos/intss/bug26684_1 +++ b/tests/lowalgos/intss/bug26684_1 @@ -20,7 +20,7 @@ fit set bop_info [bopcurves f1 f2] regexp {Tolerance Reached=([-0-9.+eE]+)} $bop_info full Tolerance -checkreal "Reached tolerance" ${Tolerance} 5.8654166482879483e-009 1.e-7 0 +checkreal "Reached tolerance" ${Tolerance} 5.8654392197230118e-09 1.e-7 0 # 2 case set bop_info_2d [bopcurves f1 f2 -2d] diff --git a/tests/lowalgos/intss/bug27263 b/tests/lowalgos/intss/bug27263 index 9471b1eb4d..e117068d54 100644 --- a/tests/lowalgos/intss/bug27263 +++ b/tests/lowalgos/intss/bug27263 @@ -30,6 +30,6 @@ if {${NbCurv} != ${GoodNbCurv}} { } checklength c_1 -l 2.9620641619623407 -checklength c_2 -l 3.1050603628884668 +checklength c_2 -l 3.105060362884668 checkview -screenshot -2d -path ${imagedir}/${test_image}.png \ No newline at end of file diff --git a/tests/sewing/tol_100/D3 b/tests/sewing/tol_100/D3 index aee1cbeca6..1837b3275d 100644 --- a/tests/sewing/tol_100/D3 +++ b/tests/sewing/tol_100/D3 @@ -1,4 +1,4 @@ -puts "TODO OCC23674 ALL: Error : Number of faults is" +##puts "TODO OCC23674 ALL: Error : Number of faults is" restore [locate_data_file CFI_pro15441.rle] a diff --git a/tests/sewing/tol_100/I5 b/tests/sewing/tol_100/I5 index 0268d88562..8f5045077f 100755 --- a/tests/sewing/tol_100/I5 +++ b/tests/sewing/tol_100/I5 @@ -4,7 +4,7 @@ restore [locate_data_file CIN901_intcqhmi.rle] a sewing result $tol a -checkmaxtol result -ref 1.91680e+001 +checkmaxtol result -ref 26.246606802805864 checknbshapes result -shell 1 -checkfreebounds result 3 +checkfreebounds result 0 checkfaults result a 6 diff --git a/tests/sewing/tol_100/J1 b/tests/sewing/tol_100/J1 index aa7901677a..89e2b67701 100644 --- a/tests/sewing/tol_100/J1 +++ b/tests/sewing/tol_100/J1 @@ -4,7 +4,7 @@ restore [locate_data_file CIN902_intcqhmn.rle] a sewing result $tol a -checkmaxtol result -ref 31.117378506550729 +checkmaxtol result -ref 33.208410811730566 checknbshapes result -shell 1 checkfreebounds result 47 checkfaults result a 7 diff --git a/tests/sewing/tol_100/J2 b/tests/sewing/tol_100/J2 index b6d95b07f1..fc862d800c 100644 --- a/tests/sewing/tol_100/J2 +++ b/tests/sewing/tol_100/J2 @@ -4,7 +4,7 @@ restore [locate_data_file CIN902_intcqhmo.rle] a sewing result $tol a -checkmaxtol result -ref 31.117378506550729 +checkmaxtol result -ref 33.208410811730566 checknbshapes result -shell 1 checkfreebounds result 47 checkfaults result a 7 -- 2.39.5