1 // Copyright (C) 2007-2011 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
22 // File: GEOMAlgo_WireSplitter.cxx
23 // Author: Peter KURNEV
25 #include <GEOMAlgo_WireSplitter.hxx>
27 #include <TColStd_SequenceOfReal.hxx>
28 #include <Precision.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Vec2d.hxx>
32 #include <TColgp_SequenceOfPnt2d.hxx>
34 #include <Geom_Curve.hxx>
35 #include <Geom2d_Curve.hxx>
36 #include <GeomAdaptor_Surface.hxx>
38 #include <TopAbs_Orientation.hxx>
41 #include <TopoDS_Vertex.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Face.hxx>
44 #include <TopoDS_Iterator.hxx>
47 #include <BRep_Tool.hxx>
48 #include <BRepAdaptor_Surface.hxx>
49 #include <BRepAdaptor_Curve2d.hxx>
52 #include <TopExp_Explorer.hxx>
56 #include <TopTools_SequenceOfShape.hxx>
57 #include <TopTools_ListOfShape.hxx>
58 #include <TopTools_ListIteratorOfListOfShape.hxx>
59 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
60 #include <TopTools_IndexedMapOfShape.hxx>
62 #include <BOPTColStd_ListOfListOfShape.hxx>
63 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
65 #include <BOPTools_Tools2D.hxx>
67 #include <BOP_EdgeInfo.hxx>
68 #include <BOP_ListOfEdgeInfo.hxx>
69 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
70 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
73 void Path (const GeomAdaptor_Surface& aGAS,
74 const TopoDS_Face& myFace,
75 const TopoDS_Vertex& aVa,
76 const TopoDS_Edge& aEOuta,
77 BOP_EdgeInfo& anEdgeInfo,
78 TopTools_SequenceOfShape& aLS,
79 TopTools_SequenceOfShape& aVertVa,
80 TColgp_SequenceOfPnt2d& aCoordVa,
81 BOPTColStd_ListOfListOfShape& myShapes,
82 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
86 Standard_Real Angle (const gp_Dir2d& aDir2D);
90 void GetNextVertex(const TopoDS_Vertex& aV,
91 const TopoDS_Edge& aE,
94 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
95 const Standard_Real aAngleOut);
98 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
99 const BOP_ListOfEdgeInfo& aLEInfo);
102 Standard_Real Angle2D (const TopoDS_Vertex& aV,
103 const TopoDS_Edge& anEdge,
104 const TopoDS_Face& myFace,
105 const GeomAdaptor_Surface& aGAS,
106 const Standard_Boolean aFlag);
108 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
109 const TopoDS_Edge& aE1,
110 const TopoDS_Face& aF);
112 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
113 const TopoDS_Face& aF);
115 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
116 const GeomAdaptor_Surface& aGAS);
119 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
122 //=======================================================================
125 //=======================================================================
126 GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
129 myNothingToDo(Standard_False)
132 //=======================================================================
135 //=======================================================================
136 GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
139 //=======================================================================
142 //=======================================================================
143 void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
147 //=======================================================================
150 //=======================================================================
151 const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
155 //=======================================================================
156 // function: SetEdges
158 //=======================================================================
159 void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
161 TopTools_ListIteratorOfListOfShape anIt;
164 anIt.Initialize(aLE);
165 for (; anIt.More(); anIt.Next()) {
166 const TopoDS_Shape& aE =anIt.Value();
168 if (aE.Orientation()==TopAbs_INTERNAL){
175 //=======================================================================
178 //=======================================================================
179 const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
183 //=======================================================================
184 // function: IsNothingToDo
186 //=======================================================================
187 Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
189 return myNothingToDo;
191 //=======================================================================
194 //=======================================================================
195 const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
199 //=======================================================================
202 //=======================================================================
203 void GEOMAlgo_WireSplitter::Perform()
206 myNothingToDo=Standard_True;
208 Standard_Integer index, i, aNb, aCntIn, aCntOut;
209 Standard_Boolean anIsIn;
210 Standard_Real anAngle;
212 BOP_ListOfEdgeInfo emptyInfo;
213 TopTools_ListIteratorOfListOfShape anItList;
215 // 1.Filling mySmartMap
218 anItList.Initialize(myEdges);
219 for (; anItList.More(); anItList.Next()) {
220 const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
222 if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
226 TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
227 for (; anExpVerts.More(); anExpVerts.Next()) {
228 const TopoDS_Shape& aVertex= anExpVerts.Current();
230 index = mySmartMap.FindIndex(aVertex);
232 index=mySmartMap.Add(aVertex, emptyInfo);
235 BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
238 aEInfo.SetEdge(anEdge);
240 TopAbs_Orientation anOr=aVertex.Orientation();
242 if (anOr==TopAbs_FORWARD) {
243 aEInfo.SetInFlag(Standard_False);
246 else if (anOr==TopAbs_REVERSED) {
247 aEInfo.SetInFlag(Standard_True);
250 aListOfEInfo.Append(aEInfo);
254 aNb=mySmartMap.Extent();
257 myNothingToDo=Standard_True;
259 for (i=1; i<=aNb; i++) {
262 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
263 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
264 for (; anIt.More(); anIt.Next()) {
265 const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
266 anIsIn=anEdgeInfo.IsIn();
274 if (aCntIn!=1 || aCntOut!=1) {
275 myNothingToDo=Standard_False;
280 // Each vertex has one edge In and one - Out. Good. But it is not enought
281 // to consider that nothing to do with this. We must check edges on TShape
282 // coinsidence. If there are such edges there is something to do with.
285 Standard_Integer aNbE, aNbMapEE;
286 TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
287 aNbE=myEdges.Extent();
289 anItList.Initialize(myEdges);
290 for (; anItList.More(); anItList.Next()) {
291 const TopoDS_Shape& aE = anItList.Value();
293 if (!aMapEE.Contains(aE)) {
294 TopTools_ListOfShape aLEx;
296 aMapEE.Add(aE, aLEx);
299 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
304 Standard_Boolean bFlag;
306 aNbMapEE=aMapEE.Extent();
307 for (i=1; i<=aNbMapEE; i++) {
308 const TopTools_ListOfShape& aLEx=aMapEE(i);
315 const TopoDS_Shape& aE1=aLEx.First();
316 const TopoDS_Shape& aE2=aLEx.Last();
317 if (aE1.IsSame(aE2)) {
318 bFlag=Standard_False;
323 bFlag=Standard_False;
327 myNothingToDo=myNothingToDo && bFlag;
336 // 3. Angles in mySmartMap
337 BRepAdaptor_Surface aBAS(myFace);
338 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
339 for (i=1; i<=aNb; i++) {
340 const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
341 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
343 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
344 for (; anIt.More(); anIt.Next()) {
345 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
346 const TopoDS_Edge& aE=anEdgeInfo.Edge();
348 TopoDS_Vertex aVV=aV;
350 anIsIn=anEdgeInfo.IsIn();
353 aVV.Orientation(TopAbs_REVERSED);
354 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
359 aVV.Orientation(TopAbs_FORWARD);
360 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
362 anEdgeInfo.SetAngle(anAngle);
369 Standard_Boolean anIsOut, anIsNotPassed;
371 TopTools_SequenceOfShape aLS, aVertVa;
372 TColgp_SequenceOfPnt2d aCoordVa;
374 BOP_ListIteratorOfListOfEdgeInfo anIt;
376 for (i=1; i<=aNb; i++) {
377 const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
378 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
380 anIt.Initialize(aLEInfo);
381 for (; anIt.More(); anIt.Next()) {
382 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
383 const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
385 anIsOut=!anEdgeInfo.IsIn();
386 anIsNotPassed=!anEdgeInfo.Passed();
388 if (anIsOut && anIsNotPassed) {
394 Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS,
395 aVertVa, aCoordVa, myShapes, mySmartMap);
401 Standard_Integer aNbV, aNbE;
402 TopoDS_Vertex aV1, aV2;
403 BOPTColStd_ListOfListOfShape aShapes;
404 BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
406 for (; anItW.More(); anItW.Next()) {
407 TopTools_IndexedMapOfShape aMV, aME;
408 const TopTools_ListOfShape& aLE=anItW.Value();
409 TopTools_ListIteratorOfListOfShape anItE(aLE);
410 for (; anItE.More(); anItE.Next()) {
411 const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
413 TopExp::Vertices(aE, aV1, aV2);
425 anItW.Initialize(aShapes);
426 for (; anItW.More(); anItW.Next()) {
427 const TopTools_ListOfShape& aLE=anItW.Value();
428 myShapes.Append(aLE);
434 //=======================================================================
437 //=======================================================================
438 void Path (const GeomAdaptor_Surface& aGAS,
439 const TopoDS_Face& myFace,
440 const TopoDS_Vertex& aVa,
441 const TopoDS_Edge& aEOuta,
442 BOP_EdgeInfo& anEdgeInfo,
443 TopTools_SequenceOfShape& aLS,
444 TopTools_SequenceOfShape& aVertVa,
445 TColgp_SequenceOfPnt2d& aCoordVa,
446 BOPTColStd_ListOfListOfShape& myShapes,
447 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
450 Standard_Integer i,j, aNb, aNbj;
451 Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
452 Standard_Real aTol2D, aTol2D2;
453 Standard_Real aTol2, aD2;//, aTolUVb, aTolVVb;
454 Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
455 BOP_ListIteratorOfListOfEdgeInfo anIt;
463 // Do not escape through edge from which you enter
466 const TopoDS_Shape& anEPrev=aLS(aNb);
467 if (anEPrev.IsSame(aEOuta)) {
473 anEdgeInfo.SetPassed(Standard_True);
477 TopoDS_Vertex pVa=aVa;
478 pVa.Orientation(TopAbs_FORWARD);
479 gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
480 aCoordVa.Append(aPa);
482 GetNextVertex (pVa, aEOuta, aVb);
484 gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
486 //const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb);
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 Standard_Integer aCurIndexE = 0;
566 anIt.Initialize(aLEInfo);
567 for (; anIt.More(); anIt.Next()) {
568 BOP_EdgeInfo& anEI=anIt.Value();
569 const TopoDS_Edge& aE=anEI.Edge();
570 anIsOut=!anEI.IsIn();
571 anIsNotPassed=!anEI.Passed();
573 if (anIsOut && anIsNotPassed) {
576 // Is there one way to go out of the vertex
577 // we have to use it only.
578 Standard_Integer iCnt;
579 iCnt=NbWaysOut (aLEInfo);
582 // no way to go . (Error)
587 // the one and only way to go out .
589 anIsFound=Standard_True;
593 // Look for minimal angle and make the choice.
596 aP2Dx=Coord2dVf(aE, myFace);
598 aD2=aP2Dx.SquareDistance(aPb);
604 anAngleOut=anEI.Angle();
606 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
607 if (anAngle < aMinAngle) {
610 anIsFound=Standard_True;
613 } // for (; anIt.More(); anIt.Next())
616 // no way to go . (Error)
620 aEOutb=pEdgeInfo->Edge();
622 Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
623 aVertVa, aCoordVa, myShapes, mySmartMap);
625 //=======================================================================
626 // function: Coord2dVf
628 //=======================================================================
629 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
630 const TopoDS_Face& aF)
632 Standard_Real aCoord=99.;
633 gp_Pnt2d aP2D1(aCoord, aCoord);
637 for (; aIt.More(); aIt.Next()) {
638 const TopoDS_Shape& aVx=aIt.Value();
639 if (aVx.Orientation()==TopAbs_FORWARD) {
640 const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
641 aP2D1=Coord2d(aVxx, aE, aF);
647 //=======================================================================
648 // function: Tolerance2D
650 //=======================================================================
651 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
652 const GeomAdaptor_Surface& aGAS)
654 Standard_Real aTol2D, anUr, aVr, aTolV3D;
655 GeomAbs_SurfaceType aType;
657 aType=aGAS.GetType();
658 aTolV3D=BRep_Tool::Tolerance(aV);
660 anUr=aGAS.UResolution(aTolV3D);
661 aVr =aGAS.VResolution(aTolV3D);
662 aTol2D=(aVr>anUr) ? aVr : anUr;
664 if (aType==GeomAbs_BSplineSurface||
665 aType==GeomAbs_Sphere||
666 GeomAbs_SurfaceOfRevolution) {
667 if (aTol2D < aTolV3D) {
671 if (aType==GeomAbs_BSplineSurface) {
678 //=======================================================================
681 //=======================================================================
682 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
683 const TopoDS_Edge& aE1,
684 const TopoDS_Face& aF)
686 Standard_Real aT, aFirst, aLast;
687 Handle(Geom2d_Curve) aC2D;
690 aT=BRep_Tool::Parameter (aV1, aE1, aF);
691 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
692 aC2D->D0 (aT, aP2D1);
696 //=======================================================================
699 //=======================================================================
700 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
701 const BOP_ListOfEdgeInfo& aLEInfo)
703 Standard_Real anAngleIn;
704 Standard_Boolean anIsIn;
705 BOP_ListIteratorOfListOfEdgeInfo anIt;
707 anIt.Initialize(aLEInfo);
708 for (; anIt.More(); anIt.Next()) {
709 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
710 const TopoDS_Edge& aE=anEdgeInfo.Edge();
711 anIsIn=anEdgeInfo.IsIn();
713 if (anIsIn && aE==aEIn) {
714 anAngleIn=anEdgeInfo.Angle();
721 //=======================================================================
722 // function: ClockWiseAngle
724 //=======================================================================
725 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
726 const Standard_Real aAngleOut)
728 Standard_Real aTwoPi = M_PI+M_PI;
729 Standard_Real dA, A1, A2, AIn, AOut ;
737 if (AOut >= aTwoPi) {
752 //modified by NIZNHY-PKV Thu Feb 17 08:26:39 2011f
756 //modified by NIZNHY-PKV Thu Feb 17 08:26:42 2011t
759 else if (dA <= 1.e-14) {
764 //=======================================================================
765 // function: GetNextVertex
767 //=======================================================================
768 void GetNextVertex(const TopoDS_Vertex& aV,
769 const TopoDS_Edge& aE,
775 for (; aIt.More(); aIt.Next()) {
776 const TopoDS_Shape& aVx=aIt.Value();
777 if (!aVx.IsEqual(aV)) {
778 aV1=TopoDS::Vertex(aVx);
784 //=======================================================================
787 //=======================================================================
788 Standard_Real Angle2D (const TopoDS_Vertex& aV,
789 const TopoDS_Edge& anEdge,
790 const TopoDS_Face& myFace,
791 const GeomAdaptor_Surface& aGAS,
792 const Standard_Boolean aFlag)
794 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
797 Handle(Geom2d_Curve) aC2D;
799 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
800 if (Precision::IsInfinite(aTV)) {
804 BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
805 aFirst, aLast, aToler, Standard_True);
807 dt=2.*Tolerance2D(aV, aGAS);
809 aTX=0.25*(aLast - aFirst);
811 // to save direction of the curve as much as it possible
812 // in the case of big tolerances
816 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
824 aC2D->D0 (aTV1, aPV1);
827 gp_Vec2d aV2DIn(aPV1, aPV);
831 gp_Vec2d aV2DOut(aPV, aPV1);
835 gp_Dir2d aDir2D(aV2D);
836 anAngle=Angle(aDir2D);
840 //=======================================================================
843 //=======================================================================
844 Standard_Real Angle (const gp_Dir2d& aDir2D)
846 gp_Dir2d aRefDir(1., 0.);
847 Standard_Real anAngle = aRefDir.Angle(aDir2D);
850 anAngle += M_PI + M_PI;
855 //=======================================================================
856 // function: NbWaysOut
858 //=======================================================================
859 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
861 Standard_Boolean bIsOut, bIsNotPassed;
862 Standard_Integer iCnt=0;
863 BOP_ListIteratorOfListOfEdgeInfo anIt;
865 anIt.Initialize(aLEInfo);
866 for (; anIt.More(); anIt.Next()) {
867 BOP_EdgeInfo& anEI=anIt.Value();
870 bIsNotPassed=!anEI.Passed();
871 if (bIsOut && bIsNotPassed) {