0023853: BOP regression (2) - BRepAlgoAPI_Cut.
[occt.git] / src / BOPTools / BOPTools_AlgoTools.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 2010-2012 OPEN CASCADE SAS
3 // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE
4 // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT,
5 //                         EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
6 //
7 // The content of this file is subject to the Open CASCADE Technology Public
8 // License Version 6.5 (the "License"). You may not use the content of this file
9 // except in compliance with the License. Please obtain a copy of the License
10 // at http://www.opencascade.org and read it completely before using this file.
11 //
12 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
13 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
14 //
15 // The Original Code and all software distributed under the License is
16 // distributed on an "AS IS" basis, without warranty of any kind, and the
17 // Initial Developer hereby disclaims all such warranties, including without
18 // limitation, any warranties of merchantability, fitness for a particular
19 // purpose or non-infringement. Please see the License for the specific terms
20 // and conditions governing the rights and limitations under the License.
21
22
23 #include <BOPTools_AlgoTools.ixx>
24 //
25 #include <Precision.hxx>
26 //
27 #include <gp_Pnt.hxx>
28 #include <gp_XYZ.hxx>
29 #include <gp_Pnt2d.hxx>
30 #include <gp_Cylinder.hxx>
31 #include <gp_Cone.hxx>
32 #include <gp_Sphere.hxx>
33 #include <gp_Torus.hxx>
34 //
35 #include <Geom2d_Curve.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom_Plane.hxx>
38 #include <Geom_TrimmedCurve.hxx>
39 #include <Geom_Curve.hxx>
40 #include <GeomAPI_ProjectPointOnSurf.hxx>
41 #include <Geom2dInt_Geom2dCurveTool.hxx>
42 #include <GeomAdaptor_Surface.hxx>
43 //
44 #include <TopAbs_Orientation.hxx>
45 //
46 #include <TopoDS_Compound.hxx>
47 #include <TopoDS_CompSolid.hxx>
48 #include <TopoDS_Solid.hxx>
49 #include <TopoDS_Shell.hxx>
50 #include <TopoDS_Wire.hxx>
51 //
52 #include <BRep_Builder.hxx>
53 #include <BRep_Tool.hxx>
54 #include <BRepLib.hxx>
55 #include <BRepAdaptor_Curve2d.hxx>
56 #include <BRepClass3d_SolidClassifier.hxx>
57 #include <TopExp.hxx>
58 #include <TopExp_Explorer.hxx>
59 //
60 #include <IntTools_Tools.hxx>
61 //
62 #include <BOPTools.hxx>
63 #include <BOPTools_CoupleOfShape.hxx>
64 #include <BOPTools_ListOfCoupleOfShape.hxx>
65 #include <BOPTools_AlgoTools2D.hxx>
66 #include <BOPTools_AlgoTools3D.hxx>
67 //
68 #include <BOPCol_IndexedMapOfShape.hxx>
69 #include <BOPCol_MapOfShape.hxx>
70 //
71 #include <BOPInt_ShrunkRange.hxx>
72 //
73
74 static
75   Standard_Real AngleWithRef(const gp_Dir& theD1,
76                              const gp_Dir& theD2,
77                              const gp_Dir& theDRef);
78 static 
79   inline Standard_Real fsqrt(Standard_Real val);
80
81 static
82   Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
83                                   const BOPCol_ListOfShape& thLF,
84                                   BOPTools_ListOfCoupleOfShape& theLCFF,
85                                   Handle(BOPInt_Context)& theContext);
86 static
87   TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
88                                  const TopoDS_Face& aF);
89
90 static 
91   void GetFaceDir(const TopoDS_Edge& aE,
92                   const TopoDS_Face& aF,
93                   const gp_Pnt& aP,
94                   const Standard_Real aT,
95                   const gp_Dir& aDTgt,
96                   gp_Dir& aDN,
97                   gp_Dir& aDB,
98                   Handle(BOPInt_Context)& theContext);
99 static 
100   Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
101                                    const TopoDS_Face& aF,
102                                    const gp_Pnt& aP,
103                                    const Standard_Real aT,
104                                    gp_Dir& aDB,
105                                    gp_Pnt& aPOut,
106                                    Handle(BOPInt_Context)& theContext,
107                                    const GeomAdaptor_Surface& aGAS);
108
109 //=======================================================================
110 // function: MakeConnexityBlocks
111 // purpose: 
112 //=======================================================================
113   void BOPTools_AlgoTools::MakeConnexityBlocks (const TopoDS_Shape& theS,
114                                             const TopAbs_ShapeEnum theType1,
115                                             const TopAbs_ShapeEnum theType2,
116                                             BOPCol_ListOfShape& theLCB)
117 {
118   Standard_Integer  aNbF, aNbAdd, aNbAdd1, i;
119   BRep_Builder aBB;
120   TopoDS_Compound aC;
121   TopoDS_Iterator aIt;
122   TopExp_Explorer aExp;
123   BOPCol_MapOfShape aMP;
124   BOPCol_IndexedMapOfShape aMCB, aMAdd, aMAdd1;
125   BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
126   BOPCol_ListIteratorOfListOfShape aItLF;
127   //
128   // 1. aMEF
129   BOPTools::MapShapesAndAncestors(theS, theType1, theType2, aMEF);
130   //
131   // 2. aMCB
132   aIt.Initialize(theS);
133   for (; aIt.More(); aIt.Next()) {
134     const TopoDS_Shape& aF1=aIt.Value();
135     if (aMP.Contains(aF1)) {
136       continue;
137     }
138     //
139     aMCB.Clear();
140     aMAdd.Clear();
141     aMAdd.Add(aF1);
142     //
143     while(1) {
144       aMAdd1.Clear();
145       //
146       aNbAdd = aMAdd.Extent();
147       for (i=1; i<=aNbAdd; ++i) {
148         const TopoDS_Shape& aF=aMAdd(i);
149         //
150         aExp.Init(aF, theType1);
151         for (; aExp.More(); aExp.Next()) {
152           const TopoDS_Shape& aE=aExp.Current();
153           //
154           const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
155           aItLF.Initialize(aLF);
156           for (; aItLF.More(); aItLF.Next()) {
157             const TopoDS_Shape& aFx=aItLF.Value();
158             if (aFx.IsSame(aF)) {
159               continue;
160             }
161             if (aMCB.Contains(aFx)) {
162               continue;
163             }
164             aMAdd1.Add(aFx);
165           }
166         }//for (; aExp.More(); aExp.Next()){
167         aMCB.Add(aF);
168       }// for (i=1; i<=aNbAdd; ++i) {
169       //
170       aNbAdd1=aMAdd1.Extent();
171       if (!aNbAdd1) {
172         break;// ->make new CB from aMCB
173       }
174       //
175       aMAdd.Clear();
176       for (i=1; i<=aNbAdd1; ++i) {
177         const TopoDS_Shape& aFAdd = aMAdd1(i);
178         aMAdd.Add(aFAdd);
179       }
180     }//while(1) {
181     //
182     aNbF=aMCB.Extent();
183     if (aNbF) {
184       aBB.MakeCompound(aC);
185       //
186       for (i=1; i<=aNbF; ++i) {
187         const TopoDS_Shape& aF=aMCB(i);
188         aBB.Add(aC, aF);  
189         aMP.Add(aF);
190       }
191       theLCB.Append(aC);
192     }
193   }// for (; aIt.More(); aIt.Next()) 
194 }
195 //=======================================================================
196 // function: OrientFacesOnShell
197 // purpose: 
198 //=======================================================================
199   void BOPTools_AlgoTools::OrientFacesOnShell (TopoDS_Shape& aShell)
200 {
201   Standard_Boolean bIsProcessed1, bIsProcessed2;
202   Standard_Integer i, aNbE, aNbF, j;
203   TopAbs_Orientation anOrE1, anOrE2;
204   TopoDS_Face aF1x, aF2x;
205   TopoDS_Shape aShellNew;
206   BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
207   BOPCol_IndexedMapOfShape aProcessedFaces;
208   BRep_Builder aBB;
209   //
210   BOPTools_AlgoTools::MakeContainer(TopAbs_SHELL, aShellNew);
211   //
212   BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
213   aNbE=aEFMap.Extent();
214   // 
215   // One seam edge  in aEFMap contains  2 equivalent faces.
216   for (i=1; i<=aNbE; ++i) {
217     BOPCol_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
218     aNbF=aLF.Extent();
219     if (aNbF>1) {
220       BOPCol_ListOfShape aLFTmp;
221       BOPCol_IndexedMapOfShape aFM;
222       //
223       BOPCol_ListIteratorOfListOfShape anIt(aLF);
224       for (; anIt.More(); anIt.Next()) {
225         const TopoDS_Shape& aF=anIt.Value();
226         if (!aFM.Contains(aF)) {
227           aFM.Add(aF);
228           aLFTmp.Append(aF);
229         }
230       }
231       aLF.Clear();
232       aLF=aLFTmp;
233     }
234   }
235   //
236   // Do
237   for (i=1; i<=aNbE; ++i) {
238     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
239     if (BRep_Tool::Degenerated(aE)) {
240       continue;
241     }
242     //
243     const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
244     aNbF=aLF.Extent();
245     if (aNbF!=2) {
246       continue;
247     }
248     //
249     TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
250     TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
251     //    
252     bIsProcessed1=aProcessedFaces.Contains(aF1);
253     bIsProcessed2=aProcessedFaces.Contains(aF2);
254     if (bIsProcessed1 && bIsProcessed2) {
255       continue;
256     }
257     
258     if (!bIsProcessed1 && !bIsProcessed2) {
259       aProcessedFaces.Add(aF1);
260       aBB.Add(aShellNew, aF1);
261       bIsProcessed1=!bIsProcessed1;
262     }
263     //
264     aF1x=aF1;
265     if (bIsProcessed1) {
266       j=aProcessedFaces.FindIndex(aF1);
267       aF1x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
268     }
269     //
270     aF2x=aF2;
271     if (bIsProcessed2) {
272       j=aProcessedFaces.FindIndex(aF2);
273       aF2x=(*(TopoDS_Face*)(&aProcessedFaces.FindKey(j)));
274     }
275     //
276     anOrE1=Orientation(aE, aF1x); 
277     anOrE2=Orientation(aE, aF2x);
278     //
279     if (bIsProcessed1 && !bIsProcessed2) {
280       if (anOrE1==anOrE2) {
281         if (!BRep_Tool::IsClosed(aE, aF1) &&
282             !BRep_Tool::IsClosed(aE, aF2)) {
283           aF2.Reverse();
284         }
285       }
286       aProcessedFaces.Add(aF2);
287       aBB.Add(aShellNew, aF2);
288     }
289     else if (!bIsProcessed1 && bIsProcessed2) {
290       if (anOrE1==anOrE2) {
291         if (!BRep_Tool::IsClosed(aE, aF1) &&
292             !BRep_Tool::IsClosed(aE, aF2)) {
293           aF1.Reverse();
294         }
295       }
296       aProcessedFaces.Add(aF1);
297       aBB.Add(aShellNew, aF1);
298     }
299   }
300   //
301   //
302   for (i=1; i<=aNbE; ++i) {
303     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aEFMap.FindKey(i)));
304     if (BRep_Tool::Degenerated(aE)) {
305       continue;
306     }
307     //
308     const BOPCol_ListOfShape& aLF=aEFMap.FindFromIndex(i);
309     aNbF=aLF.Extent();
310     if (aNbF!=2) {
311       BOPCol_ListIteratorOfListOfShape anIt(aLF);
312       for(; anIt.More(); anIt.Next()) {
313         const TopoDS_Face& aF=(*(TopoDS_Face*)(&anIt.Value()));
314         if (!aProcessedFaces.Contains(aF)) {
315           aProcessedFaces.Add(aF);
316           aBB.Add(aShellNew, aF);
317         }
318       }
319     }
320   }
321   aShell=aShellNew;
322 }
323 //=======================================================================
324 //function : Orientation
325 //purpose  :
326 //=======================================================================
327   TopAbs_Orientation Orientation(const TopoDS_Edge& anE,
328                                  const TopoDS_Face& aF)
329 {
330   TopAbs_Orientation anOr=TopAbs_INTERNAL;
331
332   TopExp_Explorer anExp;
333   anExp.Init(aF, TopAbs_EDGE);
334   for (; anExp.More(); anExp.Next()) {
335     const TopoDS_Edge& anEF1=(*(TopoDS_Edge*)(&anExp.Current()));
336     if (anEF1.IsSame(anE)) {
337       anOr=anEF1.Orientation();
338       break;
339     }
340   }
341   return anOr;
342 }
343
344 ////////////
345
346
347 //=======================================================================
348 // function: MakeConnexityBlock.
349 // purpose: 
350 //=======================================================================
351   void BOPTools_AlgoTools::MakeConnexityBlock (BOPCol_ListOfShape& theLFIn,
352                                            BOPCol_IndexedMapOfShape& theMEAvoid,
353                                            BOPCol_ListOfShape& theLCB,
354                                            const Handle(NCollection_BaseAllocator)& theAllocator)
355 {
356   Standard_Integer  aNbF, aNbAdd1, aNbAdd, i;
357   TopExp_Explorer aExp;
358   BOPCol_ListIteratorOfListOfShape aIt;
359   //
360   BOPCol_IndexedMapOfShape aMCB(100, theAllocator);
361   BOPCol_IndexedMapOfShape aMAdd(100, theAllocator);
362   BOPCol_IndexedMapOfShape aMAdd1(100, theAllocator);
363   BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, theAllocator);
364   //
365   // 1. aMEF
366   aNbF=theLFIn.Extent();
367   aIt.Initialize(theLFIn);
368   for (; aIt.More(); aIt.Next()) {
369     const TopoDS_Shape& aF=aIt.Value();      
370     BOPTools::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
371   }
372   //
373   // 2. aMCB
374   const TopoDS_Shape& aF1=theLFIn.First();
375   aMAdd.Add(aF1);
376   //
377   while(1) {
378     aMAdd1.Clear();
379     aNbAdd = aMAdd.Extent();
380     for (i=1; i<=aNbAdd; ++i) {
381       const TopoDS_Shape& aF=aMAdd(i);
382       //
383       //aMAdd1.Clear();
384       aExp.Init(aF, TopAbs_EDGE);
385       for (; aExp.More(); aExp.Next()) {
386         const TopoDS_Shape& aE=aExp.Current();
387         if (theMEAvoid.Contains(aE)){
388           continue;
389         }
390         //
391         const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
392         aIt.Initialize(aLF);
393         for (; aIt.More(); aIt.Next()) {
394           const TopoDS_Shape& aFx=aIt.Value();
395           if (aFx.IsSame(aF)) {
396             continue;
397           }
398           if (aMCB.Contains(aFx)) {
399             continue;
400           }
401           aMAdd1.Add(aFx);
402         }
403       }//for (; aExp.More(); aExp.Next()){
404       aMCB.Add(aF);
405     }// for (i=1; i<=aNbAdd; ++i) {
406     //
407     aNbAdd1=aMAdd1.Extent();
408     if (!aNbAdd1) {
409       break;
410     }
411     //
412     aMAdd.Clear();
413     for (i=1; i<=aNbAdd1; ++i) {
414       const TopoDS_Shape& aFAdd=aMAdd1(i);
415       aMAdd.Add(aFAdd);
416     }
417     //
418   }//while(1) {
419   
420   //
421   aNbF=aMCB.Extent();
422   for (i=1; i<=aNbF; ++i) {
423     const TopoDS_Shape& aF=aMCB(i);
424     theLCB.Append(aF);
425   }
426 }
427 //=======================================================================
428 // function:  ComputeStateByOnePoint
429 // purpose: 
430 //=======================================================================
431   TopAbs_State BOPTools_AlgoTools::ComputeStateByOnePoint(const TopoDS_Shape& theS,
432                                                       const TopoDS_Solid& theRef,
433                                                       const Standard_Real theTol,
434                                                       Handle(BOPInt_Context)& theContext)
435 {
436   TopAbs_State aState;
437   TopAbs_ShapeEnum aType;
438   //
439   aState=TopAbs_UNKNOWN;
440   aType=theS.ShapeType();
441   if (aType==TopAbs_VERTEX) {
442     const TopoDS_Vertex& aV=(*(TopoDS_Vertex*)(&theS));
443     aState=BOPTools_AlgoTools::ComputeState(aV, theRef, theTol, theContext);
444   }
445   else if (aType==TopAbs_EDGE) {
446     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&theS));
447     aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
448   }
449   return aState;
450 }
451
452 //=======================================================================
453 // function:  ComputeState
454 // purpose: 
455 //=======================================================================
456   TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Face& theF,
457                                             const TopoDS_Solid& theRef,
458                                             const Standard_Real theTol,
459                                             BOPCol_IndexedMapOfShape& theBounds,
460                                             Handle(BOPInt_Context)& theContext)
461 {
462   TopAbs_State aState;
463   TopExp_Explorer aExp; 
464   TopoDS_Edge aE1;
465   gp_Pnt2d aP2D;
466   gp_Pnt aP3D; 
467   //
468   aState=TopAbs_UNKNOWN;
469   //
470   aExp.Init(theF, TopAbs_EDGE);
471   for (; aExp.More(); aExp.Next()) {
472     const TopoDS_Edge& aSE=(*(TopoDS_Edge*)(&aExp.Current()));
473     if (BRep_Tool::Degenerated(aSE)) {
474       continue;
475     }
476     //
477     if (!theBounds.Contains(aSE)) {
478       const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aSE));
479       aState=BOPTools_AlgoTools::ComputeState(aE, theRef, theTol, theContext);
480       return aState;
481     }
482     if (aE1.IsNull()) {
483       aE1=(*(TopoDS_Edge*)(&aSE));
484     }
485   }
486   // !!<- process edges that are all on theRef
487   if (!aE1.IsNull()) {
488     BOPTools_AlgoTools3D::PointNearEdge(aE1, theF, aP2D, aP3D, theContext);
489     aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
490   }
491   //
492   return aState;
493 }
494 //=======================================================================
495 // function:  ComputeState
496 // purpose: 
497 //=======================================================================
498   TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Vertex& theV,
499                                             const TopoDS_Solid& theRef,
500                                             const Standard_Real theTol,
501                                             Handle(BOPInt_Context)& theContext)
502 {
503   TopAbs_State aState;
504   gp_Pnt aP3D; 
505   //
506   aP3D=BRep_Tool::Pnt(theV);
507   aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
508   return aState;
509 }
510 //=======================================================================
511 // function:  ComputeState
512 // purpose: 
513 //=======================================================================
514   TopAbs_State BOPTools_AlgoTools::ComputeState(const TopoDS_Edge& theE,
515                                             const TopoDS_Solid& theRef,
516                                             const Standard_Real theTol,
517                                             Handle(BOPInt_Context)& theContext)
518 {
519   Standard_Real aT1, aT2, aT = 0.;
520   TopAbs_State aState;
521   Handle(Geom_Curve) aC3D;
522   gp_Pnt aP3D; 
523   //
524   aC3D = BRep_Tool::Curve(theE, aT1, aT2);
525   //
526   if(aC3D.IsNull()) {
527     //it means that we are in degenerated edge
528     const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
529     if(aV.IsNull()){
530       return TopAbs_UNKNOWN;
531     }
532     aP3D=BRep_Tool::Pnt(aV);
533   }
534   else {//usual case
535     Standard_Boolean bF2Inf, bL2Inf;
536     Standard_Real dT=10.;
537     //
538     bF2Inf = Precision::IsNegativeInfinite(aT1);
539     bL2Inf = Precision::IsPositiveInfinite(aT2);
540     //
541     if (bF2Inf && !bL2Inf) {
542       aT=aT2-dT;
543     }
544     else if (!bF2Inf && bL2Inf) {
545       aT=aT1+dT;
546     }
547     else if (bF2Inf && bL2Inf) {
548       aT=0.;
549     }
550     else {
551       aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
552     }
553     aC3D->D0(aT, aP3D);
554   }
555   //
556   aState=BOPTools_AlgoTools::ComputeState(aP3D, theRef, theTol, theContext);
557   //
558   return aState;
559 }
560 //=======================================================================
561 // function:  ComputeState
562 // purpose: 
563 //=======================================================================
564   TopAbs_State BOPTools_AlgoTools::ComputeState(const gp_Pnt& theP,
565                                             const TopoDS_Solid& theRef,
566                                             const Standard_Real theTol,
567                                             Handle(BOPInt_Context)& theContext)
568 {
569   TopAbs_State aState;
570   //
571   BRepClass3d_SolidClassifier& aSC=theContext->SolidClassifier(theRef);
572   aSC.Perform(theP, theTol);
573   //
574   aState=aSC.State();
575   //
576   return aState;
577 }
578 //=======================================================================
579 //function : IsInternalFace
580 //purpose  : 
581 //=======================================================================
582   Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
583                                                       const TopoDS_Solid& theSolid,
584                                                       BOPCol_IndexedDataMapOfShapeListOfShape& theMEF,
585                                                       const Standard_Real theTol,
586                                                       Handle(BOPInt_Context)& theContext)
587 {
588   Standard_Boolean bRet, bDegenerated;
589   Standard_Integer aNbF;
590   TopAbs_Orientation aOr;
591   TopoDS_Edge aEL;
592   TopExp_Explorer aExp;
593   BOPCol_ListIteratorOfListOfShape aItF;
594   //
595   bRet=Standard_False;
596   //
597   // 1 Try to find an edge from theFace in theMEF
598   aExp.Init(theFace, TopAbs_EDGE);
599   for(; aExp.More(); aExp.Next()) {
600     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
601     if (!theMEF.Contains(aE)) {
602       continue;
603     }
604     //
605     aOr=aE.Orientation();
606     if (aOr==TopAbs_INTERNAL) {
607       continue;
608     }
609     bDegenerated=BRep_Tool::Degenerated(aE);
610     if (bDegenerated){
611       continue;
612     }
613     // aE
614     BOPCol_ListOfShape& aLF=theMEF.ChangeFromKey(aE);
615     aNbF=aLF.Extent();
616     if (!aNbF) {
617       return bRet; // it can not be so
618     }
619     else if (aNbF==1) {
620       // aE is internal edge on aLF.First()
621       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
622       bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF1, theContext);
623       return bRet;
624     }
625     else if (aNbF==2) {
626       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
627       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
628       //
629       if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
630         // treat as it was for 1 face
631         bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aF1, aF2, theContext);
632         return bRet;
633       }
634     }
635     if (aNbF%2) {
636       return bRet; // it can not be so
637     }
638     else { // aNbF=2,4,6,8,...
639       bRet=BOPTools_AlgoTools::IsInternalFace(theFace, aE, aLF, theContext);
640       return bRet;
641     }
642   }//for(; aExp.More(); aExp.Next()) {
643   //
644   //========================================
645   // 2. Classify face using classifier
646   //
647   TopAbs_State aState;
648   BOPCol_IndexedMapOfShape aBounds;
649   //
650   aState=BOPTools_AlgoTools::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
651   bRet=(aState==TopAbs_IN);
652   //
653   return bRet;
654 }
655 //=======================================================================
656 //function : IsInternalFace
657 //purpose  : 
658 //=======================================================================
659   Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
660                                                       const TopoDS_Edge& theEdge,
661                                                       BOPCol_ListOfShape& theLF,
662                                                       Handle(BOPInt_Context)& theContext)
663 {
664   Standard_Boolean bRet;
665   Standard_Boolean aNbF;
666   //
667   bRet=Standard_False;
668   //
669   aNbF=theLF.Extent();
670   if (aNbF==2) {
671     const TopoDS_Face& aF1=(*(TopoDS_Face*)(&theLF.First()));
672     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&theLF.Last()));
673     bRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
674     return bRet;
675   }
676   //
677   else {
678     BOPTools_ListOfCoupleOfShape aLCFF;
679     BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
680     //
681     FindFacePairs(theEdge, theLF, aLCFF, theContext);
682     //
683     aIt.Initialize(aLCFF);
684     for (; aIt.More(); aIt.Next()) {
685       BOPTools_CoupleOfShape& aCSFF=aIt.ChangeValue();
686       //
687       const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aCSFF.Shape1()));
688       const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCSFF.Shape2()));
689       bRet=BOPTools_AlgoTools::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
690       if (bRet) {
691         return bRet;
692       }
693     }
694   }
695   return bRet;
696 }
697 //=======================================================================
698 //function : IsInternalFace
699 //purpose  : 
700 //=======================================================================
701   Standard_Boolean BOPTools_AlgoTools::IsInternalFace(const TopoDS_Face& theFace,
702                                                       const TopoDS_Edge& theEdge,
703                                                       const TopoDS_Face& theFace1,
704                                                       const TopoDS_Face& theFace2,
705                                                       Handle(BOPInt_Context)& theContext)
706 {
707   Standard_Boolean bRet;
708   TopoDS_Edge aE1, aE2;
709   TopoDS_Face aFOff;
710   BOPTools_ListOfCoupleOfShape theLCSOff;
711   BOPTools_CoupleOfShape aCS1, aCS2;
712   //
713   BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace1, aE1);
714   if (aE1.Orientation()==TopAbs_INTERNAL) {
715     aE2=aE1;
716     aE1.Orientation(TopAbs_FORWARD);
717     aE2.Orientation(TopAbs_REVERSED);
718   }
719   else if (theFace1==theFace2) {
720     aE2=aE1;
721     aE1.Orientation(TopAbs_FORWARD);
722     aE2.Orientation(TopAbs_REVERSED);
723   }
724   else {
725     BOPTools_AlgoTools::GetEdgeOnFace(theEdge, theFace2, aE2);
726   }
727   //
728   aCS1.SetShape1(theEdge);
729   aCS1.SetShape2(theFace);
730   theLCSOff.Append(aCS1);
731   //
732   aCS2.SetShape1(aE2);
733   aCS2.SetShape2(theFace2);
734   theLCSOff.Append(aCS2);
735   //
736   GetFaceOff(aE1, theFace1, theLCSOff, aFOff, theContext);
737   //
738   bRet = theFace.IsEqual(aFOff);
739   return bRet;
740 }
741 //=======================================================================
742 //function : GetFaceOff
743 //purpose  : 
744 //=======================================================================
745   void BOPTools_AlgoTools::GetFaceOff(const TopoDS_Edge& theE1,
746                                       const TopoDS_Face& theF1,
747                                       BOPTools_ListOfCoupleOfShape& theLCSOff,
748                                       TopoDS_Face& theFOff,
749                                       Handle(BOPInt_Context)& theContext)
750 {
751   Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
752   gp_Pnt aPn1, aPn2, aPx;
753   gp_Dir aDN1, aDN2, aDBF, aDBF2, aDTF;
754   gp_Vec aVTgt;
755   TopAbs_Orientation aOr;
756   Handle(Geom_Curve)aC3D;
757   BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
758   //
759   aAngleMin=100.;
760   aTwoPI=M_PI+M_PI;
761   aC3D =BRep_Tool::Curve(theE1, aT1, aT2);
762   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
763   aC3D->D0(aT, aPx);
764   //
765   BOPTools_AlgoTools2D::EdgeTangent(theE1, aT, aVTgt);
766   gp_Dir aDTgt(aVTgt), aDTgt2;
767   aOr = theE1.Orientation();
768   //
769   GetFaceDir(theE1, theF1, aPx, aT, aDTgt, aDN1, aDBF, theContext);
770   //
771   aDTF=aDN1^aDBF;
772   //
773   aIt.Initialize(theLCSOff);
774   for (; aIt.More(); aIt.Next()) {
775     const BOPTools_CoupleOfShape& aCS=aIt.Value();
776     const TopoDS_Edge& aE2=(*(TopoDS_Edge*)(&aCS.Shape1()));
777     const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aCS.Shape2()));
778     //
779     aDTgt2 = (aE2.Orientation()==aOr) ? aDTgt : aDTgt.Reversed();
780     GetFaceDir(aE2, aF2, aPx, aT, aDTgt2, aDN2, aDBF2, theContext);
781     //Angle
782     aAngle=AngleWithRef(aDBF, aDBF2, aDTF);
783     //
784     if(aAngle<0.) {
785       aAngle=aTwoPI+aAngle;
786     }
787     //
788     if (aAngle<Precision::Angular()) {
789       if (aF2==theF1) {
790         aAngle=M_PI;
791       }
792       else if (aF2.IsSame(theF1)) {
793         aAngle=aTwoPI;
794       }
795     }
796     //
797     if (aAngle<aAngleMin){
798       aAngleMin=aAngle;
799       theFOff=aF2;
800     }
801   }
802 }
803 //=======================================================================
804 //function : GetEdgeOff
805 //purpose  : 
806 //=======================================================================
807   Standard_Boolean BOPTools_AlgoTools::GetEdgeOff(const TopoDS_Edge& theE1,
808                                               const TopoDS_Face& theF2,
809                                               TopoDS_Edge& theE2)
810 {
811   Standard_Boolean bFound;
812   TopAbs_Orientation aOr1, aOr1C, aOr2;
813   TopExp_Explorer anExp;
814   //
815   bFound=Standard_False;
816   aOr1=theE1.Orientation();
817   aOr1C=TopAbs::Reverse(aOr1);
818   //
819   anExp.Init(theF2, TopAbs_EDGE);
820   for (; anExp.More(); anExp.Next()) {
821     const TopoDS_Edge& aEF2=(*(TopoDS_Edge*)(&anExp.Current()));
822     if (aEF2.IsSame(theE1)) {
823       aOr2=aEF2.Orientation();
824       if (aOr2==aOr1C) {
825         theE2=aEF2;
826         bFound=!bFound;
827         return bFound;
828       }
829     }
830   }
831   return bFound;
832 }
833
834 //=======================================================================
835 //function : AreFacesSameDomain
836 //purpose  : 
837 //=======================================================================
838   Standard_Boolean BOPTools_AlgoTools::AreFacesSameDomain(const TopoDS_Face& theF1,
839                                                           const TopoDS_Face& theF2,
840                                                           Handle(BOPInt_Context)& theContext)
841 {
842   Standard_Boolean bFlag;
843   Standard_Integer iP;
844   Standard_Real aTolF1, aTolF2, aTol;
845   gp_Pnt2d aP2D;
846   gp_Pnt aP;
847   TopoDS_Face aF1, aF2;
848   TopoDS_Edge aE1;
849   TopExp_Explorer aExp;
850   //
851   bFlag=Standard_False;
852   //
853   aF1=theF1;
854   aF1.Orientation(TopAbs_FORWARD);
855   aF2=theF2;
856   aF2.Orientation(TopAbs_FORWARD);
857   //
858   aTolF1=BRep_Tool::Tolerance(aF1);
859   // 1
860   iP=0;
861   aExp.Init(aF1, TopAbs_EDGE);
862   for (; aExp.More(); aExp.Next()) {
863     aE1=(*(TopoDS_Edge*)(&aExp.Current()));
864     if (!BRep_Tool::Degenerated(aE1)) {
865       iP=1;
866       //break;
867       Standard_Real aTolE = BRep_Tool::Tolerance(aE1);
868       aTolF1 = (aTolE > aTolF1) ? aTolE : aTolF1;
869     }
870   }
871   if (!iP) {
872     return bFlag;
873   }
874   //
875   // 2
876   aTolF2=BRep_Tool::Tolerance(aF2);
877   aTol=aTolF1+aTolF2;
878   //
879   BOPTools_AlgoTools3D::PointNearEdge(aE1, aF1, aP2D, aP, theContext);
880   bFlag=theContext->IsValidPointForFace(aP, aF2, aTol);
881   //
882   return bFlag;
883 }
884
885 //=======================================================================
886 //function : CheckSameGeom
887 //purpose  : 
888 //=======================================================================
889   Standard_Boolean BOPTools_AlgoTools::CheckSameGeom(const TopoDS_Face& theF1,
890                                                  const TopoDS_Face& theF2,
891                                                  Handle(BOPInt_Context)& theContext)
892 {
893   Standard_Boolean bRet;
894   Standard_Real aTolF1, aTolF2, aTol;
895   gp_Pnt2d aP2D;
896   gp_Pnt aP;
897   TopExp_Explorer aExp;
898   //
899   bRet=Standard_False;
900   aExp.Init(theF1, TopAbs_EDGE);
901   for (; aExp.More(); aExp.Next()) {
902     const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
903     if (!BRep_Tool::Degenerated(aE)) {
904       aTolF1=BRep_Tool::Tolerance(theF1);
905       aTolF2=BRep_Tool::Tolerance(theF2);
906       aTol=aTolF1+aTolF2;
907       BOPTools_AlgoTools3D::PointNearEdge(aE, theF1, aP2D, aP, theContext);
908       bRet=theContext->IsValidPointForFace(aP, theF2, aTol);
909       break;
910     }
911   }
912   return bRet;
913 }
914 //=======================================================================
915 // function: Sense
916 // purpose: 
917 //=======================================================================
918   Standard_Integer BOPTools_AlgoTools::Sense (const TopoDS_Face& theF1,
919                                           const TopoDS_Face& theF2)
920 {
921   Standard_Integer iSense=0;
922   gp_Dir aDNF1, aDNF2;
923   TopoDS_Edge aE1, aE2;
924   TopExp_Explorer aExp;
925   //
926   aExp.Init(theF1, TopAbs_EDGE);
927   for (; aExp.More(); aExp.Next()) {
928     aE1=(*(TopoDS_Edge*)(&aExp.Current()));
929     if (!BRep_Tool::Degenerated(aE1)) {
930       if (!BRep_Tool::IsClosed(aE1, theF1)) {
931         break;
932       }
933     }
934   }
935   //
936   aExp.Init(theF2, TopAbs_EDGE);
937   for (; aExp.More(); aExp.Next()) {
938     aE2=(*(TopoDS_Edge*)(&aExp.Current()));
939     if (!BRep_Tool::Degenerated(aE2)) {
940       if (!BRep_Tool::IsClosed(aE2, theF2)) {
941         if (aE2.IsSame(aE1)) {
942           iSense=1;
943           break;
944         }
945       }
946     }
947   }
948   //
949   if (!iSense) {
950     return iSense;
951   }
952   //
953   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1);
954   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2);
955   //
956   iSense=BOPTools_AlgoTools3D::SenseFlag(aDNF1, aDNF2);
957   //
958   return iSense;
959 }
960 //=======================================================================
961 // function: IsSplitToReverse
962 // purpose: 
963 //=======================================================================
964   Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Shape& theSp,
965                                                     const TopoDS_Shape& theSr,
966                                                     Handle(BOPInt_Context)& theContext)
967 {
968   Standard_Boolean bRet;
969   TopAbs_ShapeEnum aType;
970   //
971   bRet=Standard_False;
972   //
973   aType=theSp.ShapeType();
974   switch (aType) {
975     case TopAbs_EDGE: {
976       const TopoDS_Edge& aESp=(*(TopoDS_Edge*)(&theSp));
977       const TopoDS_Edge& aESr=(*(TopoDS_Edge*)(&theSr));
978       bRet=BOPTools_AlgoTools::IsSplitToReverse(aESp, aESr, theContext);
979     }
980       break;
981       //
982     case TopAbs_FACE: {
983       const TopoDS_Face& aFSp=(*(TopoDS_Face*)(&theSp));
984       const TopoDS_Face& aFSr=(*(TopoDS_Face*)(&theSr));
985       bRet=BOPTools_AlgoTools::IsSplitToReverse(aFSp, aFSr, theContext);
986     }
987       break;
988       //
989     default:
990       break;
991   }
992   return bRet;
993 }
994 //=======================================================================
995 //function :IsSplitToReverse
996 //purpose  : 
997 //=======================================================================
998   Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Face& theFSp,
999                                                     const TopoDS_Face& theFSr,
1000                                                     Handle(BOPInt_Context)& theContext)
1001 {
1002   Standard_Boolean bRet, bFound, bInFace;
1003   Standard_Real aT1, aT2, aT, aU, aV, aScPr;
1004   gp_Pnt aPFSp, aPFSr;
1005   gp_Dir aDNFSp;
1006   gp_Vec aD1U, aD1V;
1007   Handle(Geom_Surface) aSr, aSp;
1008   TopAbs_Orientation aOrSr, aOrSp;
1009   TopExp_Explorer anExp;
1010   TopoDS_Edge aESp;
1011   //
1012   bRet=Standard_False;
1013   //
1014   aSr=BRep_Tool::Surface(theFSr);
1015   aSp=BRep_Tool::Surface(theFSp);
1016   if (aSr==aSp) {
1017     aOrSr=theFSr.Orientation();
1018     aOrSp=theFSp.Orientation();
1019     bRet=(aOrSr!=aOrSp);
1020     return bRet;
1021   }
1022   //
1023   bFound=Standard_False;
1024   anExp.Init(theFSp, TopAbs_EDGE);
1025   for (; anExp.More(); anExp.Next()) {
1026     aESp=(*(TopoDS_Edge*)(&anExp.Current()));
1027     if (!BRep_Tool::Degenerated(aESp)) {
1028       if (!BRep_Tool::IsClosed(aESp, theFSp)) {
1029         bFound=!bFound;
1030         break;
1031       }
1032     }
1033   }
1034   if (!bFound) {
1035     Standard_Boolean bFlag;
1036     Standard_Integer iErr;
1037     gp_Pnt2d aP2DFSp;
1038     //
1039     iErr=BOPTools_AlgoTools3D::PointInFace(theFSp, aPFSp, aP2DFSp, theContext);
1040     if (iErr) {
1041       return bRet;
1042     }
1043     //
1044     aP2DFSp.Coord(aU, aV);
1045     bFlag=BOPTools_AlgoTools3D::GetNormalToSurface(aSp, aU, aV, aDNFSp);
1046     if (!bFlag) {
1047       return bRet;
1048     }
1049   }
1050   else {
1051     BRep_Tool::Range(aESp, aT1, aT2);
1052     aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
1053     BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp, theContext);
1054   }
1055   //
1056   // Parts of theContext->ComputeVS(..) 
1057   GeomAPI_ProjectPointOnSurf& aProjector=theContext->ProjPS(theFSr);
1058   aProjector.Perform(aPFSp);
1059   if (!aProjector.IsDone()) {
1060     return bRet;
1061   }
1062   //
1063   aProjector.LowerDistanceParameters(aU, aV);
1064   gp_Pnt2d aP2D(aU, aV);
1065   bInFace=theContext->IsPointInFace (theFSr, aP2D);
1066   if (!bInFace) {
1067     return bRet;
1068   }
1069   //
1070   aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
1071   gp_Dir aDD1U(aD1U); 
1072   gp_Dir aDD1V(aD1V);
1073   gp_Dir aDNFSr=aDD1U^aDD1V; 
1074   if (theFSr.Orientation()==TopAbs_REVERSED){
1075     aDNFSr.Reverse();
1076   }
1077   //
1078   aScPr=aDNFSp*aDNFSr;
1079   bRet=(aScPr<0.);
1080   //
1081   return bRet;
1082 }
1083 //=======================================================================
1084 //function :IsSplitToReverse
1085 //purpose  : 
1086 //=======================================================================
1087   Standard_Boolean BOPTools_AlgoTools::IsSplitToReverse(const TopoDS_Edge& aEF1,
1088                                                     const TopoDS_Edge& aEF2,
1089                                                     Handle(BOPInt_Context)& theContext)
1090 {
1091   Standard_Boolean bRet, bIsDegenerated;
1092   //
1093   bRet=Standard_False;
1094   bIsDegenerated=(BRep_Tool::Degenerated(aEF1) || 
1095                   BRep_Tool::Degenerated(aEF2));
1096   if (bIsDegenerated) {
1097     return bRet;
1098   }
1099   //
1100   Standard_Real a, b;
1101   TopAbs_Orientation aOrE, aOrSp;
1102   Handle(Geom_Curve)aC1, aC2;
1103   //
1104   aC2=BRep_Tool::Curve(aEF2, a, b);
1105   aC1=BRep_Tool::Curve(aEF1, a, b);
1106   //
1107   if (aC1==aC2) {
1108     aOrE=aEF2.Orientation();
1109     aOrSp=aEF1.Orientation();
1110     bRet=(aOrE!=aOrSp);
1111     return bRet;
1112   }
1113   //
1114   Standard_Real aT1, aT2, aScPr;
1115   gp_Vec aV1, aV2;
1116   gp_Pnt aP;
1117   //
1118   aT1=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
1119   aC1->D0(aT1, aP);
1120   BOPTools_AlgoTools2D::EdgeTangent(aEF1, aT1, aV1);
1121   gp_Dir aDT1(aV1);
1122   //
1123   theContext->ProjectPointOnEdge(aP, aEF2, aT2);
1124   //
1125   BOPTools_AlgoTools2D::EdgeTangent(aEF2, aT2, aV2);
1126   gp_Dir aDT2(aV2);
1127   //
1128   aScPr=aDT1*aDT2;
1129   bRet=(aScPr<0.);
1130   //
1131   return bRet;
1132 }
1133
1134 //=======================================================================
1135 //function : IsHole
1136 //purpose  : 
1137 //=======================================================================
1138   Standard_Boolean BOPTools_AlgoTools::IsHole(const TopoDS_Shape& aW,
1139                                           const TopoDS_Shape& aFace)
1140 {
1141   Standard_Boolean bIsHole;
1142   Standard_Integer i, aNbS;
1143   Standard_Real aT1, aT2, aS;
1144   Standard_Real aU1, aU2, aU, dU;
1145   Standard_Real aX1, aY1, aX0, aY0;
1146   TopAbs_Orientation aOr;
1147   
1148   gp_Pnt2d aP2D0, aP2D1;
1149   Handle(Geom2d_Curve) aC2D;
1150   TopoDS_Face aF, aFF;
1151   TopoDS_Iterator aItW;
1152   //
1153   bIsHole=Standard_False;
1154   //
1155   aF=(*(TopoDS_Face *)(&aFace));
1156   aFF=aF;
1157   aFF.Orientation(TopAbs_FORWARD);
1158   //
1159   aS=0.;
1160   aItW.Initialize(aW);
1161   for (; aItW.More(); aItW.Next()) { 
1162     const TopoDS_Edge& aE=(*(TopoDS_Edge *)(&aItW.Value()));
1163     aOr=aE.Orientation();
1164     if (!(aOr==TopAbs_FORWARD || 
1165           aOr==TopAbs_REVERSED)) {
1166       continue;
1167     }
1168     //
1169     aC2D=BRep_Tool::CurveOnSurface(aE, aFF, aT1, aT2);
1170     if (aC2D.IsNull()) {
1171       break; //xx
1172     }
1173     //
1174     BRepAdaptor_Curve2d aBAC2D(aE, aFF);
1175     aNbS=Geom2dInt_Geom2dCurveTool::NbSamples(aBAC2D);
1176     if (aNbS>2) {
1177       aNbS*=4;
1178     }
1179     //
1180     dU=(aT2-aT1)/(Standard_Real)(aNbS-1);
1181     aU =aT1;
1182     aU1=aT1;
1183     aU2=aT2;
1184     if (aOr==TopAbs_REVERSED) {
1185       aU =aT2;
1186       aU1=aT2;
1187       aU2=aT1;
1188       dU=-dU;
1189     }
1190     //
1191     aC2D->D0(aU, aP2D0);
1192     for(i=2; i<=aNbS; i++) {
1193       aU=aU1+(i-1)*dU;
1194       aC2D->D0(aU, aP2D1);
1195       aP2D0.Coord(aX0, aY0);
1196       aP2D1.Coord(aX1, aY1);
1197       //
1198       aS=aS+(aY0+aY1)*(aX1-aX0); 
1199       //
1200       aP2D0=aP2D1;
1201     }
1202   }//for (; aItW.More(); aItW.Next()) { 
1203   bIsHole=(aS>0.);
1204   return bIsHole;
1205 }
1206
1207 //=======================================================================
1208 // function: MakeContainer
1209 // purpose: 
1210 //=======================================================================
1211   void BOPTools_AlgoTools::MakeContainer(const TopAbs_ShapeEnum theType,
1212                                      TopoDS_Shape& theC)
1213 {
1214   BRep_Builder aBB;
1215   //
1216   switch(theType) {
1217     case TopAbs_COMPOUND:{
1218       TopoDS_Compound aC;
1219       aBB.MakeCompound(aC);
1220       theC=aC;
1221     }
1222       break;
1223       //
1224     case TopAbs_COMPSOLID:{
1225       TopoDS_CompSolid aCS;
1226       aBB.MakeCompSolid(aCS);
1227       theC=aCS;
1228     }
1229       break;
1230       //
1231     case TopAbs_SOLID:{
1232       TopoDS_Solid aSolid;
1233       aBB.MakeSolid(aSolid);
1234       theC=aSolid;
1235     }  
1236       break;
1237       //
1238       //
1239     case TopAbs_SHELL:{
1240       TopoDS_Shell aShell;
1241       aBB.MakeShell(aShell);
1242       theC=aShell;
1243     }  
1244       break;
1245       //
1246     case TopAbs_WIRE: {
1247       TopoDS_Wire aWire;
1248       aBB.MakeWire(aWire);
1249       theC=aWire;
1250     }
1251       break;
1252       //
1253     default:
1254       break;
1255   }
1256 }
1257 //=======================================================================
1258 // function: MakePCurve
1259 // purpose: 
1260 //=======================================================================
1261   void  BOPTools_AlgoTools::MakePCurve(const TopoDS_Edge& aE,
1262                                        const TopoDS_Face& aF1,
1263                                        const TopoDS_Face& aF2,
1264                                        const IntTools_Curve& aIC,
1265                                        const Standard_Boolean bPC1,
1266                                        const Standard_Boolean bPC2)
1267
1268 {
1269   Standard_Integer i;
1270   Standard_Real aTolE, aT1, aT2, aOutFirst, aOutLast, aOutTol;
1271   Handle(Geom2d_Curve) aC2D, aC2DA, aC2Dx1;
1272   TopoDS_Face aFFWD; 
1273   BRep_Builder aBB;
1274   Standard_Boolean bPC;
1275   //
1276   aTolE=BRep_Tool::Tolerance(aE);
1277   //
1278   const Handle(Geom_Curve)& aC3DE=BRep_Tool::Curve(aE, aT1, aT2);
1279   Handle(Geom_TrimmedCurve)aC3DETrim=new Geom_TrimmedCurve(aC3DE, aT1, aT2);
1280   //
1281   for (i=0; i<2; ++i) {
1282     bPC = !i ? bPC1 : bPC2;
1283     if (!bPC) {
1284       continue;
1285     }
1286     //
1287     if (!i) {
1288       aFFWD=aF1;
1289       aC2Dx1=aIC.FirstCurve2d();
1290     }
1291     else {
1292       aFFWD=aF2;
1293       aC2Dx1=aIC.SecondCurve2d();
1294     }
1295     //
1296     aFFWD.Orientation(TopAbs_FORWARD);
1297     //
1298     aC2D=aC2Dx1;
1299     if (aC2D.IsNull()) { 
1300       BOPTools_AlgoTools2D::BuildPCurveForEdgeOnFace(aE, aFFWD);
1301       BOPTools_AlgoTools2D::CurveOnSurface(aE, aFFWD, aC2D, 
1302                                        aOutFirst, aOutLast, 
1303                                        aOutTol);
1304       }
1305     //
1306     if (aC3DE->IsPeriodic()) {
1307       BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aT1, aT2,  aC2D, aC2DA); 
1308     }
1309     else {
1310       BOPTools_AlgoTools2D::AdjustPCurveOnFace(aFFWD, aC3DETrim, aC2D, aC2DA); 
1311     }
1312     //
1313     aBB.UpdateEdge(aE, aC2DA, aFFWD, aTolE);
1314     //BRepLib::SameParameter(aE);
1315   }
1316   BRepLib::SameParameter(aE);
1317 }
1318 //=======================================================================
1319 // function: MakeEdge
1320 // purpose: 
1321 //=======================================================================
1322   void  BOPTools_AlgoTools::MakeEdge(const IntTools_Curve& theIC,
1323                                  const TopoDS_Vertex& theV1,
1324                                  const Standard_Real theT1,
1325                                  const TopoDS_Vertex& theV2,
1326                                  const Standard_Real theT2,
1327                                  const Standard_Real theTolR3D,
1328                                  TopoDS_Edge& theE)
1329 {
1330   Standard_Real aTolV;
1331   BRep_Builder aBB;
1332   //
1333   BOPTools_AlgoTools::MakeSectEdge (theIC, theV1, theT1, theV2, theT2, theE);
1334   //
1335   aBB.UpdateEdge(theE, theTolR3D);
1336   //
1337   aTolV=BRep_Tool::Tolerance(theV1);
1338   if (aTolV<theTolR3D) {
1339     aBB.UpdateVertex(theV1, theTolR3D);
1340   }
1341   //
1342   aTolV=BRep_Tool::Tolerance(theV2);
1343   if (aTolV<theTolR3D) {
1344     aBB.UpdateVertex(theV2, theTolR3D);
1345   }
1346 }
1347 //=======================================================================
1348 // function: ComputeVV
1349 // purpose: 
1350 //=======================================================================
1351   Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1, 
1352                                              const gp_Pnt& aP2,
1353                                              const Standard_Real aTolP2)
1354 {
1355   Standard_Real aTolV1, aTolSum, aTolSum2, aD2;
1356   gp_Pnt aP1;
1357   //
1358   aTolV1=BRep_Tool::Tolerance(aV1);
1359   
1360   aTolSum=aTolV1+aTolP2;
1361   aTolSum2=aTolSum*aTolSum;
1362   //
1363   aP1=BRep_Tool::Pnt(aV1);
1364   //
1365   aD2=aP1.SquareDistance(aP2);
1366   if (aD2>aTolSum2) {
1367     return 1;
1368   }
1369   return 0;
1370
1371 //=======================================================================
1372 // function: ComputeVV
1373 // purpose: 
1374 //=======================================================================
1375   Standard_Integer BOPTools_AlgoTools::ComputeVV(const TopoDS_Vertex& aV1, 
1376                                              const TopoDS_Vertex& aV2)
1377 {
1378   Standard_Real aTolV1, aTolV2, aTolSum, aTolSum2, aD2;
1379   gp_Pnt aP1, aP2;
1380   //
1381   aTolV1=BRep_Tool::Tolerance(aV1);
1382   aTolV2=BRep_Tool::Tolerance(aV2);
1383   aTolSum=aTolV1+aTolV2;
1384   aTolSum2=aTolSum*aTolSum;
1385   //
1386   aP1=BRep_Tool::Pnt(aV1);
1387   aP2=BRep_Tool::Pnt(aV2);
1388   //
1389   aD2=aP1.SquareDistance(aP2);
1390   if (aD2>aTolSum2) {
1391     return 1;
1392   }
1393   return 0;
1394 }
1395 //=======================================================================
1396 // function: MakeVertex
1397 // purpose : 
1398 //=======================================================================
1399   void BOPTools_AlgoTools::MakeVertex(BOPCol_ListOfShape& aLV,
1400                                   TopoDS_Vertex& aVnew)
1401 {
1402   Standard_Integer aNb;
1403   Standard_Real aTi, aDi, aDmax;
1404   gp_Pnt aPi, aP;
1405   gp_XYZ aXYZ(0.,0.,0.), aXYZi;
1406   BOPCol_ListIteratorOfListOfShape aIt;
1407   //
1408   aNb=aLV.Extent();
1409   if (aNb) {
1410     aIt.Initialize(aLV);
1411     for (; aIt.More(); aIt.Next()) {
1412       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1413       aPi=BRep_Tool::Pnt(aVi);
1414       aXYZi=aPi.XYZ();
1415       aXYZ=aXYZ+aXYZi;
1416     }
1417     //
1418     aXYZ.Divide((Standard_Real)aNb);
1419     aP.SetXYZ(aXYZ);
1420     //
1421     aDmax=-1.;
1422     aIt.Initialize(aLV);
1423     for (; aIt.More(); aIt.Next()) {
1424       TopoDS_Vertex& aVi=*((TopoDS_Vertex*)(&aIt.Value()));
1425       aPi=BRep_Tool::Pnt(aVi);
1426       aTi=BRep_Tool::Tolerance(aVi);
1427       aDi=aP.SquareDistance(aPi);
1428       aDi=fsqrt(aDi);
1429       aDi=aDi+aTi;
1430       if (aDi > aDmax) {
1431         aDmax=aDi;
1432       }
1433     }
1434     //
1435     BRep_Builder aBB;
1436     aBB.MakeVertex (aVnew, aP, aDmax);
1437   }
1438 }
1439 //=======================================================================
1440 //function : GetEdgeOnFace
1441 //purpose  : 
1442 //=======================================================================
1443   Standard_Boolean BOPTools_AlgoTools::GetEdgeOnFace(const TopoDS_Edge& theE1,
1444                                                  const TopoDS_Face& theF2,
1445                                                  TopoDS_Edge& theE2)
1446 {
1447   Standard_Boolean bFound;
1448   TopoDS_Iterator aItF, aItW;
1449   //
1450   bFound=Standard_False;
1451   //
1452   aItF.Initialize(theF2);
1453   for (; aItF.More(); aItF.Next()) {
1454     const TopoDS_Shape& aW=aItF.Value();
1455     aItW.Initialize(aW);
1456     for (; aItW.More(); aItW.Next()) {
1457       const TopoDS_Shape& aE=aItW.Value();
1458       if (aE.IsSame(theE1)) {
1459         theE2=(*(TopoDS_Edge*)(&aE));
1460         bFound=!bFound;
1461         return bFound;
1462       }
1463     }
1464   }
1465   return bFound;
1466 }
1467 //=======================================================================
1468 //function : FindFacePairs
1469 //purpose  : 
1470 //=======================================================================
1471 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
1472                                 const BOPCol_ListOfShape& thLF,
1473                                 BOPTools_ListOfCoupleOfShape& theLCFF,
1474                                 Handle(BOPInt_Context)& theContext)
1475 {
1476   Standard_Boolean bFound;
1477   Standard_Integer i, aNbCEF;
1478   TopAbs_Orientation aOr, aOrC;
1479   BOPCol_MapOfShape aMFP;
1480   TopoDS_Face aF1, aF2;
1481   TopoDS_Edge aEL, aE1;
1482   BOPCol_ListIteratorOfListOfShape aItLF;
1483   BOPTools_CoupleOfShape aCEF, aCFF;
1484   BOPTools_ListOfCoupleOfShape aLCEF, aLCEFx;
1485   BOPTools_ListIteratorOfListOfCoupleOfShape aIt;
1486   //
1487   bFound=Standard_True;
1488   //
1489   // Preface aLCEF
1490   aItLF.Initialize(thLF);
1491   for (; aItLF.More(); aItLF.Next()) { 
1492     const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
1493     //
1494     bFound=BOPTools_AlgoTools::GetEdgeOnFace(theE, aFL, aEL);
1495     if (!bFound) {
1496       return bFound; // it can not be so
1497     }
1498     //
1499     aCEF.SetShape1(aEL);
1500     aCEF.SetShape2(aFL);
1501     aLCEF.Append(aCEF);
1502   }
1503   //
1504   aNbCEF=aLCEF.Extent();
1505   while(aNbCEF) {
1506     //
1507     // aLCEFx
1508     aLCEFx.Clear();
1509     aIt.Initialize(aLCEF);
1510     for (i=0; aIt.More(); aIt.Next(), ++i) {
1511       const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1512       const TopoDS_Shape& aEx=aCSx.Shape1();
1513       const TopoDS_Shape& aFx=aCSx.Shape2();
1514       //
1515       aOr=aEx.Orientation();
1516       //
1517       if (!i) {
1518         aOrC=TopAbs::Reverse(aOr);
1519         aE1=(*(TopoDS_Edge*)(&aEx));
1520         aF1=(*(TopoDS_Face*)(&aFx));
1521         aMFP.Add(aFx);
1522         continue;
1523       }
1524       //
1525       if (aOr==aOrC) {
1526         aLCEFx.Append(aCSx);
1527         aMFP.Add(aFx);
1528       }
1529     }
1530     //
1531     // F2
1532     BOPTools_AlgoTools::GetFaceOff(aE1, aF1, aLCEFx, aF2, theContext);
1533     //
1534     aCFF.SetShape1(aF1);
1535     aCFF.SetShape2(aF2);
1536     theLCFF.Append(aCFF);
1537     //
1538     aMFP.Add(aF1);
1539     aMFP.Add(aF2);
1540     //
1541     // refine aLCEF
1542     aLCEFx.Clear();
1543     aLCEFx=aLCEF;
1544     aLCEF.Clear();
1545     aIt.Initialize(aLCEFx);
1546     for (; aIt.More(); aIt.Next()) {
1547       const BOPTools_CoupleOfShape& aCSx=aIt.Value();
1548       const TopoDS_Shape& aFx=aCSx.Shape2();
1549       if (!aMFP.Contains(aFx)) {
1550         aLCEF.Append(aCSx);
1551       }
1552     }
1553     //
1554     aNbCEF=aLCEF.Extent();
1555   }//while(aNbCEF) {
1556   //
1557   return bFound;
1558 }
1559 //=======================================================================
1560 //function : AngleWithRef
1561 //purpose  : 
1562 //=======================================================================
1563 Standard_Real AngleWithRef(const gp_Dir& theD1,
1564                            const gp_Dir& theD2,
1565                            const gp_Dir& theDRef)
1566 {
1567   Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1568   gp_XYZ aXYZ;
1569   //
1570   aHalfPI=0.5*M_PI;
1571   //
1572   const gp_XYZ& aXYZ1=theD1.XYZ();
1573   const gp_XYZ& aXYZ2=theD2.XYZ();
1574   aXYZ=aXYZ1.Crossed(aXYZ2);
1575   aSinus=aXYZ.Modulus();
1576   aCosinus=theD1*theD2;
1577   //
1578   aBeta=0.;
1579   if (aSinus>=0.) {
1580     aBeta=aHalfPI*(1.-aCosinus);
1581   }
1582   else {
1583     aBeta=2.*M_PI-aHalfPI*(3.+aCosinus);
1584   }
1585   //
1586   aScPr=aXYZ.Dot(theDRef.XYZ());
1587   if (aScPr<0.) {
1588     aBeta=-aBeta;
1589   }
1590   return aBeta;
1591 }
1592 //=======================================================================
1593 //function : fsqrt
1594 //purpose  : 
1595 //=======================================================================
1596 Standard_Real fsqrt(Standard_Real val)  
1597 {
1598   union {
1599     int tmp;
1600     float val;
1601   } u;
1602   //
1603   u.val = (float)val;
1604   u.tmp -= 1<<23; /* Remove last bit so 1.0 gives 1.0 */
1605   /* tmp is now an approximation to logbase2(val) */
1606   u.tmp >>= 1; /* divide by 2 */
1607   u.tmp += 1<<29; /* add 64 to exponent: (e+127)/2 =(e/2)+63, */
1608   /* that represents (e/2)-64 but we want e/2 */
1609   return (double)u.val;
1610 }
1611
1612 //=======================================================================
1613 // function: IsBlockInOnFace
1614 // purpose: 
1615 //=======================================================================
1616   Standard_Boolean BOPTools_AlgoTools::IsBlockInOnFace (const IntTools_Range& aShrR,
1617                                                         const TopoDS_Face& aF,
1618                                                         const TopoDS_Edge& aE1,
1619                                                         Handle(BOPInt_Context)& aContext)
1620 {
1621   Standard_Boolean bFlag;
1622   Standard_Real f1, l1, ULD, VLD;
1623   gp_Pnt2d aP2D;
1624   gp_Pnt aP11, aP12;
1625   //
1626   aShrR.Range(f1, l1);
1627   Standard_Real dt=0.0075,  k;//dt=0.001,  k;
1628   k=dt*(l1-f1);
1629   f1=f1+k;
1630   l1=l1-k;
1631   //
1632   // Treatment P11
1633   BOPTools_AlgoTools::PointOnEdge(aE1, f1, aP11);
1634   //
1635   GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
1636   aProjector.Perform(aP11);
1637   //
1638   bFlag=aProjector.IsDone();
1639   if (!bFlag) {
1640     return bFlag;
1641   }
1642   
1643   aProjector.LowerDistanceParameters(ULD, VLD);
1644   aP2D.SetCoord(ULD, VLD);
1645   //
1646   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1647   //
1648   if (!bFlag) {
1649     return bFlag;
1650   }
1651   //
1652   // Treatment P12
1653   BOPTools_AlgoTools::PointOnEdge(aE1, l1, aP12);
1654   //
1655   aProjector.Perform(aP12);
1656   //
1657   bFlag=aProjector.IsDone();
1658   if (!bFlag) {
1659     return bFlag;
1660   }
1661   
1662   aProjector.LowerDistanceParameters(ULD, VLD);
1663   aP2D.SetCoord(ULD, VLD);
1664   //
1665   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1666   //
1667   if (!bFlag) {
1668     return bFlag;
1669   }
1670   //
1671   // Treatment intemediate
1672   Standard_Real m1, aTolF, aTolE, aTol, aDist;
1673   m1=IntTools_Tools::IntermediatePoint(f1, l1);
1674   BOPTools_AlgoTools::PointOnEdge(aE1, m1, aP12);
1675   //
1676   aProjector.Perform(aP12);
1677   //
1678   bFlag=aProjector.IsDone();
1679   if (!bFlag) {
1680     return bFlag;
1681   }
1682   //
1683   aTolE=BRep_Tool::Tolerance(aE1);
1684   aTolF=BRep_Tool::Tolerance(aF);
1685   aTol=aTolE+aTolF;
1686   aDist=aProjector.LowerDistance();
1687   if (aDist > aTol){
1688    return Standard_False;
1689   }
1690
1691   aProjector.LowerDistanceParameters(ULD, VLD);
1692   aP2D.SetCoord(ULD, VLD);
1693   //
1694   bFlag=aContext->IsPointInOnFace (aF, aP2D);
1695   //
1696   if (!bFlag) {
1697     return bFlag;
1698   }
1699   return bFlag;
1700 }
1701
1702 //=======================================================================
1703 //function : IsMicroEdge
1704 //purpose  : 
1705 //=======================================================================
1706   Standard_Boolean BOPTools_AlgoTools::IsMicroEdge(const TopoDS_Edge& aE,
1707                                                    const Handle(BOPInt_Context)& aCtx) 
1708 {
1709   Standard_Boolean bRet;
1710   Standard_Integer iErr;
1711   Standard_Real aT1, aT2, aTmp;
1712   Handle(Geom_Curve) aC3D;
1713   TopoDS_Vertex aV1, aV2;
1714   //
1715   bRet=(BRep_Tool::Degenerated(aE) ||
1716         !BRep_Tool::IsGeometric(aE));
1717   if (bRet) {
1718     return bRet;
1719   }
1720   //
1721   aC3D=BRep_Tool::Curve(aE, aT1, aT2);
1722   TopExp::Vertices(aE, aV1, aV2);
1723   aT1=BRep_Tool::Parameter(aV1, aE);
1724   aT2=BRep_Tool::Parameter(aV2, aE);
1725   if (aT2<aT1) {
1726     aTmp=aT1;
1727     aT1=aT2;
1728     aT2=aTmp;
1729   }
1730   //
1731   BOPInt_ShrunkRange aSR;
1732   aSR.SetData(aE, aT1, aT2, aV1, aV2, aCtx);
1733   aSR.Perform();
1734   iErr=aSR.ErrorStatus();
1735   bRet = !(iErr==0);
1736   //
1737   return bRet;
1738 }
1739
1740 //=======================================================================
1741 //function : GetFaceDir
1742 //purpose  : Get binormal direction for the face in the point aP
1743 //=======================================================================
1744   void GetFaceDir(const TopoDS_Edge& aE,
1745                   const TopoDS_Face& aF,
1746                   const gp_Pnt& aP,
1747                   const Standard_Real aT,
1748                   const gp_Dir& aDTgt,
1749                   gp_Dir& aDN,
1750                   gp_Dir& aDB,
1751                   Handle(BOPInt_Context)& theContext)
1752 {
1753   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge(aE, aF, aT, aDN);
1754   if (aF.Orientation()==TopAbs_REVERSED){
1755     aDN.Reverse();
1756   }
1757   aDB = aDN^aDTgt;
1758   //
1759   Handle(Geom_Surface) aS = BRep_Tool::Surface(aF);
1760   GeomAdaptor_Surface aGAS(aS);
1761   if (aGAS.GetType()!=GeomAbs_Plane) {
1762     gp_Pnt aPx;
1763     if (!FindPointInFace(aE, aF, aP, aT, aDB, aPx, theContext, aGAS)) {
1764       gp_Pnt2d aPx2D;
1765       Handle(Geom_Plane) aPL;
1766       GeomAPI_ProjectPointOnSurf aProj;
1767       //
1768       BOPTools_AlgoTools3D::PointNearEdge(aE, aF, aT, aPx2D, aPx, theContext);
1769       aPL = new Geom_Plane(aP, aDTgt);
1770       aProj.Init(aPx, aPL);
1771       aPx = aProj.NearestPoint();
1772       gp_Vec aVec(aP, aPx);
1773       aDB.SetXYZ(aVec.XYZ());
1774     }
1775   }
1776 }
1777
1778 //=======================================================================
1779 //function : FindPointInFace
1780 //purpose  : Find a point in the face in direction of <aDB>
1781 //=======================================================================
1782   Standard_Boolean FindPointInFace(const TopoDS_Edge& aE,
1783                                    const TopoDS_Face& aF,
1784                                    const gp_Pnt& aP,
1785                                    const Standard_Real aT,
1786                                    gp_Dir& aDB,
1787                                    gp_Pnt& aPOut,
1788                                    Handle(BOPInt_Context)& theContext,
1789                                    const GeomAdaptor_Surface& aGAS) 
1790 {
1791   Standard_Integer aNbItMax;
1792   Standard_Real aDt, aDtMin, aTolE, aTolF, aDist;
1793   Standard_Boolean bRet;
1794   gp_Pnt aP1;
1795   //
1796   bRet = Standard_False;
1797   aTolE = BRep_Tool::Tolerance(aE);
1798   aTolF = BRep_Tool::Tolerance(aF);
1799   aDt = 2*(aTolE+aTolF);
1800   //
1801   aDtMin=5.e-4;
1802   if (aDt < aDtMin) {
1803     Standard_Real aR;
1804     GeomAbs_SurfaceType aSType=aGAS.GetType();
1805     switch (aSType) {
1806     case GeomAbs_Cylinder:
1807       aR = aGAS.Cylinder().Radius();
1808       break;
1809     case GeomAbs_Cone:
1810       aR = aGAS.Cone().RefRadius();
1811       break;
1812     case GeomAbs_Sphere:
1813       aR = aGAS.Sphere().Radius();
1814       break;
1815     case GeomAbs_Torus:
1816       aR = aGAS.Torus().MinorRadius();
1817       break;
1818     case GeomAbs_SurfaceOfRevolution:
1819       aR=1.;
1820       break;
1821     default:
1822       aR=0.001;
1823     }
1824     if (aR < 0.01) {
1825       aDtMin=5.e-6;
1826     }
1827     else if (aR > 100.) {
1828       aDtMin*=10;
1829     }
1830     if (aDt < aDtMin) {
1831       aDt=aDtMin;
1832     }
1833   }
1834   //
1835   GeomAPI_ProjectPointOnSurf& aProj=theContext->ProjPS(aF);
1836   aNbItMax = 15;
1837   //
1838   do {
1839     aP1.SetCoord(aP.X()+aDt*aDB.X(),
1840                  aP.Y()+aDt*aDB.Y(),
1841                  aP.Z()+aDt*aDB.Z());
1842     //
1843     aProj.Perform(aP1);
1844     if (!aProj.IsDone()) {
1845       return bRet;
1846     }
1847     aPOut = aProj.NearestPoint();
1848     aDist = aProj.LowerDistance();
1849     //
1850     gp_Vec aV(aP, aPOut);
1851     aDB.SetXYZ(aV.XYZ());
1852   } while (aDist>Precision::Angular() && --aNbItMax);
1853   //
1854   bRet = aDist < Precision::Angular();
1855   return bRet;
1856 }