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.ixx>
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>
46 #include <BRep_Tool.hxx>
47 #include <BRepAdaptor_Surface.hxx>
48 #include <BRepAdaptor_Curve2d.hxx>
51 #include <TopExp_Explorer.hxx>
53 #include <TopTools_SequenceOfShape.hxx>
54 #include <TopTools_ListOfShape.hxx>
55 #include <TopTools_ListIteratorOfListOfShape.hxx>
56 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
57 #include <TopTools_IndexedMapOfShape.hxx>
59 #include <BOPTColStd_ListOfListOfShape.hxx>
60 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
62 #include <BOPTools_Tools2D.hxx>
64 #include <BOP_EdgeInfo.hxx>
65 #include <BOP_ListOfEdgeInfo.hxx>
66 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
67 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
70 void Path (const GeomAdaptor_Surface& aGAS,
71 const TopoDS_Face& myFace,
72 const TopoDS_Vertex& aVa,
73 const TopoDS_Edge& aEOuta,
74 BOP_EdgeInfo& anEdgeInfo,
75 TopTools_SequenceOfShape& aLS,
76 TopTools_SequenceOfShape& aVertVa,
77 TColgp_SequenceOfPnt2d& aCoordVa,
78 BOPTColStd_ListOfListOfShape& myShapes,
79 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
83 Standard_Real Angle (const gp_Dir2d& aDir2D);
87 void GetNextVertex(const TopoDS_Vertex& aV,
88 const TopoDS_Edge& aE,
91 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
92 const Standard_Real aAngleOut);
95 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
96 const BOP_ListOfEdgeInfo& aLEInfo);
99 Standard_Real Angle2D (const TopoDS_Vertex& aV,
100 const TopoDS_Edge& anEdge,
101 const TopoDS_Face& myFace,
102 const GeomAdaptor_Surface& aGAS,
103 const Standard_Boolean aFlag);
105 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
106 const TopoDS_Edge& aE1,
107 const TopoDS_Face& aF);
109 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
110 const TopoDS_Face& aF);
112 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
113 const GeomAdaptor_Surface& aGAS);
116 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
119 //=======================================================================
122 //=======================================================================
123 GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
126 myNothingToDo(Standard_False)
129 //=======================================================================
132 //=======================================================================
133 GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
136 //=======================================================================
139 //=======================================================================
140 void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
144 //=======================================================================
147 //=======================================================================
148 const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
152 //=======================================================================
153 // function: SetEdges
155 //=======================================================================
156 void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
158 TopTools_ListIteratorOfListOfShape anIt;
161 anIt.Initialize(aLE);
162 for (; anIt.More(); anIt.Next()) {
163 const TopoDS_Shape& aE =anIt.Value();
165 if (aE.Orientation()==TopAbs_INTERNAL){
172 //=======================================================================
175 //=======================================================================
176 const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
180 //=======================================================================
181 // function: IsNothingToDo
183 //=======================================================================
184 Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
186 return myNothingToDo;
188 //=======================================================================
191 //=======================================================================
192 const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
196 //=======================================================================
199 //=======================================================================
200 void GEOMAlgo_WireSplitter::Perform()
203 myNothingToDo=Standard_True;
205 Standard_Integer index, i, aNb, aCntIn, aCntOut;
206 Standard_Boolean anIsIn;
207 Standard_Real anAngle;
209 BOP_ListOfEdgeInfo emptyInfo;
210 TopTools_ListIteratorOfListOfShape anItList;
212 // 1.Filling mySmartMap
215 anItList.Initialize(myEdges);
216 for (; anItList.More(); anItList.Next()) {
217 const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
219 if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
223 TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
224 for (; anExpVerts.More(); anExpVerts.Next()) {
225 const TopoDS_Shape& aVertex= anExpVerts.Current();
227 index = mySmartMap.FindIndex(aVertex);
229 index=mySmartMap.Add(aVertex, emptyInfo);
232 BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
235 aEInfo.SetEdge(anEdge);
237 TopAbs_Orientation anOr=aVertex.Orientation();
239 if (anOr==TopAbs_FORWARD) {
240 aEInfo.SetInFlag(Standard_False);
243 else if (anOr==TopAbs_REVERSED) {
244 aEInfo.SetInFlag(Standard_True);
247 aListOfEInfo.Append(aEInfo);
251 aNb=mySmartMap.Extent();
254 myNothingToDo=Standard_True;
256 for (i=1; i<=aNb; i++) {
259 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
260 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
261 for (; anIt.More(); anIt.Next()) {
262 const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
263 anIsIn=anEdgeInfo.IsIn();
271 if (aCntIn!=1 || aCntOut!=1) {
272 myNothingToDo=Standard_False;
277 // Each vertex has one edge In and one - Out. Good. But it is not enought
278 // to consider that nothing to do with this. We must check edges on TShape
279 // coinsidence. If there are such edges there is something to do with.
282 Standard_Integer aNbE, aNbMapEE;
283 TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
284 aNbE=myEdges.Extent();
286 anItList.Initialize(myEdges);
287 for (; anItList.More(); anItList.Next()) {
288 const TopoDS_Shape& aE = anItList.Value();
290 if (!aMapEE.Contains(aE)) {
291 TopTools_ListOfShape aLEx;
293 aMapEE.Add(aE, aLEx);
296 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
301 Standard_Boolean bFlag;
303 aNbMapEE=aMapEE.Extent();
304 for (i=1; i<=aNbMapEE; i++) {
305 const TopTools_ListOfShape& aLEx=aMapEE(i);
312 const TopoDS_Shape& aE1=aLEx.First();
313 const TopoDS_Shape& aE2=aLEx.Last();
314 if (aE1.IsSame(aE2)) {
315 bFlag=Standard_False;
320 bFlag=Standard_False;
324 myNothingToDo=myNothingToDo && bFlag;
333 // 3. Angles in mySmartMap
334 BRepAdaptor_Surface aBAS(myFace);
335 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
336 for (i=1; i<=aNb; i++) {
337 const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
338 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
340 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
341 for (; anIt.More(); anIt.Next()) {
342 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
343 const TopoDS_Edge& aE=anEdgeInfo.Edge();
345 TopoDS_Vertex aVV=aV;
347 anIsIn=anEdgeInfo.IsIn();
350 aVV.Orientation(TopAbs_REVERSED);
351 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
356 aVV.Orientation(TopAbs_FORWARD);
357 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
359 anEdgeInfo.SetAngle(anAngle);
366 Standard_Boolean anIsOut, anIsNotPassed;
368 TopTools_SequenceOfShape aLS, aVertVa;
369 TColgp_SequenceOfPnt2d aCoordVa;
371 BOP_ListIteratorOfListOfEdgeInfo anIt;
373 for (i=1; i<=aNb; i++) {
374 const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
375 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
377 anIt.Initialize(aLEInfo);
378 for (; anIt.More(); anIt.Next()) {
379 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
380 const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
382 anIsOut=!anEdgeInfo.IsIn();
383 anIsNotPassed=!anEdgeInfo.Passed();
385 if (anIsOut && anIsNotPassed) {
391 Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS,
392 aVertVa, aCoordVa, myShapes, mySmartMap);
398 Standard_Integer aNbV, aNbE;
399 TopoDS_Vertex aV1, aV2;
400 BOPTColStd_ListOfListOfShape aShapes;
401 BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
403 for (; anItW.More(); anItW.Next()) {
404 TopTools_IndexedMapOfShape aMV, aME;
405 const TopTools_ListOfShape& aLE=anItW.Value();
406 TopTools_ListIteratorOfListOfShape anItE(aLE);
407 for (; anItE.More(); anItE.Next()) {
408 const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
410 TopExp::Vertices(aE, aV1, aV2);
422 anItW.Initialize(aShapes);
423 for (; anItW.More(); anItW.Next()) {
424 const TopTools_ListOfShape& aLE=anItW.Value();
425 myShapes.Append(aLE);
431 //=======================================================================
434 //=======================================================================
435 void Path (const GeomAdaptor_Surface& aGAS,
436 const TopoDS_Face& myFace,
437 const TopoDS_Vertex& aVa,
438 const TopoDS_Edge& aEOuta,
439 BOP_EdgeInfo& anEdgeInfo,
440 TopTools_SequenceOfShape& aLS,
441 TopTools_SequenceOfShape& aVertVa,
442 TColgp_SequenceOfPnt2d& aCoordVa,
443 BOPTColStd_ListOfListOfShape& myShapes,
444 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
446 Standard_Integer i,j, aNb, aNbj;
447 Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
448 Standard_Real aTol2D, aTol2D2;
449 Standard_Real aTol2, aD2;//, aTolUVb, aTolVVb;
450 Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
451 BOP_ListIteratorOfListOfEdgeInfo anIt;
459 // Do not escape through edge from which you enter
462 const TopoDS_Shape& anEPrev=aLS(aNb);
463 if (anEPrev.IsSame(aEOuta)) {
469 anEdgeInfo.SetPassed(Standard_True);
473 TopoDS_Vertex pVa=aVa;
474 pVa.Orientation(TopAbs_FORWARD);
475 gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
476 aCoordVa.Append(aPa);
478 GetNextVertex (pVa, aEOuta, aVb);
480 gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
482 //const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb);
484 aTol=2.*Tolerance2D(aVb, aGAS);
490 TopTools_ListOfShape aBuf;
492 for (i=aNb; i>0; i--) {
493 const TopoDS_Shape& aVPrev=aVertVa(i);
494 const gp_Pnt2d& aPaPrev=aCoordVa(i);
495 const TopoDS_Shape& aEPrev=aLS(i);
499 anIsSameV=aVPrev.IsSame(aVb);
500 anIsSameV2d=Standard_False;
503 anIsSameV2d = Standard_True;
505 aD2=aPaPrev.SquareDistance(aPb);
506 anIsSameV2d =aD2<aTol2;
509 if (anIsSameV && anIsSameV2d) {
510 myShapes.Append(aBuf);
512 TopTools_SequenceOfShape aLSt, aVertVat;
513 TColgp_SequenceOfPnt2d aCoordVat;
525 aVb=TopoDS::Vertex(aVertVa(i));
527 for (j=1; j<=aNbj; j++) {
529 aVertVat.Append(aVertVa(j));
530 aCoordVat.Append(aCoordVa(j));
546 aTol2D=2.*Tolerance2D(aVb, aGAS);
547 aTol2D2=100.*aTol2D*aTol2D;
549 // anAngleIn in Vb from edge aEOuta
550 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
552 anAngleIn=AngleIn(aEOuta, aLEInfo);
555 BOP_EdgeInfo *pEdgeInfo=NULL;
558 anIsFound=Standard_False;
560 Standard_Integer aCurIndexE = 0;
562 anIt.Initialize(aLEInfo);
563 for (; anIt.More(); anIt.Next()) {
564 BOP_EdgeInfo& anEI=anIt.Value();
565 const TopoDS_Edge& aE=anEI.Edge();
566 anIsOut=!anEI.IsIn();
567 anIsNotPassed=!anEI.Passed();
569 if (anIsOut && anIsNotPassed) {
572 // Is there one way to go out of the vertex
573 // we have to use it only.
574 Standard_Integer iCnt;
575 iCnt=NbWaysOut (aLEInfo);
578 // no way to go . (Error)
583 // the one and only way to go out .
585 anIsFound=Standard_True;
589 // Look for minimal angle and make the choice.
592 aP2Dx=Coord2dVf(aE, myFace);
594 aD2=aP2Dx.SquareDistance(aPb);
600 anAngleOut=anEI.Angle();
602 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
603 if (anAngle < aMinAngle) {
606 anIsFound=Standard_True;
609 } // for (; anIt.More(); anIt.Next())
612 // no way to go . (Error)
616 aEOutb=pEdgeInfo->Edge();
618 Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
619 aVertVa, aCoordVa, myShapes, mySmartMap);
621 //=======================================================================
622 // function: Coord2dVf
624 //=======================================================================
625 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
626 const TopoDS_Face& aF)
628 Standard_Real aCoord=99.;
629 gp_Pnt2d aP2D1(aCoord, aCoord);
633 for (; aIt.More(); aIt.Next()) {
634 const TopoDS_Shape& aVx=aIt.Value();
635 if (aVx.Orientation()==TopAbs_FORWARD) {
636 const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
637 aP2D1=Coord2d(aVxx, aE, aF);
643 //=======================================================================
644 // function: Tolerance2D
646 //=======================================================================
647 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
648 const GeomAdaptor_Surface& aGAS)
650 Standard_Real aTol2D, anUr, aVr, aTolV3D;
651 GeomAbs_SurfaceType aType;
653 aType=aGAS.GetType();
654 aTolV3D=BRep_Tool::Tolerance(aV);
656 anUr=aGAS.UResolution(aTolV3D);
657 aVr =aGAS.VResolution(aTolV3D);
658 aTol2D=(aVr>anUr) ? aVr : anUr;
660 if (aType==GeomAbs_BSplineSurface||
661 aType==GeomAbs_Sphere||
662 GeomAbs_SurfaceOfRevolution) {
663 if (aTol2D < aTolV3D) {
667 if (aType==GeomAbs_BSplineSurface) {
674 //=======================================================================
677 //=======================================================================
678 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
679 const TopoDS_Edge& aE1,
680 const TopoDS_Face& aF)
682 Standard_Real aT, aFirst, aLast;
683 Handle(Geom2d_Curve) aC2D;
686 aT=BRep_Tool::Parameter (aV1, aE1, aF);
687 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
688 aC2D->D0 (aT, aP2D1);
692 //=======================================================================
695 //=======================================================================
696 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
697 const BOP_ListOfEdgeInfo& aLEInfo)
699 Standard_Real anAngleIn;
700 Standard_Boolean anIsIn;
701 BOP_ListIteratorOfListOfEdgeInfo anIt;
703 anIt.Initialize(aLEInfo);
704 for (; anIt.More(); anIt.Next()) {
705 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
706 const TopoDS_Edge& aE=anEdgeInfo.Edge();
707 anIsIn=anEdgeInfo.IsIn();
709 if (anIsIn && aE==aEIn) {
710 anAngleIn=anEdgeInfo.Angle();
717 //=======================================================================
718 // function: ClockWiseAngle
720 //=======================================================================
721 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
722 const Standard_Real aAngleOut)
724 Standard_Real aTwoPi = M_PI+M_PI;
725 Standard_Real dA, A1, A2, AIn, AOut ;
733 if (AOut >= aTwoPi) {
748 //modified by NIZNHY-PKV Thu Feb 17 08:26:39 2011f
752 //modified by NIZNHY-PKV Thu Feb 17 08:26:42 2011t
755 else if (dA <= 1.e-14) {
760 //=======================================================================
761 // function: GetNextVertex
763 //=======================================================================
764 void GetNextVertex(const TopoDS_Vertex& aV,
765 const TopoDS_Edge& aE,
771 for (; aIt.More(); aIt.Next()) {
772 const TopoDS_Shape& aVx=aIt.Value();
773 if (!aVx.IsEqual(aV)) {
774 aV1=TopoDS::Vertex(aVx);
780 //=======================================================================
783 //=======================================================================
784 Standard_Real Angle2D (const TopoDS_Vertex& aV,
785 const TopoDS_Edge& anEdge,
786 const TopoDS_Face& myFace,
787 const GeomAdaptor_Surface& aGAS,
788 const Standard_Boolean aFlag)
790 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
793 Handle(Geom2d_Curve) aC2D;
795 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
796 if (Precision::IsInfinite(aTV)) {
800 BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
801 aFirst, aLast, aToler, Standard_True);
803 dt=2.*Tolerance2D(aV, aGAS);
805 aTX=0.25*(aLast - aFirst);
807 // to save direction of the curve as much as it possible
808 // in the case of big tolerances
812 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
820 aC2D->D0 (aTV1, aPV1);
823 gp_Vec2d aV2DIn(aPV1, aPV);
827 gp_Vec2d aV2DOut(aPV, aPV1);
831 gp_Dir2d aDir2D(aV2D);
832 anAngle=Angle(aDir2D);
836 //=======================================================================
839 //=======================================================================
840 Standard_Real Angle (const gp_Dir2d& aDir2D)
842 gp_Dir2d aRefDir(1., 0.);
843 Standard_Real anAngle = aRefDir.Angle(aDir2D);
846 anAngle += M_PI + M_PI;
851 //=======================================================================
852 // function: NbWaysOut
854 //=======================================================================
855 Standard_Integer NbWaysOut(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& anEI=anIt.Value();
866 bIsNotPassed=!anEI.Passed();
867 if (bIsOut && bIsNotPassed) {