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