0024655: Boolean common produces incorrect result
[occt.git] / src / BOPAlgo / BOPAlgo_WireSplitter_1.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15 #include <BOPAlgo_WireSplitter.ixx>
16
17 #include <Precision.hxx>
18
19 #include <gp_Pnt2d.hxx>
20 #include <gp_Vec2d.hxx>
21 #include <gp_Dir2d.hxx>
22
23 #include <Geom_Surface.hxx>
24 #include <Geom_Plane.hxx>
25 #include <Geom_RectangularTrimmedSurface.hxx>
26 #include <Geom2d_Curve.hxx>
27 #include <Geom2d_Line.hxx>
28 #include <GeomAdaptor_Surface.hxx>
29 #include <Geom2dAdaptor_Curve.hxx>
30
31 #include <Geom2dInt_GInter.hxx>
32 #include <IntRes2d_Domain.hxx>
33 #include <IntRes2d_IntersectionPoint.hxx>
34
35 #include <TopLoc_Location.hxx>
36
37 #include <TopoDS_Edge.hxx>
38 #include <TopoDS_Vertex.hxx>
39 #include <TopoDS_Wire.hxx>
40 #include <TopoDS_Iterator.hxx>
41 #include <BRep_Tool.hxx>
42 #include <BRep_Builder.hxx>
43
44 #include <TopTools_ShapeMapHasher.hxx>
45 #include <TopExp.hxx>
46 #include <TopExp_Explorer.hxx>
47
48 #include <BRepAdaptor_Surface.hxx>
49
50 #include <BOPCol_ListOfShape.hxx>
51 #include <BOPCol_SequenceOfShape.hxx>
52 #include <BOPCol_SequenceOfPnt2d.hxx>
53 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
54 #include <BOPCol_SequenceOfReal.hxx>
55 #include <BOPCol_DataMapOfShapeInteger.hxx>
56 #include <BOPCol_MapOfShape.hxx>
57
58 #include <BOPTools_AlgoTools2D.hxx>
59
60 static
61   Standard_Real Angle (const gp_Dir2d& aDir2D);
62
63 static
64   Standard_Real Angle2D (const TopoDS_Vertex& aV,
65                          const TopoDS_Edge& anEdge,
66                          const TopoDS_Face& myFace,
67                          const GeomAdaptor_Surface& aGAS,
68                          const Standard_Boolean aFlag);
69
70 static
71   void GetNextVertex(const TopoDS_Vertex& aV,
72                      const TopoDS_Edge& aE,
73                      TopoDS_Vertex& aV1);
74
75 static
76   Standard_Real AngleIn(const TopoDS_Edge& aEIn,
77                         const BOPAlgo_ListOfEdgeInfo& aLEInfo);
78
79 static
80   Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo);
81
82 static
83   gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
84                       const TopoDS_Face& aF);
85
86 static
87   gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
88                     const TopoDS_Edge& aE1,
89                     const TopoDS_Face& aF);
90
91
92 static
93   Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
94                                const Standard_Real aAngleOut);
95
96 static 
97   void Path (const GeomAdaptor_Surface& aGAS,
98              const TopoDS_Face& myFace,
99              const TopoDS_Vertex& aVa,
100              const TopoDS_Edge& aEOuta,
101              BOPAlgo_EdgeInfo& anEdgeInfo,
102              BOPCol_SequenceOfShape& aLS,
103              BOPCol_SequenceOfShape& aVertVa,
104              BOPCol_SequenceOfPnt2d& aCoordVa,
105              BOPTools_ConnexityBlock& aCB,
106              BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap);
107              
108 static
109   Standard_Real Angle2D (const TopoDS_Vertex& aV,
110                          const TopoDS_Edge& anEdge,
111                          const TopoDS_Face& myFace,
112                          const GeomAdaptor_Surface& aGAS,
113                          const Standard_Boolean aFlag);
114 static
115   Standard_Real Angle (const gp_Dir2d& aDir2D);
116
117 static
118   Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
119                              const GeomAdaptor_Surface& aGAS);
120
121
122
123 static
124   Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
125                               const GeomAdaptor_Surface& aGAS);
126 static
127   Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
128                               const GeomAdaptor_Surface& aGAS);
129
130 static
131   Standard_Boolean RecomputeAngles(const BOPAlgo_ListOfEdgeInfo& aLEInfo, 
132                                    const TopoDS_Face&            theFace, 
133                                    const gp_Pnt2d&               thePb, 
134                                    const TopoDS_Vertex&          theVb,
135                                    const GeomAdaptor_Surface&    theGAS,
136                                    const TopoDS_Edge&            theEOuta, 
137                                    const Standard_Boolean&       bHasClosed,
138                                    const Standard_Real&          theTol2D,
139                                    BOPCol_SequenceOfReal&        theRecomputedAngles);
140
141 static
142   void RefineAngles(const TopoDS_Face& myFace,
143                     const BOPCol_ListOfShape&,
144                     BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo&);
145
146
147 static
148   void RefineAngles(const TopoDS_Vertex& ,
149                   const TopoDS_Face& ,
150                   const BOPCol_MapOfShape& ,
151                   BOPAlgo_ListOfEdgeInfo& );
152
153 static
154   Standard_Boolean RefineAngle2D(const TopoDS_Vertex& ,
155                                  const TopoDS_Edge& ,
156                                  const TopoDS_Face& ,
157                                  const Standard_Real ,
158                                  const Standard_Real ,
159                                  Standard_Real& );
160
161 //=======================================================================
162 //function : SplitBlock
163 //purpose  : 
164 //=======================================================================
165 void BOPAlgo_WireSplitter::SplitBlock(const TopoDS_Face& myFace,
166                                       BOPTools_ConnexityBlock& aCB)
167 {
168   Standard_Boolean bNothingToDo;
169   Standard_Integer aIx, aNb, i, aCntIn, aCntOut;
170   Standard_Real aAngle;
171   TopAbs_Orientation aOr;
172   TopoDS_Iterator aItS;
173   TopoDS_Vertex aVV;
174   BOPCol_ListIteratorOfListOfShape aIt;
175   BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
176   //
177   BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo mySmartMap(100);
178   //
179   const BOPCol_ListOfShape& myEdges=aCB.Shapes();
180   //
181   // 1.Filling mySmartMap
182   BOPTools_AlgoTools2D::BuildPCurveForEdgesOnPlane(myEdges, myFace);
183   //
184   aIt.Initialize(myEdges);
185   for(; aIt.More(); aIt.Next()) {
186     const TopoDS_Edge& aE=(*(TopoDS_Edge *)&aIt.Value());
187     if (!BOPTools_AlgoTools2D::HasCurveOnSurface (aE, myFace)) {
188       continue;
189     }
190     //
191     aItS.Initialize(aE);
192     for(; aItS.More(); aItS.Next()) {
193       const TopoDS_Shape& aV=aItS.Value();
194       aIx=mySmartMap.FindIndex(aV);
195       if (!aIx) {
196         BOPAlgo_ListOfEdgeInfo aLEIx;
197         aIx=mySmartMap.Add(aV, aLEIx);
198       }
199       //
200       BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(aIx);
201       //
202       BOPAlgo_EdgeInfo aEI;
203       //
204       aEI.SetEdge(aE);
205       aOr=aV.Orientation();
206       if (aOr==TopAbs_FORWARD) {
207         aEI.SetInFlag(Standard_False);
208       }
209       else if (aOr==TopAbs_REVERSED) {
210         aEI.SetInFlag(Standard_True);
211       }
212       aLEI.Append(aEI);
213     }
214   }
215   //
216   aNb=mySmartMap.Extent();
217   //
218   bNothingToDo=Standard_True;
219   for (i=1; i<=aNb; i++) {
220     aCntIn=0;
221     aCntOut=0;
222     const BOPAlgo_ListOfEdgeInfo& aLEInfo= mySmartMap(i);
223     BOPAlgo_ListIteratorOfListOfEdgeInfo anIt(aLEInfo);
224     for (; anIt.More(); anIt.Next()) {
225       const BOPAlgo_EdgeInfo& aEI=anIt.Value();
226       if (aEI.IsIn()) {
227         aCntIn++;
228       }
229       else {
230         aCntOut++;
231       }
232     }
233     if (aCntIn!=1 || aCntOut!=1) {
234       bNothingToDo=Standard_False;
235       break;
236     }
237   }
238   //
239   // Each vertex has one edge In and one - Out. Good. But it is not enought
240   // to consider that nothing to do with this. We must check edges on TShape
241   // coinsidence. If there are such edges there is something to do with.
242   if (bNothingToDo) {
243     Standard_Integer aNbE, aNbMapEE;
244     Standard_Boolean bFlag;
245     //
246     BOPCol_IndexedDataMapOfShapeListOfShape aMapEE(100);
247     aNbE=myEdges.Extent();
248     //
249     aIt.Initialize(myEdges);
250     for (; aIt.More(); aIt.Next()) {
251       const TopoDS_Shape& aE = aIt.Value();
252       if (!aMapEE.Contains(aE)) {
253         BOPCol_ListOfShape aLEx;
254         aLEx.Append(aE);
255         aMapEE.Add(aE, aLEx);
256       }
257       else {
258         BOPCol_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE);
259         aLEx.Append(aE);
260       }
261     }
262     //
263     bFlag=Standard_True;
264     aNbMapEE=aMapEE.Extent();
265     for (i=1; i<=aNbMapEE; ++i) {
266       const BOPCol_ListOfShape& aLEx=aMapEE(i);
267       aNbE=aLEx.Extent();
268       if (aNbE==1) {// usual case
269         continue;
270       }
271       else if (aNbE==2){
272         const TopoDS_Shape& aE1=aLEx.First();
273         const TopoDS_Shape& aE2=aLEx.Last();
274         if (aE1.IsSame(aE2)) {
275           bFlag=Standard_False;
276           break;
277         }
278       }
279       else {
280         bFlag=Standard_False;
281         break;
282       }
283     }
284     bNothingToDo=bNothingToDo && bFlag;
285   } // if (bNothingToDo) {
286   if (bNothingToDo) {
287     TopoDS_Wire aW;
288     //
289     BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
290     BOPAlgo_WireSplitter::MakeWire(aLECB, aW);
291     BOPCol_ListOfShape& aLoops=aCB.ChangeLoops();
292     aLoops.Append(aW);
293     //
294     return;
295   }
296   //
297   // 3. Angles in mySmartMap
298   BRepAdaptor_Surface aBAS(myFace);
299   const GeomAdaptor_Surface& aGAS=aBAS.Surface();
300   //
301   for (i=1; i<=aNb; i++) {
302     const TopoDS_Vertex& aV=(*(TopoDS_Vertex *)(&mySmartMap.FindKey(i))); 
303     const BOPAlgo_ListOfEdgeInfo& aLEI= mySmartMap(i);
304
305     aItLEI.Initialize(aLEI);
306     for (; aItLEI.More(); aItLEI.Next()) {
307       BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
308       const TopoDS_Edge& aE=aEI.Edge();
309       //
310       aVV=aV;
311       if (aEI.IsIn()) {
312         aVV.Orientation(TopAbs_REVERSED);
313         aAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True);
314       }
315       else { // OUT
316         aVV.Orientation(TopAbs_FORWARD);
317         aAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False);
318       }
319       aEI.SetAngle(aAngle);
320     }
321   }// for (i=1; i<=aNb; i++) {
322   //
323   //Theme: The treatment p-curves convergent in node.
324   //The refining the angles of p-curves taking into account 
325   //bounging curves if exist. 
326   RefineAngles(myFace, myEdges, mySmartMap);
327   //
328   // 4. Do
329   //
330   Standard_Boolean bIsOut, bIsNotPassed;
331   BOPCol_SequenceOfShape aLS, aVertVa;
332   BOPCol_SequenceOfPnt2d aCoordVa;
333   //
334   for (i=1; i<=aNb; ++i) {
335     const TopoDS_Vertex& aVa=(*(TopoDS_Vertex *)(&mySmartMap.FindKey(i))); 
336     const BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
337     aItLEI.Initialize(aLEI);
338     for (; aItLEI.More(); aItLEI.Next()) {
339       BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
340       const TopoDS_Edge& aEOuta=aEI.Edge();
341       //
342       bIsOut=!aEI.IsIn();
343       bIsNotPassed=!aEI.Passed();
344       if (bIsOut && bIsNotPassed) {
345         //
346         aLS.Clear();
347         aVertVa.Clear();
348         aCoordVa.Clear();
349         //
350         Path(aGAS, myFace, aVa, aEOuta, aEI, aLS, 
351              aVertVa, aCoordVa, aCB, mySmartMap);
352       }
353     }
354   }// for (i=1; i<=aNb; ++i) {
355 }
356 //=======================================================================
357 // function: Path
358 // purpose: 
359 //=======================================================================
360 void Path (const GeomAdaptor_Surface& aGAS,
361            const TopoDS_Face& myFace,
362            const TopoDS_Vertex& aVFirst,
363            const TopoDS_Edge& aEFirst,
364            BOPAlgo_EdgeInfo& aEIFirst,
365            BOPCol_SequenceOfShape& aLS,
366            BOPCol_SequenceOfShape& aVertVa,
367            BOPCol_SequenceOfPnt2d& aCoordVa,
368            BOPTools_ConnexityBlock& aCB,
369            BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap)
370      
371 {
372   Standard_Integer i, j, aNb, aNbj;
373   Standard_Real anAngleIn, anAngleOut, anAngle, aMinAngle;
374   Standard_Real aTol2D, aTol2D2, aD2, aTwoPI;
375   Standard_Boolean anIsSameV2d, anIsSameV, anIsFound, anIsOut, anIsNotPassed;
376   Standard_Boolean bIsClosed, bRecomputeAngle;
377   TopoDS_Vertex aVa, aVb;
378   TopoDS_Edge aEOuta;
379   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
380   BOPCol_SequenceOfReal aRecomputedAngles;
381   //
382   aVa = aVFirst;
383   aEOuta = aEFirst;
384   BOPAlgo_EdgeInfo* anEdgeInfo = &aEIFirst;
385   //
386   aTwoPI = M_PI + M_PI;
387   //
388   // append block
389   //
390   for (;;) {
391     // Do not escape through edge from which you enter 
392     aNb=aLS.Length();
393     if (aNb==1) {
394       const TopoDS_Shape& anEPrev=aLS(aNb);
395       if (anEPrev.IsSame(aEOuta)) {
396         return;
397       }
398     }
399     //
400     anEdgeInfo->SetPassed(Standard_True);
401     aLS.Append(aEOuta);
402     aVertVa.Append(aVa);
403     
404     TopoDS_Vertex pVa=aVa;
405     pVa.Orientation(TopAbs_FORWARD);
406     gp_Pnt2d aPa=Coord2d(pVa, aEOuta, myFace);
407     aCoordVa.Append(aPa);
408     
409     GetNextVertex (pVa, aEOuta, aVb);
410     
411     gp_Pnt2d aPb=Coord2d(aVb, aEOuta, myFace);
412     
413     const BOPAlgo_ListOfEdgeInfo& aLEInfo=mySmartMap.FindFromKey(aVb);
414     //
415     aTol2D = 2.*Tolerance2D(aVb, aGAS);
416     aTol2D2 = aTol2D * aTol2D;
417     //
418     bIsClosed = BRep_Tool::Degenerated(aEOuta) || 
419       BRep_Tool::IsClosed(aEOuta, myFace) || aVa.IsSame(aVb);
420     if (!bIsClosed) {
421       TopoDS_Vertex aV1, aV2;
422       //
423       anIt.Initialize(aLEInfo);
424       for (; anIt.More() && !bIsClosed; anIt.Next()) {
425         const BOPAlgo_EdgeInfo& anEI = anIt.Value();
426         const TopoDS_Edge& aE = anEI.Edge();
427         //
428         bIsClosed = BRep_Tool::Degenerated(aE) || BRep_Tool::IsClosed(aE, myFace);
429         if (!bIsClosed) {
430           TopExp::Vertices(aE, aV1, aV2);
431           bIsClosed = aV1.IsNull() || aV2.IsNull() || aV1.IsSame(aV2);
432         }
433       }
434     }
435     //
436     aNb=aLS.Length();
437     if (aNb>0) {
438       //
439       BOPCol_ListOfShape aBuf;
440       //
441       for (i=aNb; i>0; --i) {
442         const TopoDS_Shape& aVPrev=aVertVa(i);
443         const gp_Pnt2d& aPaPrev=aCoordVa(i);
444         const TopoDS_Shape& aEPrev=aLS(i);
445         
446         aBuf.Append(aEPrev);
447         
448         anIsSameV = aVPrev.IsSame(aVb);
449         anIsSameV2d = anIsSameV;
450         if (anIsSameV) {
451           if(bIsClosed) {
452             aD2 = aPaPrev.SquareDistance(aPb);
453             anIsSameV2d = aD2 < aTol2D2;
454             if (anIsSameV2d) {
455               Standard_Real udist = fabs(aPaPrev.X() - aPb.X());
456               Standard_Real vdist = fabs(aPaPrev.Y() - aPb.Y());
457               Standard_Real aTolU = 2.*UTolerance2D(aVb, aGAS);
458               Standard_Real aTolV = 2.*VTolerance2D(aVb, aGAS);
459               //
460               if((udist > aTolU) || (vdist > aTolV)) {
461                 anIsSameV2d = Standard_False;
462               }
463             }
464           }
465         }//if (anIsSameV) {
466         //
467         if (anIsSameV && anIsSameV2d) {
468           Standard_Integer iPriz;
469           iPriz=1;
470           if (aBuf.Extent()==2) {
471             if(aBuf.First().IsSame(aBuf.Last())) {
472               iPriz=0;
473             }
474           }
475           if (iPriz) {
476             TopoDS_Wire aW;
477             BOPAlgo_WireSplitter::MakeWire(aBuf, aW);
478             aCB.ChangeLoops().Append(aW);
479           }
480           //
481           aNbj=i-1;
482           if (aNbj<1) {
483             //
484             aLS.Clear();
485             aVertVa.Clear();
486             aCoordVa.Clear();
487             //
488             return;
489           }
490           //
491           BOPCol_SequenceOfShape aLSt, aVertVat;
492           BOPCol_SequenceOfPnt2d aCoordVat;
493           //
494           aVb=(*(TopoDS_Vertex *)(&aVertVa(i))); 
495           //
496           for (j=1; j<=aNbj; ++j) {
497             aLSt.Append(aLS(j));
498             aVertVat.Append(aVertVa(j));
499             aCoordVat.Append(aCoordVa(j));
500           }
501           //
502           aLS.Clear();
503           aVertVa.Clear();
504           aCoordVa.Clear();
505           
506           aLS=aLSt;
507           aVertVa=aVertVat;
508           aCoordVa=aCoordVat;
509           //
510           break;
511         }
512       }
513     }
514     //
515     aRecomputedAngles.Clear();
516     bRecomputeAngle = 
517       RecomputeAngles(aLEInfo, myFace, aPb, aVb, aGAS, aEOuta, 
518                       bIsClosed, aTol2D, aRecomputedAngles);
519     //
520     // aEOutb
521     BOPAlgo_EdgeInfo *pEdgeInfo=NULL;
522     //
523     anAngleIn = AngleIn(aEOuta, aLEInfo);
524     aMinAngle = 100.;
525     anIsFound = Standard_False;
526     Standard_Integer aCurIndexE = 0;
527     anIt.Initialize(aLEInfo);
528     for (; anIt.More(); anIt.Next()) {
529       BOPAlgo_EdgeInfo& anEI=anIt.ChangeValue();
530       const TopoDS_Edge& aE=anEI.Edge();
531       anIsOut=!anEI.IsIn();
532       anIsNotPassed=!anEI.Passed();
533       
534       if (anIsOut && anIsNotPassed) {
535         aCurIndexE++;
536         //
537         // Is there one way to go out of the vertex 
538         // we have to use it only.
539         Standard_Integer iCnt;
540         iCnt=NbWaysOut (aLEInfo);
541         //
542         if (!iCnt) {
543           // no way to go . (Error)
544           return;
545         }
546         //
547         if (iCnt==1) {
548           // the one and only way to go out .
549           pEdgeInfo=&anEI;
550           anIsFound=Standard_True;
551           break;
552         }
553         //
554         if (aE.IsSame(aEOuta)) {
555           anAngle = aTwoPI;
556         } else {
557           //check 2d distance
558           if (bIsClosed) {
559             gp_Pnt2d aP2Dx;
560             //
561             aP2Dx = Coord2dVf(aE, myFace);
562             //
563             aD2 = aP2Dx.SquareDistance(aPb);
564             if (aD2 > aTol2D2){
565               continue;
566             }
567           }
568           //
569           // Look for minimal angle and make the choice.
570           anAngleOut=anEI.Angle();
571           //
572           if(bRecomputeAngle) {
573             if(aCurIndexE <= aRecomputedAngles.Length()) {
574               anAngleOut = aRecomputedAngles.Value(aCurIndexE);
575             }
576           }
577           anAngle=ClockWiseAngle(anAngleIn, anAngleOut);
578         }
579         if (anAngle < aMinAngle) {
580           aMinAngle=anAngle;
581           pEdgeInfo=&anEI;
582           anIsFound=Standard_True;
583         }
584       }
585     } // for (; anIt.More(); anIt.Next()) 
586     //
587     if (!anIsFound) {
588       // no way to go . (Error)
589       return;
590     }
591     //
592     aVa = aVb;
593     aEOuta = pEdgeInfo->Edge();
594     anEdgeInfo = pEdgeInfo;
595   }
596 }
597 //=======================================================================
598 // function:  ClockWiseAngle
599 // purpose:
600 //=======================================================================
601  Standard_Real ClockWiseAngle(const Standard_Real aAngleIn,
602                               const Standard_Real aAngleOut)
603 {
604   Standard_Real aTwoPi=M_PI+M_PI;
605   Standard_Real dA, A1, A2, AIn, AOut ;
606
607   AIn=aAngleIn;
608   AOut=aAngleOut;
609   if (AIn >= aTwoPi) {
610     AIn=AIn-aTwoPi;
611   }
612   
613   if (AOut >= aTwoPi) {
614     AOut=AOut-aTwoPi;
615   }
616
617   A1=AIn+M_PI;
618   
619   if (A1 >= aTwoPi) {
620     A1=A1-aTwoPi;
621   }
622   
623   A2=AOut;
624   
625   dA=A1-A2;
626   if (dA <= 0.) {
627     dA=aTwoPi+dA;
628   }
629   //xx
630   //else if (dA <= 1.e-15) {
631   else if (dA <= 1.e-14) {
632     dA=aTwoPi;
633   }
634   return dA;
635 }
636 //=======================================================================
637 // function:  Coord2d
638 // purpose:
639 //=======================================================================
640  gp_Pnt2d Coord2d (const TopoDS_Vertex& aV1,
641                    const TopoDS_Edge& aE1,
642                    const TopoDS_Face& aF)
643 {
644   Standard_Real aT, aFirst, aLast;
645   Handle(Geom2d_Curve) aC2D;
646   gp_Pnt2d aP2D1;
647   //
648   aT=BRep_Tool::Parameter (aV1, aE1, aF);
649   aC2D=BRep_Tool::CurveOnSurface(aE1, aF, aFirst, aLast);
650   aC2D->D0 (aT, aP2D1);
651   //
652   return aP2D1;
653 }
654 //=======================================================================
655 // function:  Coord2dVf
656 // purpose:
657 //=======================================================================
658  gp_Pnt2d Coord2dVf (const TopoDS_Edge& aE,
659                      const TopoDS_Face& aF)
660 {
661   Standard_Real aCoord=99.;
662   gp_Pnt2d aP2D1(aCoord, aCoord);
663   TopoDS_Iterator aIt;
664   //
665   aIt.Initialize(aE);
666   for (; aIt.More(); aIt.Next()) {
667     const TopoDS_Shape& aVx=aIt.Value();
668     if (aVx.Orientation()==TopAbs_FORWARD) {
669       
670       const TopoDS_Vertex& aVxx=(*(TopoDS_Vertex *)(&aVx));// TopoDS::Vertex(aVx);
671       aP2D1=Coord2d(aVxx, aE, aF);
672       return aP2D1;
673     }
674   }
675   return aP2D1;
676 }
677
678 //=======================================================================
679 // function: NbWaysOut
680 // purpose: 
681 //=======================================================================
682 Standard_Integer NbWaysOut(const BOPAlgo_ListOfEdgeInfo& aLEInfo)
683 {
684   Standard_Boolean bIsOut, bIsNotPassed;
685   Standard_Integer iCnt=0;
686   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
687   //
688   anIt.Initialize(aLEInfo);
689   for (; anIt.More(); anIt.Next()) {
690     const BOPAlgo_EdgeInfo& anEI=anIt.Value();
691     //
692     bIsOut=!anEI.IsIn();
693     bIsNotPassed=!anEI.Passed();
694     if (bIsOut && bIsNotPassed) {
695       iCnt++;
696     }
697   }
698   return iCnt;
699 }
700
701 //=======================================================================
702 // function:  AngleIn
703 // purpose:
704 //=======================================================================
705  Standard_Real AngleIn(const TopoDS_Edge& aEIn,
706                        const BOPAlgo_ListOfEdgeInfo& aLEInfo)
707 {
708   Standard_Real anAngleIn;
709   Standard_Boolean anIsIn;
710   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
711
712   anIt.Initialize(aLEInfo);
713   for (; anIt.More(); anIt.Next()) {
714     const BOPAlgo_EdgeInfo& anEdgeInfo=anIt.Value();
715     const TopoDS_Edge& aE=anEdgeInfo.Edge();
716     anIsIn=anEdgeInfo.IsIn();
717     //
718     if (anIsIn && aE==aEIn) {
719       anAngleIn=anEdgeInfo.Angle();
720       return anAngleIn;
721     }
722   }
723   anAngleIn=0.;
724   return anAngleIn;
725 }
726 //=======================================================================
727 // function: GetNextVertex
728 // purpose: 
729 //=======================================================================
730  void GetNextVertex(const TopoDS_Vertex& aV,
731                     const TopoDS_Edge& aE,
732                     TopoDS_Vertex& aV1)
733 {
734   TopoDS_Iterator aIt;
735   //
736   aIt.Initialize(aE);
737   for (; aIt.More(); aIt.Next()) {
738     const TopoDS_Shape& aVx=aIt.Value();
739     if (!aVx.IsEqual(aV)) {
740       aV1=(*(TopoDS_Vertex *)(&aVx)); 
741       return ;
742     }
743   }
744   aV1=aV;
745 }
746 //=======================================================================
747 // function: Angle2D
748 // purpose: 
749 //=======================================================================
750   Standard_Real Angle2D (const TopoDS_Vertex& aV,
751                          const TopoDS_Edge& anEdge,
752                          const TopoDS_Face& myFace,
753                          const GeomAdaptor_Surface& aGAS,
754                          const Standard_Boolean aFlag)
755 {
756   Standard_Real aFirst, aLast, aToler, dt, aTV, aTV1, anAngle, aTX;
757   gp_Pnt2d aPV, aPV1;
758   gp_Vec2d aV2D;
759   Handle(Geom2d_Curve) aC2D;
760   //
761   aTV=BRep_Tool::Parameter (aV, anEdge, myFace);
762   if (Precision::IsInfinite(aTV)) {
763     return 0.;
764   }
765   //
766   BOPTools_AlgoTools2D::CurveOnSurface (anEdge, myFace, aC2D, 
767                                         aFirst, aLast, aToler);
768   dt=2.*Tolerance2D(aV, aGAS);
769   //
770   //for case chl/927/r9
771   aTX=0.05*(aLast - aFirst);//aTX=0.25*(aLast - aFirst);
772   if (aTX < 5.e-5) {
773     aTX = 5.e-5;
774   }
775   if(dt > aTX) {
776     // to save direction of the curve as much as it possible
777     // in the case of big tolerances
778     dt = aTX; 
779   }
780   //
781   GeomAbs_CurveType aType;
782   Geom2dAdaptor_Curve aGAC2D(aC2D);
783   aType=aGAC2D.GetType();
784   if (aType==GeomAbs_BSplineCurve || aType==GeomAbs_BezierCurve) {
785     dt=1.1*dt;
786   }
787   if (fabs (aTV-aFirst) < fabs(aTV - aLast)) {
788     aTV1=aTV + dt;
789   }
790   else {
791     aTV1=aTV - dt;
792   }
793   //
794   aC2D->D0 (aTV1, aPV1);
795   aC2D->D0 (aTV, aPV);
796   //
797   if (aFlag) {//IN
798     gp_Vec2d aV2DIn(aPV1, aPV);
799     aV2D=aV2DIn;
800   }
801   else {
802     gp_Vec2d aV2DOut(aPV, aPV1);
803     aV2D=aV2DOut;
804   }
805   //
806   gp_Dir2d aDir2D(aV2D);
807   anAngle=Angle(aDir2D);
808   //
809   return anAngle;
810 }
811 //=======================================================================
812 // function: Angle
813 // purpose: 
814 //=======================================================================
815 Standard_Real Angle (const gp_Dir2d& aDir2D)
816 {
817   gp_Dir2d aRefDir(1., 0.);
818   Standard_Real anAngle;
819   
820   anAngle = aRefDir.Angle(aDir2D);
821   if (anAngle < 0.)
822     anAngle += M_PI + M_PI;
823   return anAngle;
824 }
825 //=======================================================================
826 // function:  Tolerance2D
827 // purpose:
828 //=======================================================================
829  Standard_Real Tolerance2D (const TopoDS_Vertex& aV,
830                             const GeomAdaptor_Surface& aGAS)         
831 {
832   Standard_Real aTol2D, anUr, aVr, aTolV3D;
833   GeomAbs_SurfaceType aType;
834   //
835   aType=aGAS.GetType();
836   aTolV3D=BRep_Tool::Tolerance(aV);
837
838   anUr=aGAS.UResolution(aTolV3D);
839   aVr =aGAS.VResolution(aTolV3D);
840   aTol2D=(aVr>anUr) ? aVr : anUr;
841   //
842   if (aTol2D < aTolV3D) {
843     aTol2D=aTolV3D;
844   }
845   if (aType==GeomAbs_BSplineSurface) {
846     aTol2D=1.1*aTol2D;
847   }
848   //
849   return aTol2D;
850 }
851
852 //=======================================================================
853 //function : UTolerance2D
854 //purpose  : 
855 //=======================================================================
856 Standard_Real UTolerance2D (const TopoDS_Vertex& aV,
857                             const GeomAdaptor_Surface& aGAS)
858 {
859   const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
860   const Standard_Real anUr = aGAS.UResolution(aTolV3D);
861   //
862   return anUr;
863 }
864
865 //=======================================================================
866 //function : VTolerance2D
867 //purpose  : 
868 //=======================================================================
869 Standard_Real VTolerance2D (const TopoDS_Vertex& aV,
870                             const GeomAdaptor_Surface& aGAS)
871 {
872   const Standard_Real aTolV3D = BRep_Tool::Tolerance(aV);
873   const Standard_Real anVr = aGAS.VResolution(aTolV3D);
874   //
875   return anVr;
876 }
877
878 //=======================================================================
879 // function: RecomputeAngles
880 // purpose: 
881 //=======================================================================
882 Standard_Boolean RecomputeAngles(const BOPAlgo_ListOfEdgeInfo& aLEInfo, 
883                                  const TopoDS_Face&            theFace, 
884                                  const gp_Pnt2d&               thePb, 
885                                  const TopoDS_Vertex&          theVb,
886                                  const GeomAdaptor_Surface&    theGAS,
887                                  const TopoDS_Edge&            theEOuta, 
888                                  const Standard_Boolean&       bIsClosed,
889                                  const Standard_Real&          theTol2D,
890                                  BOPCol_SequenceOfReal&        theRecomputedAngles)
891 {
892   Standard_Boolean bRecomputeAngle = Standard_False;
893   BOPAlgo_ListIteratorOfListOfEdgeInfo anIt;
894   anIt.Initialize(aLEInfo);
895
896   for (; anIt.More(); anIt.Next()) {
897     const BOPAlgo_EdgeInfo& anEI=anIt.Value();
898     const TopoDS_Edge& aE=anEI.Edge();
899     Standard_Boolean anIsOut=!anEI.IsIn();
900     Standard_Boolean anIsNotPassed=!anEI.Passed();
901     
902     if (anIsOut && anIsNotPassed) {
903       theRecomputedAngles.Append(anEI.Angle());
904       Standard_Integer acurindex = theRecomputedAngles.Length();
905
906       Standard_Boolean bRecomputeAngleLocal = Standard_False;
907       TopExp_Explorer anExp1(aE, TopAbs_VERTEX);
908
909       for(; anExp1.More(); anExp1.Next()) {
910         TopExp_Explorer anExp2(theEOuta, TopAbs_VERTEX);
911         Standard_Boolean existsInEdge = Standard_False;
912         
913         for(; anExp2.More(); anExp2.Next()) {
914           if(anExp1.Current().IsSame(anExp2.Current())) {
915             existsInEdge = Standard_True;
916             break;
917           }
918         }
919         
920         if(!existsInEdge) {
921           bRecomputeAngleLocal = Standard_False;
922           break;
923         }
924         bRecomputeAngleLocal = Standard_True;
925       }
926       bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
927
928       if(!bRecomputeAngle) {
929         BOPAlgo_ListIteratorOfListOfEdgeInfo anIt2(aLEInfo);
930         
931         for(; anIt2.More(); anIt2.Next()) {
932           const BOPAlgo_EdgeInfo& anEI2=anIt2.Value();
933           const TopoDS_Edge& aE2=anEI2.Edge();
934           
935           if(aE2.IsSame(aE))
936             continue;
937           Standard_Boolean anIsOut2=!anEI2.IsIn();
938           Standard_Boolean anIsNotPassed2=!anEI2.Passed();
939           
940           if (anIsOut2 && anIsNotPassed2) {
941             anExp1.Init(aE, TopAbs_VERTEX);
942             
943             for(; anExp1.More(); anExp1.Next()) {
944               TopExp_Explorer anExp2(aE2, TopAbs_VERTEX);
945               Standard_Boolean existsInEdge = Standard_False;
946               
947               for(; anExp2.More(); anExp2.Next()) {
948                 if(anExp1.Current().IsSame(anExp2.Current())) {
949                   existsInEdge = Standard_True;
950                   break;
951                 }
952               }
953               
954               if(!existsInEdge) {
955                 bRecomputeAngleLocal = Standard_False;
956                 break;
957               }
958               bRecomputeAngleLocal = Standard_True;
959             }
960             bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
961           }
962         }
963       }
964       
965       bRecomputeAngle = bRecomputeAngle || bRecomputeAngleLocal;
966
967       if(bRecomputeAngle) {
968         gp_Pnt2d aP2Dx;
969         //
970         aP2Dx=Coord2dVf(aE, theFace);
971         Standard_Real aD = aP2Dx.Distance(thePb);
972         
973         TopoDS_Vertex aVf;
974         TopExp_Explorer anExp(aE, TopAbs_VERTEX);
975         
976         for (; anExp.More(); anExp.Next()) {
977           const TopoDS_Vertex& aVx=*(TopoDS_Vertex*)(&anExp.Current());
978           if (aVx.Orientation()==TopAbs_FORWARD) {
979             aVf = aVx;
980           }
981         }
982         Standard_Boolean bIgnore = Standard_False;
983         
984         if(bIsClosed || aVf.IsNull() || !aVf.IsSame(theVb)) {
985           bIgnore = (aD > theTol2D);
986         }
987         
988         if(!bIgnore && (theTol2D > M_PI)) {
989           Standard_Real udist = fabs(aP2Dx.X() - thePb.X());
990           Standard_Real vdist = fabs(aP2Dx.Y() - thePb.Y());
991           Standard_Real aTolU = 2. * UTolerance2D(theVb, theGAS);
992           Standard_Real aTolV = 2. * VTolerance2D(theVb, theGAS);
993           
994           if((udist > aTolU) ||
995              (vdist > aTolV)) {
996             bIgnore = Standard_True;
997           }
998         }
999         
1000         if((aD > Precision::Confusion()) && !bIgnore) {
1001           Standard_Real f1, l1;
1002           Handle(Geom2d_Curve) ac1 = BRep_Tool::CurveOnSurface(aE, theFace, f1, l1);
1003           
1004           Standard_Real aTV1 = BRep_Tool::Parameter (aVf, aE, theFace);
1005           Standard_Real aTV12 = 0.;
1006           Standard_Real dt1 = (l1 - f1) * 0.5;
1007           
1008           if (fabs (aTV1-f1) < fabs(aTV1 - l1)) {
1009             aTV12 = aTV1 + dt1;
1010           }
1011           else {
1012             aTV12 = aTV1 - dt1;
1013           }
1014           
1015           gp_Pnt2d aPointNew = ac1->Value(aTV12);
1016           gp_Vec2d aV2DOut(thePb, aPointNew);
1017           
1018           gp_Dir2d aDir2D(aV2DOut);
1019           Standard_Real anAngleOut = Angle(aDir2D);
1020           theRecomputedAngles.ChangeValue(acurindex) = anAngleOut;
1021         }
1022       }
1023     }
1024   }
1025   return bRecomputeAngle;
1026 }
1027 //=======================================================================
1028 //function : RefineAngles
1029 //purpose  : 
1030 //=======================================================================
1031 void RefineAngles(const TopoDS_Face& myFace,
1032                   const BOPCol_ListOfShape& myEdges,
1033                   BOPAlgo_IndexedDataMapOfShapeListOfEdgeInfo& mySmartMap)
1034 {
1035   Standard_Integer aNb, i;
1036   BOPCol_DataMapOfShapeInteger aMSI;
1037   BOPCol_DataMapIteratorOfDataMapOfShapeInteger aItMSI;
1038   BOPCol_MapOfShape aMBE;
1039   BOPCol_ListIteratorOfListOfShape aIt;
1040   //
1041   // 1. Boundary Edges
1042   aIt.Initialize(myEdges);
1043   for(; aIt.More(); aIt.Next()) {
1044     const TopoDS_Shape& aE=aIt.Value();
1045     if(aMSI.IsBound(aE)) {
1046       Standard_Integer& iCnt=aMSI.ChangeFind(aE);
1047       ++iCnt;
1048     }
1049     else {
1050       Standard_Integer iCnt=1;
1051       aMSI.Bind(aE, iCnt);
1052     }
1053   }
1054   //
1055   aItMSI.Initialize(aMSI);
1056   for(; aItMSI.More(); aItMSI.Next()) {
1057     Standard_Integer iCnt;
1058     //
1059     const TopoDS_Shape& aE=aItMSI.Key();
1060     iCnt=aItMSI.Value();
1061     if (iCnt==1) {
1062       aMBE.Add(aE);
1063     }
1064     
1065   }
1066   //
1067   aMSI.Clear();
1068   //
1069   aNb=mySmartMap.Extent();
1070   for (i=1; i<=aNb; ++i) {
1071     const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&mySmartMap.FindKey(i)); 
1072     BOPAlgo_ListOfEdgeInfo& aLEI=mySmartMap(i);
1073     //
1074     RefineAngles(aV, myFace, aMBE, aLEI);
1075   }
1076 }
1077 //=======================================================================
1078 typedef NCollection_DataMap \
1079   <TopoDS_Shape, Standard_Real, TopTools_ShapeMapHasher> \
1080    BOPCol_DataMapOfShapeReal; 
1081 typedef BOPCol_DataMapOfShapeReal::Iterator \
1082   BOPCol_DataMapIteratorOfDataMapOfShapeReal; 
1083 //
1084 //=======================================================================
1085 //function : RefineAngles
1086 //purpose  : 
1087 //=======================================================================
1088 void RefineAngles(const TopoDS_Vertex& aV,
1089                   const TopoDS_Face& myFace,
1090                   const BOPCol_MapOfShape& aMBE,
1091                   BOPAlgo_ListOfEdgeInfo& aLEI)
1092 {
1093   Standard_Boolean bIsIn, bIsBoundary, bRefined; 
1094   Standard_Integer iCnt;
1095   Standard_Real aA, aA1, aA2;
1096   BOPCol_DataMapOfShapeReal aDMSR;
1097   BOPAlgo_ListIteratorOfListOfEdgeInfo aItLEI;
1098   //
1099   aA1=0.;
1100   aA2=0.;
1101   iCnt=0;
1102   aItLEI.Initialize(aLEI);
1103   for (; aItLEI.More(); aItLEI.Next()) {
1104     BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
1105     const TopoDS_Edge& aE=aEI.Edge();
1106     bIsIn=aEI.IsIn();
1107     aA=aEI.Angle();
1108     //
1109     if (aMBE.Contains(aE)) {
1110       ++iCnt;
1111       if (!bIsIn) {
1112         aA1=aA;
1113       }
1114       else {
1115         aA2=aA+M_PI;
1116       }
1117     }
1118   }
1119   //
1120   if (iCnt!=2) {
1121     return;
1122   }
1123   //
1124   aItLEI.Initialize(aLEI);
1125   for (; aItLEI.More(); aItLEI.Next()) {
1126     BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
1127     const TopoDS_Edge& aE=aEI.Edge();
1128     //
1129     bIsBoundary=aMBE.Contains(aE);
1130     bIsIn=aEI.IsIn();
1131     if (bIsBoundary || bIsIn) {
1132       continue;
1133     }
1134     //
1135     aA=aEI.Angle();
1136     if (!(aA<aA1 || aA>aA2)) {
1137       continue;
1138     }
1139     //
1140     bRefined=RefineAngle2D(aV, aE, myFace, aA1, aA2, aA);
1141     if (bRefined) {
1142       aDMSR.Bind(aE, aA);
1143     }
1144   }
1145   
1146   if (aDMSR.IsEmpty()) {
1147     return;
1148   }
1149   //
1150   // update Angles
1151   aItLEI.Initialize(aLEI);
1152   for (; aItLEI.More(); aItLEI.Next()) {
1153     BOPAlgo_EdgeInfo& aEI=aItLEI.ChangeValue();
1154     const TopoDS_Edge& aE=aEI.Edge();
1155     //
1156     bIsIn=aEI.IsIn();
1157     if (!aDMSR.IsBound(aE)) {
1158       continue;
1159     }
1160     //
1161     aA=aDMSR.Find(aE);
1162     if (bIsIn) {
1163       aA=aA+M_PI;
1164     }
1165     //
1166     aEI.SetAngle(aA);
1167   }
1168 }
1169 //=======================================================================
1170 //function : RefineAngle2D
1171 //purpose  : 
1172 //=======================================================================
1173 Standard_Boolean RefineAngle2D(const TopoDS_Vertex& aV,
1174                                const TopoDS_Edge& aE,
1175                                const TopoDS_Face& myFace,
1176                                const Standard_Real aA1,
1177                                const Standard_Real aA2,
1178                                Standard_Real& aA)
1179 {
1180   Standard_Boolean bRet;
1181   Standard_Integer i, j, aNbP, iSign;
1182   Standard_Real aTV, aTol, aT1, aT2, dT, aAngle, aT;
1183   Standard_Real aTolInt, aAi, aXi, aYi, aT1j, aT2j, aT1max, aT2max, aCf; 
1184   gp_Pnt2d aPV, aP, aP1, aP2;
1185   Handle(Geom2d_Curve) aC2D;
1186   Handle(Geom2d_Line) aLi;
1187   Geom2dAdaptor_Curve aGAC1, aGAC2;
1188   Geom2dInt_GInter aGInter;
1189   IntRes2d_Domain aDomain1, aDomain2;
1190   //
1191   bRet=Standard_True;
1192   aCf=0.01;
1193   aTolInt=1.e-10;  
1194   //
1195   BOPTools_AlgoTools2D::CurveOnSurface(aE, myFace, aC2D, aT1, aT2, aTol);
1196   //
1197   aTV=BRep_Tool::Parameter (aV, aE, myFace);
1198   aC2D->D0(aTV, aPV);
1199   //
1200   iSign=(fabs(aTV-aT1) < fabs(aTV-aT2)) ? 1 : -1;
1201   //
1202   aGAC1.Load(aC2D, aT1, aT2);
1203   aC2D->D0(aT1, aP1);
1204   aC2D->D0(aT2, aP2);
1205   aDomain1.SetValues(aP1, aT1, aTolInt, aP2, aT2, aTolInt);
1206   //
1207   for (i=0; i<2; ++i) {
1208     aAi=(!i) ? aA1 : aA2;
1209     aXi=cos(aAi);
1210     aYi=sin(aAi);
1211     gp_Dir2d aDiri(aXi, aYi);
1212     aLi=new Geom2d_Line(aPV, aDiri);
1213     //
1214     aGAC2.Load(aLi);
1215     aDomain2.SetValues(aPV, 0., aTolInt, Standard_True);
1216     //
1217     aGInter.Perform(aGAC1, aDomain1, aGAC2, aDomain2, aTolInt, aTolInt);
1218     if (!aGInter.IsDone()) {
1219       continue;
1220     }
1221     //
1222     aNbP=aGInter.NbPoints();
1223     if (aNbP<2) {
1224       continue;
1225     }
1226     //
1227     aT1max=aTV;
1228     aT2max=-1.;
1229     for (j=1; j<=aNbP; ++j) {
1230       const IntRes2d_IntersectionPoint& aIPj=aGInter.Point(j);
1231       aT1j=aIPj.ParamOnFirst();
1232       aT2j=aIPj.ParamOnSecond();
1233       //
1234       if (aT2j > aT2max) {
1235         aT2max=aT2j;
1236         aT1max=aT1j;
1237       }
1238     }
1239     //
1240     dT=(iSign==1) ? aT2-aT1max : aT1max-aT1;
1241     //
1242     aT=aT1max+aCf*dT;
1243     aC2D->D0(aT, aP);
1244     gp_Vec2d aV2D(aPV, aP);
1245     gp_Dir2d aDir2D(aV2D);
1246     //
1247     aAngle=Angle(aDir2D);
1248     if (aAngle>aA1 && aAngle<aA2) {
1249       aA=aAngle;
1250       return bRet;
1251     }
1252   }// for (i=0; i<2; ++i) {
1253   return !bRet;
1254 }