1 // Copyright (C) 2007-2012 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 // This library is free software; you can redistribute it and/or
7 // modify it under the terms of the GNU Lesser General Public
8 // License as published by the Free Software Foundation; either
9 // version 2.1 of the License.
11 // This library is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 // Lesser General Public License for more details.
16 // You should have received a copy of the GNU Lesser General Public
17 // License along with this library; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
23 // File: GEOMAlgo_WireSplitter.cxx
24 // Author: Peter KURNEV
26 #include <GEOMAlgo_WireSplitter.hxx>
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>
47 #include <BRep_Tool.hxx>
48 #include <BRepAdaptor_Surface.hxx>
49 #include <BRepAdaptor_Curve2d.hxx>
52 #include <TopExp_Explorer.hxx>
54 #include <TopTools_SequenceOfShape.hxx>
55 #include <TopTools_ListOfShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
58 #include <TopTools_IndexedMapOfShape.hxx>
60 #include <BOPTColStd_ListOfListOfShape.hxx>
61 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
63 #include <BOPTools_Tools2D.hxx>
65 #include <BOP_EdgeInfo.hxx>
66 #include <BOP_ListOfEdgeInfo.hxx>
67 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
68 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
71 void Path (const GeomAdaptor_Surface& aGAS,
72 const TopoDS_Face& myFace,
73 const TopoDS_Vertex& aVa,
74 const TopoDS_Edge& aEOuta,
75 BOP_EdgeInfo& anEdgeInfo,
76 TopTools_SequenceOfShape& aLS,
77 TopTools_SequenceOfShape& aVertVa,
78 TColgp_SequenceOfPnt2d& aCoordVa,
79 BOPTColStd_ListOfListOfShape& myShapes,
80 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
84 Standard_Real Angle (const gp_Dir2d& aDir2D);
88 void GetNextVertex(const TopoDS_Vertex& aV,
89 const TopoDS_Edge& aE,
92 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
93 const Standard_Real aAngleOut);
96 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
97 const BOP_ListOfEdgeInfo& aLEInfo);
100 Standard_Real Angle2D (const TopoDS_Vertex& aV,
101 const TopoDS_Edge& anEdge,
102 const TopoDS_Face& myFace,
103 const GeomAdaptor_Surface& aGAS,
104 const Standard_Boolean aFlag);
106 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
107 const TopoDS_Edge& aE1,
108 const TopoDS_Face& aF);
110 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
111 const TopoDS_Face& aF);
113 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
114 const GeomAdaptor_Surface& aGAS);
117 //modified by NIZNHY-PKV Thu Apr 19 09:04:59 2012f
119 Standard_Integer NbWaysOut(const TopoDS_Edge& aEOuta,
120 const BOP_ListOfEdgeInfo& aLEInfo);
122 // Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
123 //modified by NIZNHY-PKV Thu Apr 19 09:04:53 2012t
125 //=======================================================================
128 //=======================================================================
129 GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
132 myNothingToDo(Standard_False)
135 //=======================================================================
138 //=======================================================================
139 GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
142 //=======================================================================
145 //=======================================================================
146 void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
150 //=======================================================================
153 //=======================================================================
154 const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
158 //=======================================================================
159 // function: SetEdges
161 //=======================================================================
162 void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
164 TopTools_ListIteratorOfListOfShape anIt;
167 anIt.Initialize(aLE);
168 for (; anIt.More(); anIt.Next()) {
169 const TopoDS_Shape& aE =anIt.Value();
171 if (aE.Orientation()==TopAbs_INTERNAL){
178 //=======================================================================
181 //=======================================================================
182 const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
186 //=======================================================================
187 // function: IsNothingToDo
189 //=======================================================================
190 Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
192 return myNothingToDo;
194 //=======================================================================
197 //=======================================================================
198 const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
202 //=======================================================================
205 //=======================================================================
206 void GEOMAlgo_WireSplitter::Perform()
209 myNothingToDo=Standard_True;
211 Standard_Integer index, i, aNb, aCntIn, aCntOut;
212 Standard_Boolean anIsIn;
213 Standard_Real anAngle;
215 BOP_ListOfEdgeInfo emptyInfo;
216 TopTools_ListIteratorOfListOfShape anItList;
218 // 1.Filling mySmartMap
221 anItList.Initialize(myEdges);
222 for (; anItList.More(); anItList.Next()) {
223 const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
225 if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
229 TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
230 for (; anExpVerts.More(); anExpVerts.Next()) {
231 const TopoDS_Shape& aVertex= anExpVerts.Current();
233 index = mySmartMap.FindIndex(aVertex);
235 index=mySmartMap.Add(aVertex, emptyInfo);
238 BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
241 aEInfo.SetEdge(anEdge);
243 TopAbs_Orientation anOr=aVertex.Orientation();
245 if (anOr==TopAbs_FORWARD) {
246 aEInfo.SetInFlag(Standard_False);
249 else if (anOr==TopAbs_REVERSED) {
250 aEInfo.SetInFlag(Standard_True);
253 aListOfEInfo.Append(aEInfo);
257 aNb=mySmartMap.Extent();
260 myNothingToDo=Standard_True;
262 for (i=1; i<=aNb; i++) {
265 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
266 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
267 for (; anIt.More(); anIt.Next()) {
268 const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
269 anIsIn=anEdgeInfo.IsIn();
277 if (aCntIn!=1 || aCntOut!=1) {
278 myNothingToDo=Standard_False;
283 // Each vertex has one edge In and one - Out. Good. But it is not enought
284 // to consider that nothing to do with this. We must check edges on TShape
285 // coinsidence. If there are such edges there is something to do with.
288 Standard_Integer aNbE, aNbMapEE;
289 TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
290 aNbE=myEdges.Extent();
292 anItList.Initialize(myEdges);
293 for (; anItList.More(); anItList.Next()) {
294 const TopoDS_Shape& aE = anItList.Value();
296 if (!aMapEE.Contains(aE)) {
297 TopTools_ListOfShape aLEx;
299 aMapEE.Add(aE, aLEx);
302 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
307 Standard_Boolean bFlag;
309 aNbMapEE=aMapEE.Extent();
310 for (i=1; i<=aNbMapEE; i++) {
311 const TopTools_ListOfShape& aLEx=aMapEE(i);
318 const TopoDS_Shape& aE1=aLEx.First();
319 const TopoDS_Shape& aE2=aLEx.Last();
320 if (aE1.IsSame(aE2)) {
321 bFlag=Standard_False;
326 bFlag=Standard_False;
330 myNothingToDo=myNothingToDo && bFlag;
339 // 3. Angles in mySmartMap
340 BRepAdaptor_Surface aBAS(myFace);
341 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
342 for (i=1; i<=aNb; i++) {
343 const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
344 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
346 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
347 for (; anIt.More(); anIt.Next()) {
348 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
349 const TopoDS_Edge& aE=anEdgeInfo.Edge();
351 TopoDS_Vertex aVV=aV;
353 anIsIn=anEdgeInfo.IsIn();
356 aVV.Orientation(TopAbs_REVERSED);
357 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
362 aVV.Orientation(TopAbs_FORWARD);
363 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
365 anEdgeInfo.SetAngle(anAngle);
372 Standard_Boolean anIsOut, anIsNotPassed;
374 TopTools_SequenceOfShape aLS, aVertVa;
375 TColgp_SequenceOfPnt2d aCoordVa;
377 BOP_ListIteratorOfListOfEdgeInfo anIt;
379 for (i=1; i<=aNb; i++) {
380 const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
381 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
383 anIt.Initialize(aLEInfo);
384 for (; anIt.More(); anIt.Next()) {
385 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
386 const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
388 anIsOut=!anEdgeInfo.IsIn();
389 anIsNotPassed=!anEdgeInfo.Passed();
391 if (anIsOut && anIsNotPassed) {
397 Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS,
398 aVertVa, aCoordVa, myShapes, mySmartMap);
404 Standard_Integer aNbV, aNbE;
405 TopoDS_Vertex aV1, aV2;
406 BOPTColStd_ListOfListOfShape aShapes;
407 BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
409 for (; anItW.More(); anItW.Next()) {
410 TopTools_IndexedMapOfShape aMV, aME;
411 const TopTools_ListOfShape& aLE=anItW.Value();
412 TopTools_ListIteratorOfListOfShape anItE(aLE);
413 for (; anItE.More(); anItE.Next()) {
414 const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
416 TopExp::Vertices(aE, aV1, aV2);
428 anItW.Initialize(aShapes);
429 for (; anItW.More(); anItW.Next()) {
430 const TopTools_ListOfShape& aLE=anItW.Value();
431 myShapes.Append(aLE);
437 //=======================================================================
440 //=======================================================================
441 void Path (const GeomAdaptor_Surface& aGAS,
442 const TopoDS_Face& myFace,
443 const TopoDS_Vertex& aVa,
444 const TopoDS_Edge& aEOuta,
445 BOP_EdgeInfo& anEdgeInfo,
446 TopTools_SequenceOfShape& aLS,
447 TopTools_SequenceOfShape& aVertVa,
448 TColgp_SequenceOfPnt2d& aCoordVa,
449 BOPTColStd_ListOfListOfShape& myShapes,
450 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
452 Standard_Integer i,j, aNb, aNbj, iCnt;
453 Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
454 Standard_Real aTol2D, aTol2D2;
455 Standard_Real aTol2, aD2;
456 Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
457 BOP_ListIteratorOfListOfEdgeInfo anIt;
465 // Do not escape through edge from which you enter
468 const TopoDS_Shape& anEPrev=aLS(aNb);
469 if (anEPrev.IsSame(aEOuta)) {
475 anEdgeInfo.SetPassed(Standard_True);
479 TopoDS_Vertex pVa=aVa;
480 pVa.Orientation(TopAbs_FORWARD);
481 gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
482 aCoordVa.Append(aPa);
484 GetNextVertex (pVa, aEOuta, aVb);
486 gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
488 aTol=2.*Tolerance2D(aVb, aGAS);
494 TopTools_ListOfShape aBuf;
496 for (i=aNb; i>0; i--) {
497 const TopoDS_Shape& aVPrev=aVertVa(i);
498 const gp_Pnt2d& aPaPrev=aCoordVa(i);
499 const TopoDS_Shape& aEPrev=aLS(i);
503 anIsSameV=aVPrev.IsSame(aVb);
504 anIsSameV2d=Standard_False;
507 anIsSameV2d = Standard_True;
509 aD2=aPaPrev.SquareDistance(aPb);
510 anIsSameV2d =aD2<aTol2;
513 if (anIsSameV && anIsSameV2d) {
514 myShapes.Append(aBuf);
516 TopTools_SequenceOfShape aLSt, aVertVat;
517 TColgp_SequenceOfPnt2d aCoordVat;
529 aVb=TopoDS::Vertex(aVertVa(i));
531 for (j=1; j<=aNbj; j++) {
533 aVertVat.Append(aVertVa(j));
534 aCoordVat.Append(aCoordVa(j));
550 aTol2D=2.*Tolerance2D(aVb, aGAS);
551 aTol2D2=100.*aTol2D*aTol2D;
553 // anAngleIn in Vb from edge aEOuta
554 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
556 anAngleIn=AngleIn(aEOuta, aLEInfo);
559 BOP_EdgeInfo *pEdgeInfo=NULL;
562 anIsFound=Standard_False;
564 //modified by NIZNHY-PKV Thu Apr 19 09:05:09 2012f
565 iCnt=NbWaysOut (aEOuta, aLEInfo);
566 //iCnt=NbWaysOut (aLEInfo);
567 //modified by NIZNHY-PKV Thu Apr 19 09:05:12 2012t
568 if (!iCnt) { // no way to go . (Error)
572 anIt.Initialize(aLEInfo);
573 for (; anIt.More(); anIt.Next()) {
574 BOP_EdgeInfo& anEI=anIt.Value();
575 const TopoDS_Edge& aE=anEI.Edge();
576 anIsOut=!anEI.IsIn();
577 anIsNotPassed=!anEI.Passed();
579 if (anIsOut && anIsNotPassed) {
580 if (aE.IsSame(aEOuta)) {
585 // the one and only way to go out .
587 anIsFound=Standard_True;
591 // Look for minimal angle and make the choice.
594 aP2Dx=Coord2dVf(aE, myFace);
596 aD2=aP2Dx.SquareDistance(aPb);
601 anAngleOut=anEI.Angle();
603 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
604 if (anAngle < aMinAngle) {
607 anIsFound=Standard_True;
610 } // for (; anIt.More(); anIt.Next())
613 // no way to go . (Error)
617 aEOutb=pEdgeInfo->Edge();
619 Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
620 aVertVa, aCoordVa, myShapes, mySmartMap);
622 //=======================================================================
623 // function: Coord2dVf
625 //=======================================================================
626 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
627 const TopoDS_Face& aF)
629 Standard_Real aCoord=99.;
630 gp_Pnt2d aP2D1(aCoord, aCoord);
634 for (; aIt.More(); aIt.Next()) {
635 const TopoDS_Shape& aVx=aIt.Value();
636 if (aVx.Orientation()==TopAbs_FORWARD) {
637 const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
638 aP2D1=Coord2d(aVxx, aE, aF);
644 //=======================================================================
645 // function: Tolerance2D
647 //=======================================================================
648 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
649 const GeomAdaptor_Surface& aGAS)
651 Standard_Real aTol2D, anUr, aVr, aTolV3D;
652 GeomAbs_SurfaceType aType;
654 aType=aGAS.GetType();
655 aTolV3D=BRep_Tool::Tolerance(aV);
657 anUr=aGAS.UResolution(aTolV3D);
658 aVr =aGAS.VResolution(aTolV3D);
659 aTol2D=(aVr>anUr) ? aVr : anUr;
661 if (aType==GeomAbs_BSplineSurface||
662 aType==GeomAbs_Sphere||
663 GeomAbs_SurfaceOfRevolution) {
664 if (aTol2D < aTolV3D) {
668 if (aType==GeomAbs_BSplineSurface) {
675 //=======================================================================
678 //=======================================================================
679 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
680 const TopoDS_Edge& aE1,
681 const TopoDS_Face& aF)
683 Standard_Real aT, aFirst, aLast;
684 Handle(Geom2d_Curve) aC2D;
687 aT=BRep_Tool::Parameter (aV1, aE1, aF);
688 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
689 aC2D->D0 (aT, aP2D1);
693 //=======================================================================
696 //=======================================================================
697 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
698 const BOP_ListOfEdgeInfo& aLEInfo)
700 Standard_Real anAngleIn;
701 Standard_Boolean anIsIn;
702 BOP_ListIteratorOfListOfEdgeInfo anIt;
704 anIt.Initialize(aLEInfo);
705 for (; anIt.More(); anIt.Next()) {
706 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
707 const TopoDS_Edge& aE=anEdgeInfo.Edge();
708 anIsIn=anEdgeInfo.IsIn();
710 if (anIsIn && aE==aEIn) {
711 anAngleIn=anEdgeInfo.Angle();
718 //=======================================================================
719 // function: ClockWiseAngle
721 //=======================================================================
722 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
723 const Standard_Real aAngleOut)
725 Standard_Real aTwoPi = M_PI+M_PI;
726 Standard_Real dA, A1, A2, AIn, AOut ;
734 if (AOut >= aTwoPi) {
754 else if (dA <= 1.e-14) {
759 //=======================================================================
760 // function: GetNextVertex
762 //=======================================================================
763 void GetNextVertex(const TopoDS_Vertex& aV,
764 const TopoDS_Edge& aE,
770 for (; aIt.More(); aIt.Next()) {
771 const TopoDS_Shape& aVx=aIt.Value();
772 if (!aVx.IsEqual(aV)) {
773 aV1=TopoDS::Vertex(aVx);
779 //=======================================================================
782 //=======================================================================
783 Standard_Real Angle2D (const TopoDS_Vertex& aV,
784 const TopoDS_Edge& anEdge,
785 const TopoDS_Face& myFace,
786 const GeomAdaptor_Surface& aGAS,
787 const Standard_Boolean aFlag)
789 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
792 Handle(Geom2d_Curve) aC2D;
794 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
795 if (Precision::IsInfinite(aTV)) {
799 BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
800 aFirst, aLast, aToler, Standard_True);
802 dt=2.*Tolerance2D(aV, aGAS);
804 aTX=0.25*(aLast - aFirst);
806 // to save direction of the curve as much as it possible
807 // in the case of big tolerances
811 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
819 aC2D->D0 (aTV1, aPV1);
822 gp_Vec2d aV2DIn(aPV1, aPV);
826 gp_Vec2d aV2DOut(aPV, aPV1);
830 gp_Dir2d aDir2D(aV2D);
831 anAngle=Angle(aDir2D);
835 //=======================================================================
838 //=======================================================================
839 Standard_Real Angle (const gp_Dir2d& aDir2D)
841 gp_Dir2d aRefDir(1., 0.);
842 Standard_Real anAngle = aRefDir.Angle(aDir2D);
845 anAngle += M_PI + M_PI;
849 //modified by NIZNHY-PKV Thu Apr 19 09:02:04 2012f
850 //=======================================================================
851 // function: NbWaysOut
853 //=======================================================================
854 Standard_Integer NbWaysOut(const TopoDS_Edge& aEOuta,
855 const BOP_ListOfEdgeInfo& aLEInfo)
857 Standard_Boolean bIsOut, bIsNotPassed;
858 Standard_Integer iCnt=0;
859 BOP_ListIteratorOfListOfEdgeInfo anIt;
861 anIt.Initialize(aLEInfo);
862 for (; anIt.More(); anIt.Next()) {
863 BOP_EdgeInfo& aEI=anIt.Value();
864 const TopoDS_Edge& aE=aEI.Edge();
866 bIsNotPassed=!aEI.Passed();
867 if (bIsOut && bIsNotPassed) {
868 if (!aE.IsSame(aEOuta)) {
876 //=======================================================================
877 // function: NbWaysOut
879 //=======================================================================
880 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
882 Standard_Boolean bIsOut, bIsNotPassed;
883 Standard_Integer iCnt=0;
884 BOP_ListIteratorOfListOfEdgeInfo anIt;
886 anIt.Initialize(aLEInfo);
887 for (; anIt.More(); anIt.Next()) {
888 BOP_EdgeInfo& anEI=anIt.Value();
891 bIsNotPassed=!anEI.Passed();
892 if (bIsOut && bIsNotPassed) {
899 //modified by NIZNHY-PKV Thu Apr 19 09:01:57 2012t