diff --git a/src/BRepTools/BRepTools_WireExplorer.cxx b/src/BRepTools/BRepTools_WireExplorer.cxx index 4a086589fe..1fe412abee 100644 --- a/src/BRepTools/BRepTools_WireExplorer.cxx +++ b/src/BRepTools/BRepTools_WireExplorer.cxx @@ -16,6 +16,7 @@ #include +#include #include #include #include @@ -101,14 +102,50 @@ void BRepTools_WireExplorer::Init(const TopoDS_Wire& W) //purpose : //======================================================================= void BRepTools_WireExplorer::Init(const TopoDS_Wire& W, - const TopoDS_Face& F) + const TopoDS_Face& F) { myEdge = TopoDS_Edge(); myVertex = TopoDS_Vertex(); myMap.Clear(); myDoubles.Clear(); - if( W.IsNull() ) + if (W.IsNull()) + return; + + Standard_Real UMin(0.0), UMax(0.0), VMin(0.0), VMax(0.0); + if (!F.IsNull()) + { + // For the faces based on Cone, BSpline and Bezier compute the + // UV bounds to precise the UV tolerance values + const GeomAbs_SurfaceType aSurfType = BRepAdaptor_Surface(F, Standard_False).GetType(); + if (aSurfType == GeomAbs_Cone || + aSurfType == GeomAbs_BSplineSurface || + aSurfType == GeomAbs_BezierSurface) + { + BRepTools::UVBounds(F, UMin, UMax, VMin, VMax); + } + } + + Init(W, F, UMin, UMax, VMin, VMax); +} + +//======================================================================= +//function : Init +//purpose : +//======================================================================= +void BRepTools_WireExplorer::Init(const TopoDS_Wire& W, + const TopoDS_Face& F, + const Standard_Real UMin, + const Standard_Real UMax, + const Standard_Real VMin, + const Standard_Real VMax) +{ + myEdge = TopoDS_Edge(); + myVertex = TopoDS_Vertex(); + myMap.Clear(); + myDoubles.Clear(); + + if (W.IsNull()) return; myFace = F; @@ -116,142 +153,147 @@ void BRepTools_WireExplorer::Init(const TopoDS_Wire& W, myReverse = Standard_False; if (!myFace.IsNull()) + { + BRepTools::Update(myFace); + TopLoc_Location aL; + const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(myFace, aL); + GeomAdaptor_Surface aGAS(aSurf); + TopExp_Explorer anExp(W, TopAbs_VERTEX); + for (; anExp.More(); anExp.Next()) { - BRepTools::Update(myFace); - TopLoc_Location aL; - const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(myFace, aL); - GeomAdaptor_Surface aGAS(aSurf); - TopExp_Explorer anExp(W, TopAbs_VERTEX); - for(; anExp.More(); anExp.Next()) - { - const TopoDS_Vertex& aV = TopoDS::Vertex(anExp.Current()); - dfVertToler = Max(BRep_Tool::Tolerance(aV), dfVertToler); - } - myTolU = 2. * aGAS.UResolution(dfVertToler); - myTolV = 2. * aGAS.VResolution(dfVertToler); - - // uresolution for cone with infinite vmin vmax is too small. - if(aGAS.GetType() == GeomAbs_Cone) - { - Standard_Real u1, u2, v1, v2; - BRepTools::UVBounds(myFace, u1, u2, v1, v2); - gp_Pnt aP; - gp_Vec aD1U, aD1V; - aGAS.D1(u1, v1, aP, aD1U, aD1V); - Standard_Real tol1, tol2, maxtol = .0005*(u2-u1); - Standard_Real a = aD1U.Magnitude(); - - if(a <= Precision::Confusion()) - tol1 = maxtol; - else - tol1 = Min(maxtol, dfVertToler/a); - - aGAS.D1(u1, v2, aP, aD1U, aD1V); - a = aD1U.Magnitude(); - if(a <= Precision::Confusion()) - tol2 = maxtol; - else - tol2 = Min(maxtol, dfVertToler/a); - - myTolU = 2. * Max(tol1, tol2); - } - - if( aGAS.GetType() == GeomAbs_BSplineSurface || - aGAS.GetType() == GeomAbs_BezierSurface ) - { - Standard_Real maxTol = Max(myTolU, myTolV); - gp_Pnt aP; - gp_Vec aDU, aDV; - Standard_Real u1, u2, v1, v2; - BRepTools::UVBounds(myFace, u1, u2, v1, v2); - aGAS.D1((u2 - u1) / 2., (v2 - v1) / 2., aP, aDU, aDV); - Standard_Real mod = Sqrt(aDU*aDU + aDV*aDV); - if (mod * maxTol / dfVertToler < 1.5) - { - maxTol = 1.5 * dfVertToler / mod; - } - myTolU = maxTol; - myTolV = maxTol; - } - - myReverse = (myFace.Orientation() == TopAbs_REVERSED); + const TopoDS_Vertex& aV = TopoDS::Vertex(anExp.Current()); + dfVertToler = Max(BRep_Tool::Tolerance(aV), dfVertToler); } - + if (dfVertToler < Precision::Confusion()) + { + // Use tolerance of edges + for (TopoDS_Iterator it(W); it.More(); it.Next()) + dfVertToler = Max(BRep_Tool::Tolerance(TopoDS::Edge(it.Value())), dfVertToler); + + if (dfVertToler < Precision::Confusion()) + // empty wire + return; + } + myTolU = 2. * aGAS.UResolution(dfVertToler); + myTolV = 2. * aGAS.VResolution(dfVertToler); + + // uresolution for cone with infinite vmin vmax is too small. + if (aGAS.GetType() == GeomAbs_Cone) + { + gp_Pnt aP; + gp_Vec aD1U, aD1V; + aGAS.D1(UMin, VMin, aP, aD1U, aD1V); + Standard_Real tol1, tol2, maxtol = .0005*(UMax - UMin); + Standard_Real a = aD1U.Magnitude(); + + if (a <= Precision::Confusion()) + tol1 = maxtol; + else + tol1 = Min(maxtol, dfVertToler / a); + + aGAS.D1(UMin, VMax, aP, aD1U, aD1V); + a = aD1U.Magnitude(); + if (a <= Precision::Confusion()) + tol2 = maxtol; + else + tol2 = Min(maxtol, dfVertToler / a); + + myTolU = 2. * Max(tol1, tol2); + } + + if (aGAS.GetType() == GeomAbs_BSplineSurface || + aGAS.GetType() == GeomAbs_BezierSurface) + { + Standard_Real maxTol = Max(myTolU, myTolV); + gp_Pnt aP; + gp_Vec aDU, aDV; + aGAS.D1((UMax - UMin) / 2., (VMax - VMin) / 2., aP, aDU, aDV); + Standard_Real mod = Sqrt(aDU*aDU + aDV*aDV); + if (mod > gp::Resolution()) + { + if (mod * maxTol / dfVertToler < 1.5) + { + maxTol = 1.5 * dfVertToler / mod; + } + myTolU = maxTol; + myTolV = maxTol; + } + } + + myReverse = (myFace.Orientation() == TopAbs_REVERSED); + } + // map of vertices to know if the wire is open TopTools_MapOfShape vmap; - // Modified by Sergey KHROMOV - Mon May 13 11:50:48 2002 Begin // map of infinite edges TopTools_MapOfShape anInfEmap; - // Modified by Sergey KHROMOV - Mon May 13 11:50:49 2002 End // list the vertices - TopoDS_Vertex V1,V2; + TopoDS_Vertex V1, V2; TopTools_ListOfShape empty; TopoDS_Iterator it(W); while (it.More()) + { + const TopoDS_Edge& E = TopoDS::Edge(it.Value()); + TopAbs_Orientation Eori = E.Orientation(); + if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL) { - const TopoDS_Edge& E = TopoDS::Edge(it.Value()); - TopAbs_Orientation Eori = E.Orientation(); - if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL) - { - it.Next(); - continue; - } - TopExp::Vertices(E,V1,V2,Standard_True); - - if( !V1.IsNull() ) - { - if( !myMap.IsBound(V1) ) - myMap.Bind(V1,empty); - myMap(V1).Append(E); - - // add or remove in the vertex map - V1.Orientation(TopAbs_FORWARD); - if( !vmap.Add(V1) ) - vmap.Remove(V1); - } - - if( !V2.IsNull() ) - { - V2.Orientation(TopAbs_REVERSED); - if(!vmap.Add(V2)) - vmap.Remove(V2); - } - - // Modified by Sergey KHROMOV - Mon May 13 11:52:20 2002 Begin - if (V1.IsNull() || V2.IsNull()) - { - Standard_Real aF = 0., aL = 0.; - BRep_Tool::Range(E, aF, aL); - - if(Eori == TopAbs_FORWARD) - { - if (aF == -Precision::Infinite()) - anInfEmap.Add(E); - } - else - { // Eori == TopAbs_REVERSED - if (aL == Precision::Infinite()) - anInfEmap.Add(E); - } - } - // Modified by Sergey KHROMOV - Mon May 13 11:52:20 2002 End it.Next(); + continue; + } + TopExp::Vertices(E, V1, V2, Standard_True); + + if (!V1.IsNull()) + { + if (!myMap.IsBound(V1)) + myMap.Bind(V1, empty); + myMap(V1).Append(E); + + // add or remove in the vertex map + V1.Orientation(TopAbs_FORWARD); + if (!vmap.Add(V1)) + vmap.Remove(V1); } + if (!V2.IsNull()) + { + V2.Orientation(TopAbs_REVERSED); + if (!vmap.Add(V2)) + vmap.Remove(V2); + } + + if (V1.IsNull() || V2.IsNull()) + { + Standard_Real aF = 0., aL = 0.; + BRep_Tool::Range(E, aF, aL); + + if (Eori == TopAbs_FORWARD) + { + if (aF == -Precision::Infinite()) + anInfEmap.Add(E); + } + else + { // Eori == TopAbs_REVERSED + if (aL == Precision::Infinite()) + anInfEmap.Add(E); + } + } + it.Next(); + } + //Construction of the set of double edges. - TopoDS_Iterator it2(W); + TopoDS_Iterator it2(W); TopTools_MapOfShape emap; while (it2.More()) { - if (!emap.Add(it2.Value())) + if (!emap.Add(it2.Value())) myDoubles.Add(it2.Value()); it2.Next(); } // if vmap is not empty the wire is open, let us find the first vertex if (!vmap.IsEmpty()) { - TopTools_MapIteratorOfMapOfShape itt(vmap); // skl : I change "it" to "itt" + TopTools_MapIteratorOfMapOfShape itt(vmap); while (itt.Key().Orientation() != TopAbs_FORWARD) { itt.Next(); if (!itt.More()) break; @@ -259,29 +301,26 @@ void BRepTools_WireExplorer::Init(const TopoDS_Wire& W, if (itt.More()) V1 = TopoDS::Vertex(itt.Key()); } else { -// Modified by Sergey KHROMOV - Mon May 13 12:05:30 2002 Begin -// The wire is infinite Try to find the first vertex. It may be NULL. + // The wire is infinite Try to find the first vertex. It may be NULL. if (!anInfEmap.IsEmpty()) { TopTools_MapIteratorOfMapOfShape itt(anInfEmap); for (; itt.More(); itt.Next()) { - TopoDS_Edge anEdge = TopoDS::Edge(itt.Key()); - TopAbs_Orientation anOri = anEdge.Orientation(); - Standard_Real aF; - Standard_Real aL; + TopoDS_Edge anEdge = TopoDS::Edge(itt.Key()); + TopAbs_Orientation anOri = anEdge.Orientation(); + Standard_Real aF; + Standard_Real aL; - BRep_Tool::Range(anEdge, aF, aL); - if ((anOri == TopAbs_FORWARD && aF == -Precision::Infinite()) || - (anOri == TopAbs_REVERSED && aL == Precision::Infinite())) { - myEdge = anEdge; - myVertex = TopoDS_Vertex(); + BRep_Tool::Range(anEdge, aF, aL); + if ((anOri == TopAbs_FORWARD && aF == -Precision::Infinite()) || + (anOri == TopAbs_REVERSED && aL == Precision::Infinite())) { + myEdge = anEdge; + myVertex = TopoDS_Vertex(); - return; - } + return; + } } } -// Modified by Sergey KHROMOV - Mon May 13 12:05:31 2002 End - // use the first vertex in iterator it.Initialize(W); @@ -289,23 +328,23 @@ void BRepTools_WireExplorer::Init(const TopoDS_Wire& W, const TopoDS_Edge& E = TopoDS::Edge(it.Value()); TopAbs_Orientation Eori = E.Orientation(); if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL) { - // JYL 10-03-97 : waiting for correct processing - // of INTERNAL/EXTERNAL edges - it.Next(); - continue; + // JYL 10-03-97 : waiting for correct processing + // of INTERNAL/EXTERNAL edges + it.Next(); + continue; } - TopExp::Vertices(E,V1,V2,Standard_True); + TopExp::Vertices(E, V1, V2, Standard_True); break; } } - if (V1.IsNull() ) return; + if (V1.IsNull()) return; if (!myMap.IsBound(V1)) return; - + TopTools_ListOfShape& l = myMap(V1); myEdge = TopoDS::Edge(l.First()); l.RemoveFirst(); - myVertex = TopExp::FirstVertex (myEdge, Standard_True); + myVertex = TopExp::FirstVertex(myEdge, Standard_True); } @@ -462,6 +501,12 @@ void BRepTools_WireExplorer::Next() aPCurve->D0(dfMPar, PRefm); // Get vector from PRef to PRefm gp_Vec2d anERefDir(PRef,PRefm); + if (anERefDir.SquareMagnitude() < gp::Resolution()) + { + myEdge = TopoDS_Edge(); + return; + } + // Search the list of edges looking for the edge having hearest // 2D point of connected vertex to current one and smallest angle. // First process all degenerated edges, then - all others. diff --git a/src/BRepTools/BRepTools_WireExplorer.hxx b/src/BRepTools/BRepTools_WireExplorer.hxx index 00b3eef112..f04ff22d5a 100644 --- a/src/BRepTools/BRepTools_WireExplorer.hxx +++ b/src/BRepTools/BRepTools_WireExplorer.hxx @@ -77,6 +77,17 @@ public: //! previous in the parametric representation of . Standard_EXPORT void Init (const TopoDS_Wire& W, const TopoDS_Face& F); + //! Initializes an exploration of the wire . + //! F is used to select the edge connected to the + //! previous in the parametric representation of . + //! , , , - the UV bounds of the face . + Standard_EXPORT void Init(const TopoDS_Wire& W, + const TopoDS_Face& F, + const Standard_Real UMin, + const Standard_Real UMax, + const Standard_Real VMin, + const Standard_Real VMax); + //! Returns True if there is a current edge. Standard_EXPORT Standard_Boolean More() const; diff --git a/src/DBRep/DBRep_IsoBuilder.cxx b/src/DBRep/DBRep_IsoBuilder.cxx index e8f46110c8..3db716aba0 100644 --- a/src/DBRep/DBRep_IsoBuilder.cxx +++ b/src/DBRep/DBRep_IsoBuilder.cxx @@ -16,7 +16,9 @@ #include +#include #include +#include #include #include #include @@ -29,15 +31,19 @@ #include #include #include +#include #include #include #include #include +#include -// Modified by Sergey KHROMOV - Thu Nov 9 12:08:37 2000 -static Standard_Real IntersectorConfusion = 1.e-10 ; // -8 ; -static Standard_Real IntersectorTangency = 1.e-10 ; // -8 ; -// Modified by Sergey KHROMOV - Thu Nov 9 12:08:38 2000 +#include +#include + +// Providing consistency with intersection tolerance for the linear curves +static Standard_Real IntersectorConfusion = Precision::PConfusion(); +static Standard_Real IntersectorTangency = Precision::PConfusion(); static Standard_Real HatcherConfusion2d = 1.e-8 ; static Standard_Real HatcherConfusion3d = 1.e-8 ; @@ -97,8 +103,10 @@ Geom2dHatch_Hatcher (Geom2dHatch_Intersector (IntersectorConfusion, } //----------------------------------------------------------------------- - // Retreiving the edges and loading them into the hatcher. + // Retrieving the edges and its p-curves for further trimming + // and loading them into the hatcher //----------------------------------------------------------------------- + DataMapOfEdgePCurve anEdgePCurveMap; TopExp_Explorer ExpEdges; for (ExpEdges.Init (TopologicalFace, TopAbs_EDGE); ExpEdges.More(); ExpEdges.Next()) @@ -126,7 +134,7 @@ Geom2dHatch_Hatcher (Geom2dHatch_Intersector (IntersectorConfusion, if (Abs(PCurve->FirstParameter()-U1)<= Precision::PConfusion() && Abs(PCurve->LastParameter()-U2)<= Precision::PConfusion()) { - AddElement (PCurve, TopologicalEdge.Orientation()); + anEdgePCurveMap.Add(TopologicalEdge, PCurve); } else { @@ -140,7 +148,6 @@ Geom2dHatch_Hatcher (Geom2dHatch_Intersector (IntersectorConfusion, U1 - TrimPCurve->BasisCurve()->LastParameter() > Precision::PConfusion() || U2 - TrimPCurve->BasisCurve()->LastParameter() > Precision::PConfusion()) { - AddElement (PCurve, TopologicalEdge.Orientation()); #ifdef OCCT_DEBUG cout << "DBRep_IsoBuilder TrimPCurve : parameters out of range\n"; cout << " U1(" << U1 << "), Umin(" << PCurve->FirstParameter() @@ -189,11 +196,20 @@ Geom2dHatch_Hatcher (Geom2dHatch_Intersector (IntersectorConfusion, // if U1 and U2 coincide-->do nothing if (Abs (U1 - U2) <= Precision::PConfusion()) continue; Handle (Geom2d_TrimmedCurve) TrimPCurve = new Geom2d_TrimmedCurve (PCurve, U1, U2); - Geom2dAdaptor_Curve aGAC (TrimPCurve); - AddElement (aGAC, TopologicalEdge.Orientation()); + anEdgePCurveMap.Add(TopologicalEdge, TrimPCurve); } } + // Fill the gaps between 2D curves, and trim the intersecting ones. + FillGaps(TopologicalFace, anEdgePCurveMap); + + // Load trimmed curves to the hatcher + Standard_Integer aNbE = anEdgePCurveMap.Extent(); + for (Standard_Integer iE = 1; iE <= aNbE; ++iE) + { + AddElement(Geom2dAdaptor_Curve(anEdgePCurveMap(iE)), + anEdgePCurveMap.FindKey(iE).Orientation()); + } //----------------------------------------------------------------------- // Loading and trimming the hatchings. //----------------------------------------------------------------------- @@ -327,3 +343,299 @@ void DBRep_IsoBuilder::LoadIsos (const Handle(DBRep_Face)& Face) const } } } + +//======================================================================= +// Function : FillGaps +// Purpose : +//======================================================================= +void DBRep_IsoBuilder::FillGaps(const TopoDS_Face& theFace, + DataMapOfEdgePCurve& theEdgePCurveMap) +{ + + // Get surface of the face for getting the 3D points from 2D coordinates + // of the p-curves bounds + BRepAdaptor_Surface aBASurf(theFace, Standard_False); + + // Analyze each wire of the face separately + TopoDS_Iterator aItW(theFace); + for (; aItW.More(); aItW.Next()) + { + const TopoDS_Shape& aW = aItW.Value(); + if (aW.ShapeType() != TopAbs_WIRE) + continue; + + // Use WireExplorer to iterate on edges of the wire + // to get the pairs of connected edges. + // Using WireExplorer will also allow avoiding treatment + // of the internal wires. + BRepTools_WireExplorer aWExp; + aWExp.Init(TopoDS::Wire(aW), theFace, myUMin, myUMax, myVMin, myVMax); + if (!aWExp.More()) + continue; + + // Check the number of edges in the wire, not to + // miss the wires containing one edge only + Standard_Boolean SingleEdge = Standard_True; + { + TopoDS_Iterator itE(aW); + if (!itE.More()) + continue; + itE.Next(); + SingleEdge = !itE.More(); + } + + TopoDS_Edge aPrevEdge, aCurrEdge; + + // Get first edge and its p-curve + aCurrEdge = aWExp.Current(); + + // Ensure analysis of the pair of first and last edges + TopoDS_Edge aFirstEdge = aCurrEdge; + Standard_Real bStop = Standard_False; + + // Iterate on all other edges + while (!bStop) + { + // Iteration to the next edge + aPrevEdge = aCurrEdge; + aWExp.Next(); + // Get the current edge for analysis + if (aWExp.More()) + { + aCurrEdge = aWExp.Current(); + } + else + { + aCurrEdge = aFirstEdge; + bStop = Standard_True; + } + + if (aPrevEdge.IsEqual(aCurrEdge) && !SingleEdge) + continue; + + // Get p-curves + Handle(Geom2d_Curve)* pPC1 = theEdgePCurveMap.ChangeSeek(aPrevEdge); + Handle(Geom2d_Curve)* pPC2 = theEdgePCurveMap.ChangeSeek(aCurrEdge); + if (!pPC1 || !pPC2) + continue; + + Handle(Geom2d_Curve)& aPrevC2d = *pPC1; + Handle(Geom2d_Curve)& aCurrC2d = *pPC2; + + // Get p-curves parameters + Standard_Real fp, lp, fc, lc; + fp = aPrevC2d->FirstParameter(); + lp = aPrevC2d->LastParameter(); + fc = aCurrC2d->FirstParameter(); + lc = aCurrC2d->LastParameter(); + + // Get common vertex to check if the gap between two edges is closed + // by the tolerance value of this vertex. + // Take into account the orientation of the edges to obtain the correct + // parameter of the vertex on edges. + + // Get vertex on the previous edge + TopoDS_Vertex aCVOnPrev = TopExp::LastVertex(aPrevEdge, Standard_True); + if (aCVOnPrev.IsNull()) + continue; + + // Get parameter of the vertex on the previous edge + Standard_Real aTPrev = BRep_Tool::Parameter(aCVOnPrev, aPrevEdge); + if (aTPrev < fp) + aTPrev = fp; + else if (aTPrev > lp) + aTPrev = lp; + + // Get vertex on the current edge + TopoDS_Vertex aCVOnCurr = TopExp::FirstVertex(aCurrEdge, Standard_True); + if (aCVOnCurr.IsNull() || !aCVOnPrev.IsSame(aCVOnCurr)) + continue; + + // Get parameter of the vertex on the current edge + Standard_Real aTCurr = BRep_Tool::Parameter(aCVOnCurr, aCurrEdge); + if (aTCurr < fc) + aTCurr = fc; + else if (aTCurr > lc) + aTCurr = lc; + + // Get bounding points on the edges corresponding to the current vertex + gp_Pnt2d aPrevP2d = aPrevC2d->Value(aTPrev), + aCurrP2d = aCurrC2d->Value(aTCurr); + + // Check if the vertex covers these bounding points by its tolerance + Standard_Real aTolV2 = BRep_Tool::Tolerance(aCVOnPrev); + gp_Pnt aPV = BRep_Tool::Pnt(aCVOnPrev); + // There is no need to check the distance if the tolerance + // of vertex is infinite (like in the test case sewing/tol_1/R2) + if (aTolV2 < Precision::Infinite()) + { + aTolV2 *= aTolV2; + + // Convert bounding point on previous edge into 3D + gp_Pnt aPrevPS = aBASurf.Value(aPrevP2d.X(), aPrevP2d.Y()); + + // Check if the vertex closes the gap + if (aPV.SquareDistance(aPrevPS) > aTolV2) + continue; + + // Convert bounding point on current edge into 3D + gp_Pnt aCurrPS = aBASurf.Value(aCurrP2d.X(), aCurrP2d.Y()); + + // Check if the vertex closes the gap + if (aPV.SquareDistance(aCurrPS) > aTolV2) + continue; + } + + // Create the segment + gp_Vec2d aV2d(aPrevP2d, aCurrP2d); + Standard_Real aSegmLen = aV2d.Magnitude(); + // Do not add too small segments + Standard_Boolean bAddSegment = (aSegmLen > Precision::PConfusion()); + // Check for periodic surfaces + if (bAddSegment) + { + if (aBASurf.IsUPeriodic()) + bAddSegment = aSegmLen < aBASurf.UPeriod() / 4.; + + if (bAddSegment && aBASurf.IsVPeriodic()) + bAddSegment = aSegmLen < aBASurf.VPeriod() / 4.; + } + + // Check that p-curves do not interfere near the vertex. + // And, if they do interfere, avoid creation of the segment. + if (bAddSegment && !aPrevEdge.IsEqual(aCurrEdge)) + { + Geom2dAdaptor_Curve aPrevGC(aPrevC2d, fp, lp), aCurrGC(aCurrC2d, fc, lc); + Geom2dInt_GInter anInter(aPrevGC, aCurrGC, Precision::PConfusion(), Precision::PConfusion()); + if (anInter.IsDone() && !anInter.IsEmpty()) + { + // Collect intersection points + NCollection_List aLPInt; + // Get bounding points from segments + Standard_Integer iP, aNbInt = anInter.NbSegments(); + for (iP = 1; iP <= aNbInt; ++iP) + { + aLPInt.Append(anInter.Segment(iP).FirstPoint()); + aLPInt.Append(anInter.Segment(iP).LastPoint()); + } + // Get intersection points + aNbInt = anInter.NbPoints(); + for (iP = 1; iP <= aNbInt; ++iP) + aLPInt.Append(anInter.Point(iP)); + + // Analyze the points and find the one closest to the current vertex + Standard_Boolean bPointFound = Standard_False; + Standard_Real aTPrevClosest = 0., aTCurrClosest = 0.; + Standard_Real aDeltaPrev = ::RealLast(), aDeltaCurr = ::RealLast(); + + NCollection_List::Iterator aItLPInt(aLPInt); + for (; aItLPInt.More(); aItLPInt.Next()) + { + const IntRes2d_IntersectionPoint& aPnt = aItLPInt.Value(); + const Standard_Real aTIntPrev = aPnt.ParamOnFirst(); + const Standard_Real aTIntCurr = aPnt.ParamOnSecond(); + // Check if the intersection point is in range + if (aTIntPrev < fp || aTIntPrev > lp || + aTIntCurr < fc || aTIntCurr > lc) + { + continue; + } + + Standard_Real aDelta1 = Abs(aTIntPrev - aTPrev); + Standard_Real aDelta2 = Abs(aTIntCurr - aTCurr); + if (aDelta1 < aDeltaPrev || aDelta2 < aDeltaCurr) + { + aTPrevClosest = aTIntPrev; + aTCurrClosest = aTIntCurr; + aDeltaPrev = aDelta1; + aDeltaCurr = aDelta2; + bPointFound = Standard_True; + } + } + + if (bPointFound) + { + // Check the number of common vertices between edges. + // If on the other end, there is also a common vertex, + // check where the intersection point is located. It might + // be closer to the other vertex than to the current one. + // And here we just need to close the gap, avoiding the trimming. + // If the common vertex is only one, do not create the segment, + // as we have the intersection of the edges and trimmed the 2d curves. + Standard_Integer aNbCV = 0; + for (TopoDS_Iterator it1(aPrevEdge); it1.More(); it1.Next()) + { + for (TopoDS_Iterator it2(aCurrEdge); it2.More(); it2.Next()) + { + if (it1.Value().IsSame(it2.Value())) + ++aNbCV; + } + } + + // Trim PCurves only if the intersection belongs to current parameter + Standard_Boolean bTrim = (aNbCV == 1 || + (Abs(aTPrev - aTPrevClosest) < (lp - fp) / 2. || + Abs(aTCurr - aTCurrClosest) < (lc - fc) / 2.)); + + if (bTrim) + { + // Check that the intersection point is covered by vertex tolerance + gp_Pnt2d aPInt = aPrevC2d->Value(aTPrevClosest); + const gp_Pnt aPOnS = aBASurf.Value(aPInt.X(), aPInt.Y()); + if (aTolV2 > Precision::Infinite() || aPOnS.SquareDistance(aPV) < aTolV2) + { + Standard_Real f, l; + + // Trim the curves with found parameters + + // Prepare trimming parameters for previous curve + if (Abs(fp - aTPrev) < Abs(lp - aTPrev)) + { + f = aTPrevClosest; + l = lp; + } + else + { + f = fp; + l = aTPrevClosest; + } + + // Trim previous p-curve + if (l - f > Precision::PConfusion()) + aPrevC2d = new Geom2d_TrimmedCurve(aPrevC2d, f, l); + + // Prepare trimming parameters for current p-curve + if (Abs(fc - aTCurr) < Abs(lc - aTCurr)) + { + f = aTCurrClosest; + l = lc; + } + else + { + f = fc; + l = aTCurrClosest; + } + + // Trim current p-curve + if (l - f > Precision::PConfusion()) + aCurrC2d = new Geom2d_TrimmedCurve(aCurrC2d, f, l); + + // Do not create the segment, as we performed the trimming + // to the intersection point. + bAddSegment = Standard_False; + } + } + } + } + } + + if (bAddSegment) + { + // Add segment to the hatcher to trim the iso-lines + Handle(Geom2d_Line) aLine = new Geom2d_Line(aPrevP2d, aV2d); + Handle(Geom2d_TrimmedCurve) aLineSegm = new Geom2d_TrimmedCurve(aLine, 0.0, aSegmLen); + AddElement(Geom2dAdaptor_Curve(aLineSegm), TopAbs_FORWARD); + } + } + } +} diff --git a/src/DBRep/DBRep_IsoBuilder.hxx b/src/DBRep/DBRep_IsoBuilder.hxx index 856ec8d49f..7fa19c022e 100644 --- a/src/DBRep/DBRep_IsoBuilder.hxx +++ b/src/DBRep/DBRep_IsoBuilder.hxx @@ -26,9 +26,11 @@ #include #include #include +#include class TopoDS_Face; class DBRep_Face; - +class TopoDS_Shape; +class TopTools_OrientedShapeMapHasher; //! Creation of isoparametric curves. class DBRep_IsoBuilder : public Geom2dHatch_Hatcher @@ -42,19 +44,30 @@ public: Standard_EXPORT DBRep_IsoBuilder(const TopoDS_Face& TopologicalFace, const Standard_Real Infinite, const Standard_Integer NbIsos); //! Returns the total number of domains. - Standard_Integer NbDomains() const; + Standard_Integer NbDomains() const + { + return myNbDom; + } //! Loading of the isoparametric curves in the //! Data Structure of a drawable face. Standard_EXPORT void LoadIsos (const Handle(DBRep_Face)& Face) const; - - - protected: + typedef NCollection_IndexedDataMap + + DataMapOfEdgePCurve; - + //! Adds to the hatcher the 2D segments connecting the p-curves + //! of the neighboring edges to close the 2D gaps which are + //! closed in 3D by the tolerance of vertices shared between edges. + //! It will allow trimming correctly the iso-lines passing through + //! such gaps. + //! The method also trims the intersecting 2D curves of the face, + //! forbidding the iso-lines beyond the face boundaries. + Standard_EXPORT void FillGaps(const TopoDS_Face& theFace, + DataMapOfEdgePCurve& theEdgePCurveMap); private: @@ -76,10 +89,4 @@ private: }; -#include - - - - - #endif // _DBRep_IsoBuilder_HeaderFile diff --git a/src/DBRep/DBRep_IsoBuilder.lxx b/src/DBRep/DBRep_IsoBuilder.lxx deleted file mode 100644 index 3a06a18f85..0000000000 --- a/src/DBRep/DBRep_IsoBuilder.lxx +++ /dev/null @@ -1,25 +0,0 @@ -// Created on: 1994-03-25 -// Created by: Jean Marc LACHAUME -// Copyright (c) 1994-1999 Matra Datavision -// Copyright (c) 1999-2014 OPEN CASCADE SAS -// -// This file is part of Open CASCADE Technology software library. -// -// This library is free software; you can redistribute it and/or modify it under -// the terms of the GNU Lesser General Public License version 2.1 as published -// by the Free Software Foundation, with special exception defined in the file -// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT -// distribution for complete text of the license and disclaimer of any warranty. -// -// Alternatively, this file may be used under the terms of Open CASCADE -// commercial license or contractual agreement. - -//======================================================================= -// Function : NbDomains -// Purpose : Returns the total number of domains. -//======================================================================= - -inline Standard_Integer DBRep_IsoBuilder::NbDomains () const -{ - return myNbDom ; -} diff --git a/src/DBRep/FILES b/src/DBRep/FILES index 98f36e2e77..3f042dde53 100755 --- a/src/DBRep/FILES +++ b/src/DBRep/FILES @@ -14,7 +14,6 @@ DBRep_HideData.hxx DBRep_HideData.lxx DBRep_IsoBuilder.cxx DBRep_IsoBuilder.hxx -DBRep_IsoBuilder.lxx DBRep_ListIteratorOfListOfEdge.hxx DBRep_ListIteratorOfListOfFace.hxx DBRep_ListIteratorOfListOfHideData.hxx diff --git a/src/math/math_FunctionRoots.cxx b/src/math/math_FunctionRoots.cxx index a6bb20c694..7d565be36b 100644 --- a/src/math/math_FunctionRoots.cxx +++ b/src/math/math_FunctionRoots.cxx @@ -444,7 +444,7 @@ math_FunctionRoots::math_FunctionRoots(math_FunctionWithDerivative& F, //-- Find minimum of the function |F| between x0 and x3 //-- by searching for the zero of the function derivative DerivFunction aDerF(F); - math_BracketedRoot aBR(aDerF, x0, x3, EpsX); + math_BracketedRoot aBR(aDerF, x0, x3, _EpsX); if (aBR.IsDone()) { aSolX1 = aBR.Root(); diff --git a/tests/bugs/modalg_7/bug28385_1 b/tests/bugs/modalg_7/bug28385_1 new file mode 100644 index 0000000000..0ca3bec87e --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_1 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_face.brep] face + +checkview -display face -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_10 b/tests/bugs/modalg_7/bug28385_10 new file mode 100644 index 0000000000..8a2bacfeb0 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_10 @@ -0,0 +1,16 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_two_circ_face_gap.brep] face + +smallview +isos face 50 +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug28385_2 b/tests/bugs/modalg_7/bug28385_2 new file mode 100644 index 0000000000..a1b75369b0 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_2 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_planar_face.brep] face + +checkview -display face -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_3 b/tests/bugs/modalg_7/bug28385_3 new file mode 100644 index 0000000000..2f3243d5a3 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_3 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_two_lines_face.brep] face + +checkview -display face -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_4 b/tests/bugs/modalg_7/bug28385_4 new file mode 100644 index 0000000000..feb48f30f6 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_4 @@ -0,0 +1,16 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_circ_face.brep] face + +smallview +don face; fit +isos face 50 + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug28385_5 b/tests/bugs/modalg_7/bug28385_5 new file mode 100644 index 0000000000..c3ac19cc99 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_5 @@ -0,0 +1,16 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_circ_face_hole.brep] face + +smallview +isos face 50 +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png diff --git a/tests/bugs/modalg_7/bug28385_6 b/tests/bugs/modalg_7/bug28385_6 new file mode 100644 index 0000000000..27836bf266 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_6 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_step4_A8_face.brep] face + +checkview -display face -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_7 b/tests/bugs/modalg_7/bug28385_7 new file mode 100644 index 0000000000..77ee2a3aad --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_7 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_27170_face.brep] face + +checkview -display face -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_8 b/tests/bugs/modalg_7/bug28385_8 new file mode 100644 index 0000000000..7a8544e5d0 --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_8 @@ -0,0 +1,12 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_bug763_faces.brep] faces + +checkview -display faces -2d -path ${imagedir}/${test_image}-2d.png diff --git a/tests/bugs/modalg_7/bug28385_9 b/tests/bugs/modalg_7/bug28385_9 new file mode 100644 index 0000000000..21d26b238f --- /dev/null +++ b/tests/bugs/modalg_7/bug28385_9 @@ -0,0 +1,16 @@ +puts "========" +puts "OCC28385" +puts "========" +puts "" +################################################# +# Improve drawing isolines (DBRep_IsoBuilder algorithm) +################################################# + + +restore [locate_data_file bug28385_two_circ_face.brep] face + +smallview +isos face 50 +fit + +checkview -screenshot -2d -path ${imagedir}/${test_image}.png