1 // File: BRepTools_WireExplorer.cxx
2 // Created: Thu Jan 21 19:09:53 1993
3 // Author: Remi LEQUETTE
7 #include <BRepTools_WireExplorer.ixx>
10 #include <TopoDS_Iterator.hxx>
11 #include <TopTools_MapOfShape.hxx>
12 #include <TopTools_MapIteratorOfMapOfShape.hxx>
13 #include <TopTools_ListOfShape.hxx>
14 #include <TopTools_ListIteratorOfListOfShape.hxx>
15 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
16 #include <BRep_Tool.hxx>
17 #include <gp_Pnt2d.hxx>
18 #include <Precision.hxx>
19 #include <BRepTools.hxx>
20 #include <Geom2d_Curve.hxx>
21 #include <GeomAdaptor_Surface.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <Geom_Surface.hxx>
25 //=======================================================================
26 // forward declarations of aux functions
27 //=======================================================================
28 static Standard_Boolean SelectDouble(TopTools_MapOfShape& Doubles,
29 TopTools_ListOfShape& L,
32 static Standard_Boolean SelectDegenerated(TopTools_ListOfShape& L,
35 static Standard_Real GetNextParamOnPC(const Handle(Geom2d_Curve)& aPC,
36 const gp_Pnt2d& aPRef,
37 const Standard_Real& fP,
38 const Standard_Real& lP,
39 const Standard_Real& tolU,
40 const Standard_Real& tolV,
41 const Standard_Boolean& reverse);
43 //=======================================================================
44 //function : BRepTools_WireExplorer
46 //=======================================================================
47 BRepTools_WireExplorer::BRepTools_WireExplorer()
51 //=======================================================================
52 //function : BRepTools_WireExplorer
54 //=======================================================================
55 BRepTools_WireExplorer::BRepTools_WireExplorer(const TopoDS_Wire& W)
57 TopoDS_Face F = TopoDS_Face();
61 //=======================================================================
62 //function : BRepTools_WireExplorer
64 //=======================================================================
65 BRepTools_WireExplorer::BRepTools_WireExplorer(const TopoDS_Wire& W,
71 //=======================================================================
74 //=======================================================================
75 void BRepTools_WireExplorer::Init(const TopoDS_Wire& W)
77 TopoDS_Face F = TopoDS_Face();
81 //=======================================================================
84 //=======================================================================
85 void BRepTools_WireExplorer::Init(const TopoDS_Wire& W,
88 myEdge = TopoDS_Edge();
89 myVertex = TopoDS_Vertex();
97 Standard_Real dfVertToler = 0.;
98 myReverse = Standard_False;
100 if (!myFace.IsNull())
102 BRepTools::Update(myFace);
104 const Handle(Geom_Surface)& aSurf = BRep_Tool::Surface(myFace, aL);
105 GeomAdaptor_Surface aGAS(aSurf);
106 TopExp_Explorer anExp(W, TopAbs_VERTEX);
107 for(; anExp.More(); anExp.Next())
109 const TopoDS_Vertex& aV = TopoDS::Vertex(anExp.Current());
110 dfVertToler = Max(BRep_Tool::Tolerance(aV), dfVertToler);
112 myTolU = 2. * aGAS.UResolution(dfVertToler);
113 myTolV = 2. * aGAS.VResolution(dfVertToler);
115 // uresolution for cone with infinite vmin vmax is too small.
116 if(aGAS.GetType() == GeomAbs_Cone)
118 Standard_Real u1, u2, v1, v2;
119 BRepTools::UVBounds(myFace, u1, u2, v1, v2);
122 aGAS.D1(u1, v1, aP, aD1U, aD1V);
123 Standard_Real tol1, tol2, maxtol = .0005*(u2-u1);
124 Standard_Real a = aD1U.Magnitude();
126 if(a <= Precision::Confusion())
129 tol1 = Min(maxtol, dfVertToler/a);
131 aGAS.D1(u1, v2, aP, aD1U, aD1V);
132 a = aD1U.Magnitude();
133 if(a <= Precision::Confusion())
136 tol2 = Min(maxtol, dfVertToler/a);
138 myTolU = 2. * Max(tol1, tol2);
141 if( aGAS.GetType() == GeomAbs_BSplineSurface ||
142 aGAS.GetType() == GeomAbs_BezierSurface )
144 Standard_Real maxTol = Max(myTolU,myTolV);
149 myReverse = (myFace.Orientation() == TopAbs_REVERSED);
152 // map of vertices to know if the wire is open
153 TopTools_MapOfShape vmap;
154 // Modified by Sergey KHROMOV - Mon May 13 11:50:48 2002 Begin
155 // map of infinite edges
156 TopTools_MapOfShape anInfEmap;
157 // Modified by Sergey KHROMOV - Mon May 13 11:50:49 2002 End
161 TopTools_ListOfShape empty;
163 TopoDS_Iterator it(W);
166 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
167 TopAbs_Orientation Eori = E.Orientation();
168 if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL)
173 TopExp::Vertices(E,V1,V2,Standard_True);
177 if( !myMap.IsBound(V1) )
178 myMap.Bind(V1,empty);
181 // add or remove in the vertex map
182 V1.Orientation(TopAbs_FORWARD);
189 V2.Orientation(TopAbs_REVERSED);
194 // Modified by Sergey KHROMOV - Mon May 13 11:52:20 2002 Begin
195 if (V1.IsNull() || V2.IsNull())
197 Standard_Real aF = 0., aL = 0.;
198 BRep_Tool::Range(E, aF, aL);
200 if(Eori == TopAbs_FORWARD)
202 if (aF == -Precision::Infinite())
206 { // Eori == TopAbs_REVERSED
207 if (aL == Precision::Infinite())
211 // Modified by Sergey KHROMOV - Mon May 13 11:52:20 2002 End
215 //Construction of the set of double edges.
216 TopoDS_Iterator it2(W);
217 TopTools_MapOfShape emap;
219 if (!emap.Add(it2.Value()))
220 myDoubles.Add(it2.Value());
224 // if vmap is not empty the wire is open, let us find the first vertex
225 if (!vmap.IsEmpty()) {
226 TopTools_MapIteratorOfMapOfShape itt(vmap); // skl : I change "it" to "itt"
227 while (itt.Key().Orientation() != TopAbs_FORWARD) {
229 if (!itt.More()) break;
231 if (itt.More()) V1 = TopoDS::Vertex(itt.Key());
234 // Modified by Sergey KHROMOV - Mon May 13 12:05:30 2002 Begin
235 // The wire is infinite Try to find the first vertex. It may be NULL.
236 if (!anInfEmap.IsEmpty()) {
237 TopTools_MapIteratorOfMapOfShape itt(anInfEmap);
239 for (; itt.More(); itt.Next()) {
240 TopoDS_Edge anEdge = TopoDS::Edge(itt.Key());
241 TopAbs_Orientation anOri = anEdge.Orientation();
245 BRep_Tool::Range(anEdge, aF, aL);
246 if ((anOri == TopAbs_FORWARD && aF == -Precision::Infinite()) ||
247 (anOri == TopAbs_REVERSED && aL == Precision::Infinite())) {
249 myVertex = TopoDS_Vertex();
255 // Modified by Sergey KHROMOV - Mon May 13 12:05:31 2002 End
258 // use the first vertex in iterator
261 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
262 TopAbs_Orientation Eori = E.Orientation();
263 if (Eori == TopAbs_INTERNAL || Eori == TopAbs_EXTERNAL) {
264 // JYL 10-03-97 : waiting for correct processing
265 // of INTERNAL/EXTERNAL edges
269 TopExp::Vertices(E,V1,V2,Standard_True);
274 if (V1.IsNull() ) return;
275 if (!myMap.IsBound(V1)) return;
277 TopTools_ListOfShape& l = myMap(V1);
278 myEdge = TopoDS::Edge(l.First());
280 myVertex = TopExp::FirstVertex (myEdge, Standard_True);
284 //=======================================================================
287 //=======================================================================
288 Standard_Boolean BRepTools_WireExplorer::More()const
290 return !myEdge.IsNull();
293 //=======================================================================
296 //=======================================================================
297 void BRepTools_WireExplorer::Next()
299 myVertex = TopExp::LastVertex (myEdge, Standard_True);
301 if (myVertex.IsNull()) {
302 myEdge = TopoDS_Edge();
305 if (!myMap.IsBound(myVertex)) {
306 myEdge = TopoDS_Edge();
310 TopTools_ListOfShape& l = myMap(myVertex);
313 myEdge = TopoDS_Edge();
315 else if (l.Extent() == 1) {
316 // Modified by Sergey KHROMOV - Fri Jun 21 10:28:01 2002 OCC325 Begin
319 TopoDS_Edge aNextEdge = TopoDS::Edge(l.First());
321 TopExp::Vertices(aNextEdge, aV1, aV2, Standard_True);
323 if (!aV1.IsSame(myVertex)) {
324 myEdge = TopoDS_Edge();
327 if (!myFace.IsNull() && aV1.IsSame(aV2)) {
328 Handle(Geom2d_Curve) aPrevPC;
329 Handle(Geom2d_Curve) aNextPC;
330 Standard_Real aPar11, aPar12;
331 Standard_Real aPar21, aPar22;
332 Standard_Real aPrevPar;
333 Standard_Real aNextFPar;
334 Standard_Real aNextLPar;
336 aPrevPC = BRep_Tool::CurveOnSurface(myEdge, myFace, aPar11, aPar12);
337 aNextPC = BRep_Tool::CurveOnSurface(aNextEdge, myFace, aPar21, aPar22);
339 if (aPrevPC.IsNull() || aNextPC.IsNull()) {
340 myEdge = TopoDS_Edge();
344 if (myEdge.Orientation() == TopAbs_FORWARD)
349 if (aNextEdge.Orientation() == TopAbs_FORWARD) {
357 gp_Pnt2d aPPrev = aPrevPC->Value(aPrevPar);
358 gp_Pnt2d aPNextF = aNextPC->Value(aNextFPar);
359 gp_Pnt2d aPNextL = aNextPC->Value(aNextLPar);
361 if (aPPrev.SquareDistance(aPNextF) > aPPrev.SquareDistance(aPNextL)) {
362 myEdge = TopoDS_Edge();
366 // Modified by Sergey KHROMOV - Fri Jun 21 11:08:16 2002 End
367 myEdge = TopoDS::Edge(l.First());
371 if (myFace.IsNull()) {
372 // Without Face - try to return edges
373 // as logically as possible
374 // At first degenerated edges.
375 TopoDS_Edge E = myEdge;
376 if (SelectDegenerated(l,E)) {
380 // At second double edges.
382 if (SelectDouble(myDoubles,l,E)) {
387 TopTools_ListIteratorOfListOfShape it(l);
388 Standard_Boolean notfound = Standard_True;
390 if (!it.Value().IsSame(myEdge)) {
391 myEdge = TopoDS::Edge(it.Value());
393 notfound = Standard_False;
400 myEdge = TopoDS_Edge();
407 // If we have more than one edge attached to the list
408 // probably wire that we explore contains a loop or loops.
409 Standard_Real dfFPar = 0., dfLPar = 0.;
410 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface (myEdge, myFace, dfFPar, dfLPar);
413 myEdge = TopoDS_Edge();
416 // Note: current < myVertex > which is last on < myEdge >
417 // equals in 2D to following 2D points:
418 // edge is FORWARD - point with MAX parameter on PCurve;
419 // edge is REVERSED - point with MIN parameter on PCurve.
421 // Get 2D point equals to < myVertex > in 2D for current edge.
423 if( myEdge.Orientation() == TopAbs_REVERSED )
424 aPCurve->D0(dfFPar, PRef);
426 aPCurve->D0(dfLPar, PRef);
428 // Get next 2D point from current edge's PCurve with parameter
429 // F + dP (REV) or L - dP (FOR)
430 Standard_Boolean isrevese = ( myEdge.Orientation() == TopAbs_REVERSED );
431 Standard_Real dfMPar = GetNextParamOnPC(aPCurve,PRef,dfFPar,dfLPar,myTolU,myTolV,isrevese);
434 aPCurve->D0(dfMPar, PRefm);
435 // Get vector from PRef to PRefm
436 gp_Vec2d anERefDir(PRef,PRefm);
437 // Search the list of edges looking for the edge having hearest
438 // 2D point of connected vertex to current one and smallest angle.
439 // First process all degenerated edges, then - all others.
441 TopTools_ListIteratorOfListOfShape it;
442 Standard_Integer k = 1, kMin = 0, iDone = 0;
443 Standard_Boolean isDegenerated = Standard_True;
444 Standard_Real dmin = RealLast();
445 Standard_Real dfMinAngle = 3.0*M_PI, dfCurAngle = 3.0*M_PI;
447 for(iDone = 0; iDone < 2; iDone++)
452 const TopoDS_Edge& E = TopoDS::Edge(it.Value());
453 if( E.IsSame(myEdge) )
460 TopoDS_Vertex aVert1, aVert2;
461 TopExp::Vertices (E, aVert1, aVert2, Standard_True);
462 if( aVert1.IsNull() || aVert2.IsNull() )
469 aPCurve = BRep_Tool::CurveOnSurface (E, myFace, dfFPar, dfLPar);
470 if( aPCurve.IsNull() )
478 if( aVert1.IsSame(aVert2) == isDegenerated )
480 if( E.Orientation() == TopAbs_REVERSED )
481 aPCurve->D0(dfLPar, aPEb);
483 aPCurve->D0(dfFPar, aPEb);
485 if( Abs(dfLPar-dfFPar) > Precision::PConfusion() )
487 isrevese = ( E.Orientation() == TopAbs_REVERSED );
488 isrevese = !isrevese;
489 Standard_Real aEPm = GetNextParamOnPC(aPCurve,aPEb,dfFPar,dfLPar,myTolU,myTolV,isrevese);
491 aPCurve->D0 (aEPm, aPEe);
492 gp_Vec2d anEDir(aPEb, aPEe);
493 dfCurAngle = Abs( anEDir.Angle(anERefDir) );
496 if( dfCurAngle <= dfMinAngle )
498 Standard_Real d = PRef.SquareDistance(aPEb);
499 if( d <= Precision::PConfusion() )
501 if( Abs(aPEb.X()-PRef.X()) < myTolU && Abs(aPEb.Y()-PRef.Y()) < myTolV )
505 dfMinAngle = dfCurAngle;
518 isDegenerated = Standard_False;
528 // probably unclosed in 2d space wire
529 myEdge = TopoDS_Edge();
533 // Selection the edge.
540 myEdge = TopoDS::Edge(it.Value());
547 }//else face != NULL && l > 1
551 //=======================================================================
554 //=======================================================================
555 const TopoDS_Edge& BRepTools_WireExplorer::Current()const
560 //=======================================================================
561 //function : Orientation
563 //=======================================================================
564 TopAbs_Orientation BRepTools_WireExplorer::Orientation() const
566 TopoDS_Iterator it(myEdge,Standard_False);
568 if (myVertex.IsSame(it.Value()))
569 return it.Value().Orientation();
572 Standard_NoSuchObject::Raise("BRepTools_WireExplorer::Orientation");
573 return TopAbs_FORWARD;
576 //=======================================================================
577 //function : CurrentVertex
579 //=======================================================================
580 const TopoDS_Vertex& BRepTools_WireExplorer::CurrentVertex() const
585 //=======================================================================
588 //=======================================================================
590 void BRepTools_WireExplorer::Clear()
594 myEdge = TopoDS_Edge();
595 myFace = TopoDS_Face();
596 myVertex = TopoDS_Vertex();
600 //=======================================================================
601 //function : SelectDouble
603 //=======================================================================
605 Standard_Boolean SelectDouble(TopTools_MapOfShape& Doubles,
606 TopTools_ListOfShape& L,
609 TopTools_ListIteratorOfListOfShape it(L);
611 for (; it.More(); it.Next()) {
612 const TopoDS_Shape& CE = it.Value();
613 if (Doubles.Contains(CE) && (!E.IsSame(CE))) {
614 E = TopoDS::Edge(CE);
622 //=======================================================================
623 //function : SelectDegenerated
625 //=======================================================================
627 Standard_Boolean SelectDegenerated(TopTools_ListOfShape& L,
630 TopTools_ListIteratorOfListOfShape it(L);
632 if (!it.Value().IsSame(E)) {
633 E = TopoDS::Edge(it.Value());
634 if (BRep_Tool::Degenerated(E)) {
644 //=======================================================================
645 //function : GetNextParamOnPC
647 //=======================================================================
648 Standard_Real GetNextParamOnPC(const Handle(Geom2d_Curve)& aPC,
649 const gp_Pnt2d& aPRef,
650 const Standard_Real& fP,
651 const Standard_Real& lP,
652 const Standard_Real& tolU,
653 const Standard_Real& tolV,
654 const Standard_Boolean& reverse)
656 Standard_Real result = ( reverse ) ? fP : lP;
657 Standard_Real dP = Abs( lP - fP ) / 1000.; // was / 16.;
660 Standard_Real startPar = fP;
661 Standard_Boolean nextPntOnEdge = Standard_False;
662 while( !nextPntOnEdge && startPar < lP )
666 aPC->D0(startPar, pnt);
667 if( Abs( aPRef.X() - pnt.X() ) < tolU && Abs( aPRef.Y() - pnt.Y() ) < tolV )
672 nextPntOnEdge = Standard_True;
685 Standard_Real startPar = lP;
686 Standard_Boolean nextPntOnEdge = Standard_False;
687 while( !nextPntOnEdge && startPar > fP )
691 aPC->D0(startPar, pnt);
692 if( Abs( aPRef.X() - pnt.X() ) < tolU && Abs( aPRef.Y() - pnt.Y() ) < tolV )
697 nextPntOnEdge = Standard_True;