1 // Copyright (C) 2007-2008 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
24 // Author: Peter KURNEV
27 #include <GEOMAlgo_WireSplitter.ixx>
29 #include <TColStd_SequenceOfReal.hxx>
30 #include <Precision.hxx>
32 #include <gp_Pnt2d.hxx>
33 #include <gp_Vec2d.hxx>
34 #include <TColgp_SequenceOfPnt2d.hxx>
36 #include <Geom_Curve.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <GeomAdaptor_Surface.hxx>
40 #include <TopAbs_Orientation.hxx>
43 #include <TopoDS_Vertex.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Face.hxx>
46 #include <TopoDS_Iterator.hxx>
49 #include <BRep_Tool.hxx>
50 #include <BRepAdaptor_Surface.hxx>
51 #include <BRepAdaptor_Curve2d.hxx>
54 #include <TopExp_Explorer.hxx>
58 #include <TopTools_SequenceOfShape.hxx>
59 #include <TopTools_ListOfShape.hxx>
60 #include <TopTools_ListIteratorOfListOfShape.hxx>
61 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
62 #include <TopTools_IndexedMapOfShape.hxx>
64 #include <BOPTColStd_ListOfListOfShape.hxx>
65 #include <BOPTColStd_ListIteratorOfListOfListOfShape.hxx>
67 #include <BOPTools_Tools2D.hxx>
69 #include <BOP_EdgeInfo.hxx>
70 #include <BOP_ListOfEdgeInfo.hxx>
71 #include <BOP_ListIteratorOfListOfEdgeInfo.hxx>
72 #include <BOP_IndexedDataMapOfVertexListEdgeInfo.hxx>
75 void Path (const GeomAdaptor_Surface& aGAS,
76 const TopoDS_Face& myFace,
77 const TopoDS_Vertex& aVa,
78 const TopoDS_Edge& aEOuta,
79 BOP_EdgeInfo& anEdgeInfo,
80 TopTools_SequenceOfShape& aLS,
81 TopTools_SequenceOfShape& aVertVa,
82 TColgp_SequenceOfPnt2d& aCoordVa,
83 BOPTColStd_ListOfListOfShape& myShapes,
84 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap);
88 Standard_Real Angle (const gp_Dir2d& aDir2D);
92 void GetNextVertex(const TopoDS_Vertex& aV,
93 const TopoDS_Edge& aE,
96 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
97 const Standard_Real aAngleOut);
100 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
101 const BOP_ListOfEdgeInfo& aLEInfo);
104 Standard_Real Angle2D (const TopoDS_Vertex& aV,
105 const TopoDS_Edge& anEdge,
106 const TopoDS_Face& myFace,
107 const GeomAdaptor_Surface& aGAS,
108 const Standard_Boolean aFlag);
110 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
111 const TopoDS_Edge& aE1,
112 const TopoDS_Face& aF);
114 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
115 const TopoDS_Face& aF);
117 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
118 const GeomAdaptor_Surface& aGAS);
121 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& );
124 //=======================================================================
127 //=======================================================================
128 GEOMAlgo_WireSplitter::GEOMAlgo_WireSplitter()
131 myNothingToDo(Standard_False)
134 //=======================================================================
137 //=======================================================================
138 GEOMAlgo_WireSplitter::~GEOMAlgo_WireSplitter()
141 //=======================================================================
144 //=======================================================================
145 void GEOMAlgo_WireSplitter::SetFace(const TopoDS_Face& aFace)
149 //=======================================================================
152 //=======================================================================
153 const TopoDS_Face& GEOMAlgo_WireSplitter::Face()const
157 //=======================================================================
158 // function: SetEdges
160 //=======================================================================
161 void GEOMAlgo_WireSplitter::SetEdges(const TopTools_ListOfShape& aLE)
163 TopTools_ListIteratorOfListOfShape anIt;
166 anIt.Initialize(aLE);
167 for (; anIt.More(); anIt.Next()) {
168 const TopoDS_Shape& aE =anIt.Value();
170 if (aE.Orientation()==TopAbs_INTERNAL){
177 //=======================================================================
180 //=======================================================================
181 const TopTools_ListOfShape& GEOMAlgo_WireSplitter::Edges()const
185 //=======================================================================
186 // function: IsNothingToDo
188 //=======================================================================
189 Standard_Boolean GEOMAlgo_WireSplitter::IsNothingToDo()const
191 return myNothingToDo;
193 //=======================================================================
196 //=======================================================================
197 const BOPTColStd_ListOfListOfShape& GEOMAlgo_WireSplitter::Shapes()const
201 //=======================================================================
204 //=======================================================================
205 void GEOMAlgo_WireSplitter::Perform()
208 myNothingToDo=Standard_True;
210 Standard_Integer index, i, aNb, aCntIn, aCntOut;
211 Standard_Boolean anIsIn;
212 Standard_Real anAngle;
214 BOP_ListOfEdgeInfo emptyInfo;
215 TopTools_ListIteratorOfListOfShape anItList;
217 // 1.Filling mySmartMap
220 anItList.Initialize(myEdges);
221 for (; anItList.More(); anItList.Next()) {
222 const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value());
224 if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) {
228 TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX);
229 for (; anExpVerts.More(); anExpVerts.Next()) {
230 const TopoDS_Shape& aVertex= anExpVerts.Current();
232 index = mySmartMap.FindIndex(aVertex);
234 index=mySmartMap.Add(aVertex, emptyInfo);
237 BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index);
240 aEInfo.SetEdge(anEdge);
242 TopAbs_Orientation anOr=aVertex.Orientation();
244 if (anOr==TopAbs_FORWARD) {
245 aEInfo.SetInFlag(Standard_False);
248 else if (anOr==TopAbs_REVERSED) {
249 aEInfo.SetInFlag(Standard_True);
252 aListOfEInfo.Append(aEInfo);
256 aNb=mySmartMap.Extent();
259 myNothingToDo=Standard_True;
261 for (i=1; i<=aNb; i++) {
264 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
265 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
266 for (; anIt.More(); anIt.Next()) {
267 const BOP_EdgeInfo& anEdgeInfo=anIt.Value();
268 anIsIn=anEdgeInfo.IsIn();
276 if (aCntIn!=1 || aCntOut!=1) {
277 myNothingToDo=Standard_False;
282 // Each vertex has one edge In and one - Out. Good. But it is not enought
283 // to consider that nothing to do with this. We must check edges on TShape
284 // coinsidence. If there are such edges there is something to do with.
287 Standard_Integer aNbE, aNbMapEE;
288 TopTools_IndexedDataMapOfShapeListOfShape aMapEE;
289 aNbE=myEdges.Extent();
291 anItList.Initialize(myEdges);
292 for (; anItList.More(); anItList.Next()) {
293 const TopoDS_Shape& aE = anItList.Value();
295 if (!aMapEE.Contains(aE)) {
296 TopTools_ListOfShape aLEx;
298 aMapEE.Add(aE, aLEx);
301 TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
306 Standard_Boolean bFlag;
308 aNbMapEE=aMapEE.Extent();
309 for (i=1; i<=aNbMapEE; i++) {
310 const TopTools_ListOfShape& aLEx=aMapEE(i);
317 const TopoDS_Shape& aE1=aLEx.First();
318 const TopoDS_Shape& aE2=aLEx.Last();
319 if (aE1.IsSame(aE2)) {
320 bFlag=Standard_False;
325 bFlag=Standard_False;
329 myNothingToDo=myNothingToDo && bFlag;
338 // 3. Angles in mySmartMap
339 BRepAdaptor_Surface aBAS(myFace);
340 const GeomAdaptor_Surface& aGAS=aBAS.Surface();
341 for (i=1; i<=aNb; i++) {
342 const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i));
343 const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
345 BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
346 for (; anIt.More(); anIt.Next()) {
347 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
348 const TopoDS_Edge& aE=anEdgeInfo.Edge();
350 TopoDS_Vertex aVV=aV;
352 anIsIn=anEdgeInfo.IsIn();
355 aVV.Orientation(TopAbs_REVERSED);
356 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
361 aVV.Orientation(TopAbs_FORWARD);
362 anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
364 anEdgeInfo.SetAngle(anAngle);
371 Standard_Boolean anIsOut, anIsNotPassed;
373 TopTools_SequenceOfShape aLS, aVertVa;
374 TColgp_SequenceOfPnt2d aCoordVa;
376 BOP_ListIteratorOfListOfEdgeInfo anIt;
378 for (i=1; i<=aNb; i++) {
379 const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i));
380 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i);
382 anIt.Initialize(aLEInfo);
383 for (; anIt.More(); anIt.Next()) {
384 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
385 const TopoDS_Edge& aEOuta=anEdgeInfo.Edge();
387 anIsOut=!anEdgeInfo.IsIn();
388 anIsNotPassed=!anEdgeInfo.Passed();
390 if (anIsOut && anIsNotPassed) {
396 Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS,
397 aVertVa, aCoordVa, myShapes, mySmartMap);
403 Standard_Integer aNbV, aNbE;
404 TopoDS_Vertex aV1, aV2;
405 BOPTColStd_ListOfListOfShape aShapes;
406 BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes);
408 for (; anItW.More(); anItW.Next()) {
409 TopTools_IndexedMapOfShape aMV, aME;
410 const TopTools_ListOfShape& aLE=anItW.Value();
411 TopTools_ListIteratorOfListOfShape anItE(aLE);
412 for (; anItE.More(); anItE.Next()) {
413 const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value());
415 TopExp::Vertices(aE, aV1, aV2);
427 anItW.Initialize(aShapes);
428 for (; anItW.More(); anItW.Next()) {
429 const TopTools_ListOfShape& aLE=anItW.Value();
430 myShapes.Append(aLE);
436 //=======================================================================
439 //=======================================================================
440 void Path (const GeomAdaptor_Surface& aGAS,
441 const TopoDS_Face& myFace,
442 const TopoDS_Vertex& aVa,
443 const TopoDS_Edge& aEOuta,
444 BOP_EdgeInfo& anEdgeInfo,
445 TopTools_SequenceOfShape& aLS,
446 TopTools_SequenceOfShape& aVertVa,
447 TColgp_SequenceOfPnt2d& aCoordVa,
448 BOPTColStd_ListOfListOfShape& myShapes,
449 BOP_IndexedDataMapOfVertexListEdgeInfo& mySmartMap)
452 Standard_Integer i,j, aNb, aNbj;
453 Standard_Real aTol, anAngleIn, anAngleOut, anAngle, aMinAngle;
454 Standard_Real aTol2D, aTol2D2;
455 Standard_Real aTol2, aD2;//, aTolUVb, aTolVVb;
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 const BOP_ListOfEdgeInfo& aLEInfoVb=mySmartMap.FindFromKey(aVb);
490 aTol=2.*Tolerance2D(aVb, aGAS);
496 TopTools_ListOfShape aBuf;
498 for (i=aNb; i>0; i--) {
499 const TopoDS_Shape& aVPrev=aVertVa(i);
500 const gp_Pnt2d& aPaPrev=aCoordVa(i);
501 const TopoDS_Shape& aEPrev=aLS(i);
505 anIsSameV=aVPrev.IsSame(aVb);
506 anIsSameV2d=Standard_False;
509 anIsSameV2d = Standard_True;
511 aD2=aPaPrev.SquareDistance(aPb);
512 anIsSameV2d =aD2<aTol2;
515 if (anIsSameV && anIsSameV2d) {
516 myShapes.Append(aBuf);
518 TopTools_SequenceOfShape aLSt, aVertVat;
519 TColgp_SequenceOfPnt2d aCoordVat;
531 aVb=TopoDS::Vertex(aVertVa(i));
533 for (j=1; j<=aNbj; j++) {
535 aVertVat.Append(aVertVa(j));
536 aCoordVat.Append(aCoordVa(j));
552 aTol2D=2.*Tolerance2D(aVb, aGAS);
553 aTol2D2=aTol2D*aTol2D;
555 // anAngleIn in Vb from edge aEOuta
556 const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
558 anAngleIn=AngleIn(aEOuta, aLEInfo);
561 BOP_EdgeInfo *pEdgeInfo=NULL;
564 anIsFound=Standard_False;
566 Standard_Integer aCurIndexE = 0;
568 anIt.Initialize(aLEInfo);
569 for (; anIt.More(); anIt.Next()) {
570 BOP_EdgeInfo& anEI=anIt.Value();
571 const TopoDS_Edge& aE=anEI.Edge();
572 anIsOut=!anEI.IsIn();
573 anIsNotPassed=!anEI.Passed();
575 if (anIsOut && anIsNotPassed) {
578 // Is there one way to go out of the vertex
579 // we have to use it only.
580 Standard_Integer iCnt;
581 iCnt=NbWaysOut (aLEInfo);
584 // no way to go . (Error)
589 // the one and only way to go out .
591 anIsFound=Standard_True;
595 // Look for minimal angle and make the choice.
598 aP2Dx=Coord2dVf(aE, myFace);
600 aD2=aP2Dx.SquareDistance(aPb);
606 anAngleOut=anEI.Angle();
608 anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
609 if (anAngle < aMinAngle) {
612 anIsFound=Standard_True;
615 } // for (; anIt.More(); anIt.Next())
618 // no way to go . (Error)
622 aEOutb=pEdgeInfo->Edge();
624 Path (aGAS, myFace, aVb, aEOutb, *pEdgeInfo, aLS,
625 aVertVa, aCoordVa, myShapes, mySmartMap);
627 //=======================================================================
628 // function: Coord2dVf
630 //=======================================================================
631 gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
632 const TopoDS_Face& aF)
634 Standard_Real aCoord=99.;
635 gp_Pnt2d aP2D1(aCoord, aCoord);
639 for (; aIt.More(); aIt.Next()) {
640 const TopoDS_Shape& aVx=aIt.Value();
641 if (aVx.Orientation()==TopAbs_FORWARD) {
642 const TopoDS_Vertex& aVxx=TopoDS::Vertex(aVx);
643 aP2D1=Coord2d(aVxx, aE, aF);
649 //=======================================================================
650 // function: Tolerance2D
652 //=======================================================================
653 Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
654 const GeomAdaptor_Surface& aGAS)
656 Standard_Real aTol2D, anUr, aVr, aTolV3D;
657 GeomAbs_SurfaceType aType;
659 aType=aGAS.GetType();
660 aTolV3D=BRep_Tool::Tolerance(aV);
662 anUr=aGAS.UResolution(aTolV3D);
663 aVr =aGAS.VResolution(aTolV3D);
664 aTol2D=(aVr>anUr) ? aVr : anUr;
666 if (aType==GeomAbs_BSplineSurface||
667 aType==GeomAbs_Sphere||
668 GeomAbs_SurfaceOfRevolution) {
669 if (aTol2D < aTolV3D) {
673 if (aType==GeomAbs_BSplineSurface) {
680 //=======================================================================
683 //=======================================================================
684 gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
685 const TopoDS_Edge& aE1,
686 const TopoDS_Face& aF)
688 Standard_Real aT, aFirst, aLast;
689 Handle(Geom2d_Curve) aC2D;
692 aT=BRep_Tool::Parameter (aV1, aE1, aF);
693 aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
694 aC2D->D0 (aT, aP2D1);
698 //=======================================================================
701 //=======================================================================
702 Standard_Real AngleIn(const TopoDS_Edge& aEIn,
703 const BOP_ListOfEdgeInfo& aLEInfo)
705 Standard_Real anAngleIn;
706 Standard_Boolean anIsIn;
707 BOP_ListIteratorOfListOfEdgeInfo anIt;
709 anIt.Initialize(aLEInfo);
710 for (; anIt.More(); anIt.Next()) {
711 BOP_EdgeInfo& anEdgeInfo=anIt.Value();
712 const TopoDS_Edge& aE=anEdgeInfo.Edge();
713 anIsIn=anEdgeInfo.IsIn();
715 if (anIsIn && aE==aEIn) {
716 anAngleIn=anEdgeInfo.Angle();
723 //=======================================================================
724 // function: ClockWiseAngle
726 //=======================================================================
727 Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
728 const Standard_Real aAngleOut)
730 Standard_Real aTwoPi=Standard_PI+Standard_PI;
731 Standard_Real dA, A1, A2, AIn, AOut ;
739 if (AOut >= aTwoPi) {
756 //else if (dA <= 1.e-15) {
757 else if (dA <= 1.e-14) {
762 //=======================================================================
763 // function: GetNextVertex
765 //=======================================================================
766 void GetNextVertex(const TopoDS_Vertex& aV,
767 const TopoDS_Edge& aE,
773 for (; aIt.More(); aIt.Next()) {
774 const TopoDS_Shape& aVx=aIt.Value();
775 if (!aVx.IsEqual(aV)) {
776 aV1=TopoDS::Vertex(aVx);
782 //=======================================================================
785 //=======================================================================
786 Standard_Real Angle2D (const TopoDS_Vertex& aV,
787 const TopoDS_Edge& anEdge,
788 const TopoDS_Face& myFace,
789 const GeomAdaptor_Surface& aGAS,
790 const Standard_Boolean aFlag)
792 Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
795 Handle(Geom2d_Curve) aC2D;
797 aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
798 if (Precision::IsInfinite(aTV)) {
802 BOPTools_Tools2D::CurveOnSurface (anEdge, myFace, aC2D,
803 aFirst, aLast, aToler, Standard_True);
805 //modified by NIZNHY-PKV Wed Sep 10 14:06:04 2008f
806 //dt=Tolerance2D(aV, aGAS);
807 dt=2.*Tolerance2D(aV, aGAS);
808 //modified by NIZNHY-PKV Wed Sep 10 14:06:07 2008t
810 aTX=0.25*(aLast - aFirst);
812 // to save direction of the curve as much as it possible
813 // in the case of big tolerances
817 if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
825 aC2D->D0 (aTV1, aPV1);
828 gp_Vec2d aV2DIn(aPV1, aPV);
832 gp_Vec2d aV2DOut(aPV, aPV1);
836 gp_Dir2d aDir2D(aV2D);
837 anAngle=Angle(aDir2D);
841 //=======================================================================
844 //=======================================================================
845 Standard_Real Angle (const gp_Dir2d& aDir2D)
847 gp_Dir2d aRefDir(1., 0.);
848 Standard_Real anAngle = aRefDir.Angle(aDir2D);
851 anAngle += Standard_PI + Standard_PI;
856 //=======================================================================
857 // function: NbWaysOut
859 //=======================================================================
860 Standard_Integer NbWaysOut(const BOP_ListOfEdgeInfo& aLEInfo)
862 Standard_Boolean bIsOut, bIsNotPassed;
863 Standard_Integer iCnt=0;
864 BOP_ListIteratorOfListOfEdgeInfo anIt;
866 anIt.Initialize(aLEInfo);
867 for (; anIt.More(); anIt.Next()) {
868 BOP_EdgeInfo& anEI=anIt.Value();
871 bIsNotPassed=!anEI.Passed();
872 if (bIsOut && bIsNotPassed) {