1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either
7 // version 2.1 of the License.
9 // This library is distributed in the hope that it will be useful
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 // Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public
15 // License along with this library; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: GEOMAlgo_WireSplitter.cxx
22 // Author: Peter KURNEV
26 #include <GEOMAlgo_WireSplitter.ixx>
28 #include <TColStd_SequenceOfReal.hxx>
29 #include <Precision.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Vec2d.hxx>
33 #include <TColgp_SequenceOfPnt2d.hxx>
35 #include <Geom_Curve.hxx>
36 #include <Geom2d_Curve.hxx>
37 #include <GeomAdaptor_Surface.hxx>
39 #include <TopAbs_Orientation.hxx>
42 #include <TopoDS_Vertex.hxx>
43 #include <TopoDS_Edge.hxx>
44 #include <TopoDS_Face.hxx>
45 #include <TopoDS_Iterator.hxx>
48 #include <BRep_Tool.hxx>
49 #include <BRepAdaptor_Surface.hxx>
50 #include <BRepAdaptor_Curve2d.hxx>
53 #include <TopExp_Explorer.hxx>
57 #include <TopTools_SequenceOfShape.hxx>
58 #include <TopTools_ListOfShape.hxx>
59 #include <TopTools_ListIteratorOfListOfShape.hxx>
60 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
61 #include <TopTools_IndexedMapOfShape.hxx>
63 #include <BOPTColStd_ListOfListOfShape.hxx>
64 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
66 #include <BOPTools_Tools2D.hxx>
68 #include <BOP_EdgeInfo.hxx>
69 #include <BOP_ListOfEdgeInfo.hxx>
70 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
71 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
74 void Path (const GeomAdaptor_Surface& aGAS,
75 const TopoDS_Face& myFace,
76 const TopoDS_Vertex& aVa,
77 const TopoDS_Edge& aEOuta,
78 BOP_EdgeInfo& anEdgeInfo,
79 TopTools_SequenceOfShape& aLS,
80 TopTools_SequenceOfShape& aVertVa,
81 TColgp_SequenceOfPnt2d& aCoordVa,
82 BOPTColStd_ListOfListOfShape& myShapes,
83 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
87 Standard_Real Angle (const gp_Dir2d& aDir2D);
91 void GetNextVertex(const TopoDS_Vertex& aV,
92 const TopoDS_Edge& aE,
95 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
96 const Standard_Real aAngleOut);
99 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
100 const BOP_ListOfEdgeInfo& aLEInfo);
103 Standard_Real Angle2D (const TopoDS_Vertex& aV,
104 const TopoDS_Edge& anEdge,
105 const TopoDS_Face& myFace,
106 const GeomAdaptor_Surface& aGAS,
107 const Standard_Boolean aFlag);
109 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
110 const TopoDS_Edge& aE1,
111 const TopoDS_Face& aF);
113 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
114 const TopoDS_Face& aF);
116 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
117 const GeomAdaptor_Surface& aGAS);
120 void UVTolerance2D (const TopoDS_Vertex& aV,
121 const GeomAdaptor_Surface& aGAS,
122 Standard_Real& aTolU,
123 Standard_Real& aTolV);
125 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
128 //=======================================================================
131 //=======================================================================
132 GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
135 myNothingToDo(Standard_False)
138 //=======================================================================
141 //=======================================================================
142 GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
145 //=======================================================================
148 //=======================================================================
149 void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
153 //=======================================================================
156 //=======================================================================
157 const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
161 //=======================================================================
162 // function: SetEdges
164 //=======================================================================
165 void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
167 TopTools_ListIteratorOfListOfShape anIt;
170 anIt.Initialize(aLE);
171 for (; anIt.More(); anIt.Next()) {
172 const TopoDS_Shape& aE =anIt.Value();
174 if (aE.Orientation()==TopAbs_INTERNAL){
181 //=======================================================================
184 //=======================================================================
185 const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
189 //=======================================================================
190 // function: IsNothingToDo
192 //=======================================================================
193 Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
195 return myNothingToDo;
197 //=======================================================================
200 //=======================================================================
201 const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
205 //=======================================================================
208 //=======================================================================
209 void GEOMAlgo_WireSplitter::Perform()
212 myNothingToDo=Standard_True;
214 Standard_Integer index, i, aNb, aCntIn, aCntOut;
215 Standard_Boolean anIsIn;
216 Standard_Real anAngle;
218 BOP_ListOfEdgeInfo emptyInfo;
219 TopTools_ListIteratorOfListOfShape anItList;
221 // 1.Filling mySmartMap
224 anItList.Initialize(myEdges);
225 for (; anItList.More(); anItList.Next()) {
226 const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
228 if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
232 TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
233 for (; anExpVerts.More(); anExpVerts.Next()) {
234 const TopoDS_Shape& aVertex= anExpVerts.Current();
236 index = mySmartMap.FindIndex(aVertex);
238 index=mySmartMap.Add(aVertex, emptyInfo);
241 BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
244 aEInfo.SetEdge(anEdge);
246 TopAbs_Orientation anOr=aVertex.Orientation();
248 if (anOr==TopAbs_FORWARD) {
249 aEInfo.SetInFlag(Standard_False);
252 else if (anOr==TopAbs_REVERSED) {
253 aEInfo.SetInFlag(Standard_True);
256 aListOfEInfo.Append(aEInfo);
260 aNb=mySmartMap.Extent();
263 myNothingToDo=Standard_True;
265 for (i=1; i<=aNb; i++) {
268 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
269 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
270 for (; anIt.More(); anIt.Next()) {
271 const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
272 anIsIn=anEdgeInfo.IsIn();
280 if (aCntIn!=1 || aCntOut!=1) {
281 myNothingToDo=Standard_False;
286 // Each vertex has one edge In and one - Out. Good. But it is not enought
287 // to consider that nothing to do with this. We must check edges on TShape
288 // coinsidence. If there are such edges there is something to do with.
291 Standard_Integer aNbE, aNbMapEE;
292 TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
293 aNbE=myEdges.Extent();
295 anItList.Initialize(myEdges);
296 for (; anItList.More(); anItList.Next()) {
297 const TopoDS_Shape& aE = anItList.Value();
299 if (!aMapEE.Contains(aE)) {
300 TopTools_ListOfShape aLEx;
302 aMapEE.Add(aE, aLEx);
305 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
310 Standard_Boolean bFlag;
312 aNbMapEE=aMapEE.Extent();
313 for (i=1; i<=aNbMapEE; i++) {
314 const TopTools_ListOfShape& aLEx=aMapEE(i);
321 const TopoDS_Shape& aE1=aLEx.First();
322 const TopoDS_Shape& aE2=aLEx.Last();
323 if (aE1.IsSame(aE2)) {
324 bFlag=Standard_False;
329 bFlag=Standard_False;
333 myNothingToDo=myNothingToDo && bFlag;
342 // 3. Angles in mySmartMap
343 BRepAdaptor_Surface aBAS(myFace);
344 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
345 for (i=1; i<=aNb; i++) {
346 const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
347 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
349 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
350 for (; anIt.More(); anIt.Next()) {
351 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
352 const TopoDS_Edge& aE=anEdgeInfo.Edge();
354 TopoDS_Vertex aVV=aV;
356 anIsIn=anEdgeInfo.IsIn();
359 aVV.Orientation(TopAbs_REVERSED);
360 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
365 aVV.Orientation(TopAbs_FORWARD);
366 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
368 anEdgeInfo.SetAngle(anAngle);
375 Standard_Boolean anIsOut, anIsNotPassed;
377 TopTools_SequenceOfShape aLS, aVertVa;
378 TColgp_SequenceOfPnt2d aCoordVa;
380 BOP_ListIteratorOfListOfEdgeInfo anIt;
382 for (i=1; i<=aNb; i++) {
383 const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
384 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
386 anIt.Initialize(aLEInfo);
387 for (; anIt.More(); anIt.Next()) {
388 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
389 const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
391 anIsOut=!anEdgeInfo.IsIn();
392 anIsNotPassed=!anEdgeInfo.Passed();
394 if (anIsOut && anIsNotPassed) {
400 Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS,
401 aVertVa, aCoordVa, myShapes, mySmartMap);
407 Standard_Integer aNbV, aNbE;
408 TopoDS_Vertex aV1, aV2;
409 BOPTColStd_ListOfListOfShape aShapes;
410 BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
412 for (; anItW.More(); anItW.Next()) {
413 TopTools_IndexedMapOfShape aMV, aME;
414 const TopTools_ListOfShape& aLE=anItW.Value();
415 TopTools_ListIteratorOfListOfShape anItE(aLE);
416 for (; anItE.More(); anItE.Next()) {
417 const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
419 TopExp::Vertices(aE, aV1, aV2);
431 anItW.Initialize(aShapes);
432 for (; anItW.More(); anItW.Next()) {
433 const TopTools_ListOfShape& aLE=anItW.Value();
434 myShapes.Append(aLE);
440 //=======================================================================
443 //=======================================================================
444 void Path (const GeomAdaptor_Surface& aGAS,
445 const TopoDS_Face& myFace,
446 const TopoDS_Vertex& aVa,
447 const TopoDS_Edge& aEOuta,
448 BOP_EdgeInfo& anEdgeInfo,
449 TopTools_SequenceOfShape& aLS,
450 TopTools_SequenceOfShape& aVertVa,
451 TColgp_SequenceOfPnt2d& aCoordVa,
452 BOPTColStd_ListOfListOfShape& myShapes,
453 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
456 Standard_Integer i,j, aNb, aNbj;
457 Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
458 Standard_Real aTol2D, aTol2D2;
459 Standard_Real aTol2, aD2, aTolUVb, aTolVVb;
460 Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
461 BOP_ListIteratorOfListOfEdgeInfo anIt;
469 // Do not escape through edge from which you enter
472 const TopoDS_Shape& anEPrev=aLS(aNb);
473 if (anEPrev.IsSame(aEOuta)) {
479 anEdgeInfo.SetPassed(Standard_True);
483 TopoDS_Vertex pVa=aVa;
484 pVa.Orientation(TopAbs_FORWARD);
485 gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
486 aCoordVa.Append(aPa);
488 GetNextVertex (pVa, aEOuta, aVb);
490 gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
492 const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb);
494 aTol=2.*Tolerance2D(aVb, aGAS);
497 UVTolerance2D(aVb, aGAS, aTolUVb, aTolVVb);
498 aTolUVb = 2.*aTolUVb;
499 aTolVVb = 2.*aTolVVb;
504 TopTools_ListOfShape aBuf;
506 for (i=aNb; i>0; i--) {
507 const TopoDS_Shape& aVPrev=aVertVa(i);
508 const gp_Pnt2d& aPaPrev=aCoordVa(i);
509 const TopoDS_Shape& aEPrev=aLS(i);
513 anIsSameV=aVPrev.IsSame(aVb);
514 anIsSameV2d = Standard_False;
517 anIsSameV2d = Standard_True;
519 aD2=aPaPrev.SquareDistance(aPb);
520 anIsSameV2d =aD2<aTol2;
523 Standard_Real udist, vdist;
525 udist=fabs(aPaPrev.X() - aPb.X());
526 vdist=fabs(aPaPrev.Y() - aPb.Y());
527 if((udist > aTolUVb) || (vdist > aTolVVb)) {
528 anIsSameV2d=!anIsSameV2d;
533 if (anIsSameV && anIsSameV2d) {
534 myShapes.Append(aBuf);
536 TopTools_SequenceOfShape aLSt, aVertVat;
537 TColgp_SequenceOfPnt2d aCoordVat;
549 aVb=TopoDS::Vertex(aVertVa(i));
551 for (j=1; j<=aNbj; j++) {
553 aVertVat.Append(aVertVa(j));
554 aCoordVat.Append(aCoordVa(j));
570 aTol2D=2.*Tolerance2D(aVb, aGAS);
571 aTol2D2=aTol2D*aTol2D;
573 // anAngleIn in Vb from edge aEOuta
574 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
576 anAngleIn=AngleIn(aEOuta, aLEInfo);
579 BOP_EdgeInfo *pEdgeInfo=NULL;
582 anIsFound=Standard_False;
584 Standard_Integer aCurIndexE = 0;
586 anIt.Initialize(aLEInfo);
587 for (; anIt.More(); anIt.Next()) {
588 BOP_EdgeInfo& anEI=anIt.Value();
589 const TopoDS_Edge& aE=anEI.Edge();
590 anIsOut=!anEI.IsIn();
591 anIsNotPassed=!anEI.Passed();
593 if (anIsOut && anIsNotPassed) {
596 // Is there one way to go out of the vertex
597 // we have to use it only.
598 Standard_Integer iCnt;
599 iCnt=NbWaysOut (aLEInfo);
602 // no way to go . (Error)
607 // the one and only way to go out .
609 anIsFound=Standard_True;
613 // Look for minimal angle and make the choice.
616 aP2Dx=Coord2dVf(aE, myFace);
618 aD2=aP2Dx.SquareDistance(aPb);
624 anAngleOut=anEI.Angle();
626 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
627 if (anAngle < aMinAngle) {
630 anIsFound=Standard_True;
633 } // for (; anIt.More(); anIt.Next())
636 // no way to go . (Error)
640 aEOutb=pEdgeInfo->Edge();
642 Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
643 aVertVa, aCoordVa, myShapes, mySmartMap);
645 //=======================================================================
646 // function: Coord2dVf
648 //=======================================================================
649 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
650 const TopoDS_Face& aF)
652 Standard_Real aCoord=99.;
653 gp_Pnt2d aP2D1(aCoord, aCoord);
657 for (; aIt.More(); aIt.Next()) {
658 const TopoDS_Shape& aVx=aIt.Value();
659 if (aVx.Orientation()==TopAbs_FORWARD) {
660 const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
661 aP2D1=Coord2d(aVxx, aE, aF);
667 //=======================================================================
668 // function: Tolerance2D
670 //=======================================================================
671 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
672 const GeomAdaptor_Surface& aGAS)
674 Standard_Real aTol2D, anUr, aVr, aTolV3D;
675 GeomAbs_SurfaceType aType;
677 aType=aGAS.GetType();
678 aTolV3D=BRep_Tool::Tolerance(aV);
680 anUr=aGAS.UResolution(aTolV3D);
681 aVr =aGAS.VResolution(aTolV3D);
682 aTol2D=(aVr>anUr) ? aVr : anUr;
684 if (aType==GeomAbs_BSplineSurface||
685 aType==GeomAbs_Sphere) {
686 if (aTol2D < aTolV3D) {
690 if (aType==GeomAbs_BSplineSurface) {
697 //=======================================================================
700 //=======================================================================
701 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
702 const TopoDS_Edge& aE1,
703 const TopoDS_Face& aF)
705 Standard_Real aT, aFirst, aLast;
706 Handle(Geom2d_Curve) aC2D;
709 aT=BRep_Tool::Parameter (aV1, aE1, aF);
710 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
711 aC2D->D0 (aT, aP2D1);
715 //=======================================================================
718 //=======================================================================
719 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
720 const BOP_ListOfEdgeInfo& aLEInfo)
722 Standard_Real anAngleIn;
723 Standard_Boolean anIsIn;
724 BOP_ListIteratorOfListOfEdgeInfo anIt;
726 anIt.Initialize(aLEInfo);
727 for (; anIt.More(); anIt.Next()) {
728 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
729 const TopoDS_Edge& aE=anEdgeInfo.Edge();
730 anIsIn=anEdgeInfo.IsIn();
732 if (anIsIn && aE==aEIn) {
733 anAngleIn=anEdgeInfo.Angle();
740 //=======================================================================
741 // function: ClockWiseAngle
743 //=======================================================================
744 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
745 const Standard_Real aAngleOut)
747 Standard_Real aTwoPi=Standard_PI+Standard_PI;
748 Standard_Real dA, A1, A2, AIn, AOut ;
756 if (AOut >= aTwoPi) {
773 //else if (dA <= 1.e-15) {
774 else if (dA <= 1.e-14) {
779 //=======================================================================
780 // function: GetNextVertex
782 //=======================================================================
783 void GetNextVertex(const TopoDS_Vertex& aV,
784 const TopoDS_Edge& aE,
790 for (; aIt.More(); aIt.Next()) {
791 const TopoDS_Shape& aVx=aIt.Value();
792 if (!aVx.IsEqual(aV)) {
793 aV1=TopoDS::Vertex(aVx);
799 //=======================================================================
802 //=======================================================================
803 Standard_Real Angle2D (const TopoDS_Vertex& aV,
804 const TopoDS_Edge& anEdge,
805 const TopoDS_Face& myFace,
806 const GeomAdaptor_Surface& aGAS,
807 const Standard_Boolean aFlag)
809 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle;
811 Handle(Geom2d_Curve) aC2D;
813 BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
814 aFirst, aLast, aToler, Standard_True);
816 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
817 if (Precision::IsInfinite(aTV))
821 dt=Tolerance2D(aV, aGAS);
823 if(dt > (aLast - aFirst) * 0.25) {
824 // to save direction of the curve as much as it possible
825 // in the case of big tolerances
826 dt = (aLast - aFirst) * 0.25;
829 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
838 aC2D->D0 (aTV1, aPV1);
843 gp_Vec2d aV2DIn(aPV1, aPV);
849 gp_Vec2d aV2DOut(aPV, aPV1);
853 gp_Dir2d aDir2D(aV2D);
854 anAngle=Angle(aDir2D);
858 //=======================================================================
861 //=======================================================================
862 Standard_Real Angle (const gp_Dir2d& aDir2D)
864 gp_Dir2d aRefDir(1., 0.);
865 Standard_Real anAngle = aRefDir.Angle(aDir2D);
868 anAngle += Standard_PI + Standard_PI;
873 //=======================================================================
874 // function: NbWaysOut
876 //=======================================================================
877 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
879 Standard_Boolean bIsOut, bIsNotPassed;
880 Standard_Integer iCnt=0;
881 BOP_ListIteratorOfListOfEdgeInfo anIt;
883 anIt.Initialize(aLEInfo);
884 for (; anIt.More(); anIt.Next()) {
885 BOP_EdgeInfo& anEI=anIt.Value();
888 bIsNotPassed=!anEI.Passed();
889 if (bIsOut && bIsNotPassed) {
895 //=======================================================================
896 //function : UVTolerance2D
898 //=======================================================================
899 void UVTolerance2D (const TopoDS_Vertex& aV,
900 const GeomAdaptor_Surface& aGAS,
901 Standard_Real& aTolU,
902 Standard_Real& aTolV)
904 Standard_Real aTolV3D;
906 aTolV3D = BRep_Tool::Tolerance(aV);
907 aTolU=aGAS.UResolution(aTolV3D);
908 aTolV=aGAS.VResolution(aTolV3D);