a0a33922eada793e7c7f4dea835bb7bc99c85de5
[occt.git] / src / BOPTools / BOPTools_Tools3D.cxx
1 // File:        BOPTools_Tools3D.cxx
2 // Created:     Mon Apr  5 12:29:22 2001
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6 #include <BOPTools_Tools3D.ixx>
7
8 #include <TopExp.hxx>
9 #include <TopExp_Explorer.hxx>
10
11 #include <TopoDS.hxx>
12 #include <TopoDS_Shape.hxx>
13 #include <TopoDS_Edge.hxx>
14 #include <TopoDS_Face.hxx>
15 #include <TopoDS_Vertex.hxx>
16
17 #include <TopTools_MapOfShape.hxx>
18 #include <TopTools_MapIteratorOfMapOfShape.hxx>
19 #include <TopTools_ListOfShape.hxx>
20 #include <TopTools_ListIteratorOfListOfShape.hxx>
21 #include <TopTools_IndexedMapOfShape.hxx>
22 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
23
24 #include <BRep_Builder.hxx>
25 #include <BRep_Tool.hxx>
26 #include <BRepTools.hxx>
27 #include <BRepAdaptor_Surface.hxx>
28
29 #include <gp_Vec2d.hxx>
30 #include <gp_Pnt2d.hxx>
31 #include <gp_Lin2d.hxx>
32 #include <gp_Dir2d.hxx>
33 #include <gp_Vec.hxx>
34 #include <gp_Dir.hxx>
35 #include <gp_Pln.hxx>
36
37 #include <Geom2d_Curve.hxx>
38 #include <Geom2d_TrimmedCurve.hxx>
39 #include <Geom2d_Line.hxx>
40
41 #include <Geom_Curve.hxx>
42 #include <Geom_Surface.hxx>
43 #include <Geom_BSplineSurface.hxx>
44 #include <Geom_BezierSurface.hxx>
45
46 #include <GeomAdaptor_Surface.hxx>
47
48 #include <IntTools_Tools.hxx>
49
50 #include <BOPTools_Tools2D.hxx>
51
52 #include <GProp_GProps.hxx>
53 #include <BRepGProp.hxx>
54 #include <BRepBndLib.hxx>
55 #include <Bnd_Box.hxx>
56
57
58
59 static
60   void PointNearE (const TopoDS_Edge& aE,
61                    const TopoDS_Face& aF,
62                    const Standard_Real aT,
63                    gp_Pnt& aPInFace,
64                    const Standard_Boolean aSt);
65
66 static Standard_Boolean CheckKeepArguments(const TopoDS_Face& F1,
67                                            const TopoDS_Face& F2,
68                                            const TopoDS_Face& F3);
69
70 //=======================================================================
71 //function : RemoveSims
72 //purpose  : 
73 //=======================================================================
74   void BOPTools_Tools3D::RemoveSims (const TopoDS_Shape& aS,
75                                      IntTools_Context& aContext)
76 {
77   TopExp_Explorer anExp(aS, TopAbs_FACE);
78   for (; anExp.More(); anExp.Next()) {
79     const TopoDS_Face& aF=TopoDS::Face(anExp.Current());
80     //
81     BOPTools_Tools3D::RemoveSims (aF, aContext);
82   }
83 }
84
85 //=======================================================================
86 //function : RemoveSims
87 //purpose  : 
88 //=======================================================================
89   void BOPTools_Tools3D::RemoveSims (const TopoDS_Face& aFF,
90                                      IntTools_Context& aContext)
91 {
92   Standard_Boolean anIsClosed, anIsPointInFace1, anIsPointInFace2;
93   Standard_Real aT1, aT2, aT, aX, aY, dt=1.e-7, aTol;
94   BRep_Builder BB;
95   gp_Vec2d aV2D, aV2Dx;
96   gp_Pnt2d aP2D, aP2Dx;
97   TopAbs_Orientation anOri;
98   Handle(Geom2d_Curve) aC2Dx;
99   //
100   TopoDS_Face aF=aFF;
101   aF.Orientation(TopAbs_FORWARD);
102   //
103   TopExp_Explorer anExpW (aF, TopAbs_WIRE);
104   for (; anExpW.More(); anExpW.Next()) {
105
106     TopTools_MapOfShape aMap, aMapToAdd, aMapToRemove;
107     const TopoDS_Shape& aW=anExpW.Current();
108
109     TopExp_Explorer anExp(aW, TopAbs_EDGE);
110     for (; anExp.More(); anExp.Next())   {
111       const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current());
112       //
113       if (BRep_Tool::Degenerated(aE)){
114         continue;
115       }
116       //
117       anIsClosed=BRep_Tool::IsClosed(aE, aF); 
118       if (anIsClosed) {
119         if (aMap.Contains(aE)) {
120           continue;
121         }
122         aMap.Add(aE);
123         aTol=BRep_Tool::Tolerance(aE);
124         
125         Handle(Geom2d_Curve) aC2D=BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
126         aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
127         aC2D-> D1(aT, aP2D, aV2D);
128         
129         anOri=aE.Orientation();
130         if (anOri==TopAbs_REVERSED) {
131           aV2D.Reverse();
132         }
133         
134         aV2D.Normalize();
135         aX=aV2D.X();
136         aY=aV2D.Y();
137         aV2Dx.SetCoord(-aY, aX);
138         
139         aP2Dx.SetX(aP2D.X()+dt*aV2Dx.X());
140         aP2Dx.SetY(aP2D.Y()+dt*aV2Dx.Y());
141         //
142         anIsPointInFace1=aContext.IsPointInFace(aF, aP2Dx);
143         //
144         aP2Dx.SetX(aP2D.X()-dt*aV2Dx.X());
145         aP2Dx.SetY(aP2D.Y()-dt*aV2Dx.Y());
146         //
147         anIsPointInFace2=aContext.IsPointInFace(aF, aP2Dx);
148         //
149         
150         if (anIsPointInFace1 && anIsPointInFace2) {
151           continue;
152         }
153         //
154         TopoDS_Edge aEx=aE;
155         
156         aEx.EmptyCopy();
157         TopExp_Explorer anExpV(aE, TopAbs_VERTEX);
158         for (; anExpV.More(); anExpV.Next()) {
159           const TopoDS_Shape& aVx=anExpV.Current();
160           BB.Add (aEx, aVx);
161         }
162         
163         BB.UpdateEdge(aEx, aTol);
164         //
165         if (anIsPointInFace1) {
166           if (anOri==TopAbs_REVERSED) {
167             // Remove Forward
168             BB.UpdateEdge(aEx, aC2Dx, aF, aTol);
169             BB.UpdateEdge(aEx, aC2D , aF, aTol);
170             aEx.Orientation(TopAbs_REVERSED);
171           }
172           else {
173             // Remove Reversed
174             BB.UpdateEdge(aEx, aC2Dx, aF, aTol);
175             BB.UpdateEdge(aEx, aC2D , aF, aTol);
176             aEx.Orientation(TopAbs_FORWARD);
177           }
178           aMapToAdd.Add(aEx);
179           aMapToRemove.Add(aE);
180         }
181       }
182     }// next Edge
183     //
184     TopoDS_Shape* pW= (TopoDS_Shape*)&aW;
185     pW->Free(Standard_True);
186
187     TopTools_MapIteratorOfMapOfShape anIt(aMapToRemove);
188     for (; anIt.More(); anIt.Next()) {
189       const TopoDS_Shape& aSR=anIt.Key();
190       BB.Remove(*pW, aSR);
191     }
192     anIt.Initialize(aMapToAdd);
193     for (; anIt.More(); anIt.Next()) {
194       const TopoDS_Shape& aSA=anIt.Key();
195       BB.Add(*pW, aSA);
196     }
197     
198   }// next Wire
199 }
200
201 //=======================================================================
202 //function : SubShapesAmount
203 //purpose  : 
204 //=======================================================================
205   Standard_Integer BOPTools_Tools3D::SubShapesAmount (const TopoDS_Shape& aS,
206                                                       const TopAbs_ShapeEnum aType)
207 {
208   Standard_Integer aNb;
209   TopTools_IndexedMapOfShape aM;
210   TopExp::MapShapes(aS, aType, aM);
211   aNb=aM.Extent();
212   return aNb;
213 }
214
215 //=======================================================================
216 //function : IsConvexWire
217 //purpose  : 
218 //=======================================================================
219   Standard_Boolean BOPTools_Tools3D::IsConvexWire (const TopoDS_Wire& aW)
220 {
221   Standard_Boolean aFlag;
222   Standard_Integer aNbV, aNbE;
223
224   aNbV=BOPTools_Tools3D::SubShapesAmount(aW, TopAbs_VERTEX);
225   aNbE=BOPTools_Tools3D::SubShapesAmount(aW, TopAbs_EDGE);
226   aFlag=aNbV <= aNbE;
227   return aFlag;
228 }
229
230 //=======================================================================
231 //function : DoSplitSEAMOnFace
232 //purpose  : 
233 //=======================================================================
234   void BOPTools_Tools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
235                                             const TopoDS_Face& aF)
236 {
237   Standard_Boolean bIsUPeriodic, bIsLeft;
238   Standard_Real aTol, a, b, anUPeriod, aT, anU, dU=1.e-7, anU1;
239   Standard_Real aScPr;
240   gp_Pnt2d aP2D;
241   gp_Vec2d aVec2D;
242   Handle(Geom2d_Curve) aTmpC1, aTmpC2;
243   Handle(Geom2d_Curve) C2D1;
244   Handle(Geom2d_Line) aLD1;
245   Handle(Geom_Surface) aS;
246   BRep_Builder BB;
247   TopoDS_Edge aSp;
248   //
249   aSp=aSplit;
250   aSp.Orientation(TopAbs_FORWARD);
251   
252   aTol=BRep_Tool::Tolerance(aSp);
253
254   aS=BRep_Tool::Surface(aF);
255   bIsUPeriodic=aS->IsUPeriodic();
256   
257   anUPeriod=0.;
258   if (bIsUPeriodic) {
259     anUPeriod=aS->UPeriod();
260   }
261   else {
262     //modified by NIZNHY-PKV Fri Jul 11 09:54:43 2008f
263     Standard_Boolean bIsUClosed;
264     Standard_Real aUmin, aUmax, aVmin, aVmax;
265     Handle(Geom_BSplineSurface) aBS;
266     Handle(Geom_BezierSurface) aBZ;
267     //
268     bIsUClosed=Standard_False;
269     aBS=Handle(Geom_BSplineSurface)::DownCast(aS);
270     aBZ=Handle(Geom_BezierSurface) ::DownCast(aS);
271     //
272     if (!aBS.IsNull()) {
273       bIsUClosed=aBS->IsUClosed();
274       aBS->Bounds(aUmin, aUmax, aVmin, aVmax);
275     }
276     else if (!aBZ.IsNull()) {
277       bIsUClosed=aBZ->IsUClosed();
278       aBZ->Bounds(aUmin, aUmax, aVmin, aVmax);
279     }
280     if (!bIsUClosed) {
281       return;
282     }
283     //
284     anUPeriod=aUmax-aUmin;
285     //modified by NIZNHY-PKV Fri Jul 11 09:54:49 2008t
286   }
287   //
288   C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
289   //modified by NIZNHY-PKV Fri Jul 11 09:55:10 2008f
290   /*
291   aLD1=Handle(Geom2d_Line)::DownCast(C2D1);
292   if (aLD1.IsNull()) {
293     return;
294   }
295   */
296   //modified by NIZNHY-PKV Fri Jul 11 09:55:14 2008t
297   //
298   aT=BOPTools_Tools2D::IntermediatePoint(a, b);
299   C2D1->D1(aT, aP2D, aVec2D);
300   gp_Dir2d aDir2D1(aVec2D);
301   
302   //
303   gp_Dir2d aDOY(0.,1.);
304   aScPr=aDir2D1*aDOY;
305   //
306   //
307   anU=aP2D.X();
308   if (fabs (anU) < dU) {
309     bIsLeft=Standard_True;
310     anU1=anU+anUPeriod;
311   }
312   else if (fabs (anU-anUPeriod) < dU) {
313     bIsLeft=Standard_False;
314     anU1=anU-anUPeriod;
315   }
316   else {
317     return;
318   }
319   //
320   
321   
322   aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
323   Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve(aTmpC1, a, b);
324
325   aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
326   Handle(Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve(aTmpC2, a, b);
327   gp_Vec2d aTrV(anU1-anU, 0.);
328   aC2->Translate(aTrV);
329   //
330   if (!bIsLeft) {
331     if (aScPr<0.) {
332       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
333     }
334     else {
335       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
336     }
337   }
338   else {
339     if (aScPr<0.) {
340       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
341     }
342     else {
343       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
344     }
345   }
346   //
347 }
348 //=======================================================================
349 //function : DoSplitSEAMOnFace
350 //purpose  : 
351 //=======================================================================
352 Standard_Boolean BOPTools_Tools3D::DoSplitSEAMOnFace(const TopoDS_Edge& theSplit,
353                                                      const TopoDS_Edge& theSeam,
354                                                      const TopoDS_Face& theFace,
355                                                      Standard_Boolean&  IsReversed) 
356 {
357   Standard_Real aTol, f, l, a, b, aPeriod, aT, aParTolerance = 1.e-07;
358   Standard_Boolean bIsUPeriodic = Standard_False;
359   Standard_Boolean bIsVPeriodic = Standard_False;
360   BRep_Builder BB;
361   gp_Pnt2d aP2D;
362   gp_Vec2d aVec2D;
363
364
365   TopoDS_Edge aSp = theSplit;
366   aSp.Orientation(TopAbs_FORWARD);
367   TopoDS_Edge aSeamF = theSeam;
368   aSeamF.Orientation(TopAbs_FORWARD);
369   TopoDS_Edge aSeamR = theSeam;
370   aSeamR.Orientation(TopAbs_REVERSED);
371
372   aTol=BRep_Tool::Tolerance(aSp);
373
374   Handle(Geom2d_Curve) C2D1 = BRep_Tool::CurveOnSurface(aSp, theFace, f, l);
375   Handle(Geom2d_Curve) C2D2 = BRep_Tool::CurveOnSurface(aSeamF, theFace, a, b);
376   Handle(Geom2d_Curve) C2D3 = BRep_Tool::CurveOnSurface(aSeamR, theFace, a, b);
377   //
378   Handle(Geom2d_TrimmedCurve) atr = Handle(Geom2d_TrimmedCurve)::DownCast(C2D1);
379   Handle(Geom2d_Line) aLD1;
380
381   if(!atr.IsNull()) {
382     aLD1 = Handle(Geom2d_Line)::DownCast(atr->BasisCurve());
383   }
384   else {
385     aLD1 = Handle(Geom2d_Line)::DownCast(C2D1);
386   }
387
388   if (aLD1.IsNull()) {
389     return Standard_False;
390   }
391   aT = BOPTools_Tools2D::IntermediatePoint(f, l);
392   C2D1->D1(aT, aP2D, aVec2D);
393   gp_Dir2d aDir2D(aVec2D);
394
395   gp_Vec2d aVec2D1, aVec2D2;
396   gp_Pnt2d aP2D1, aP2D2;
397   C2D2->D1(((a+b) * 0.5), aP2D1, aVec2D1);
398   C2D3->D1(((a+b) * 0.5), aP2D2, aVec2D2);
399
400   Handle(Geom_Surface) aS=BRep_Tool::Surface(theFace);
401   bIsUPeriodic = aS->IsUPeriodic();
402   bIsVPeriodic = aS->IsVPeriodic();
403
404   for(Standard_Integer i = 0; i < 2; i++) {
405     Standard_Boolean bIsPeriodic = (i == 0) ? bIsUPeriodic : bIsVPeriodic;
406
407     if(!bIsPeriodic)
408       continue;
409
410     aPeriod = (i == 0) ? aS->UPeriod() : aS->VPeriod();
411
412     Standard_Real aParameter = (i == 0) ? aP2D.X() : aP2D.Y();
413     Standard_Real aParameter1 = (i == 0) ? aP2D1.X() : aP2D1.Y();
414     Standard_Real aParameter2 = (i == 0) ? aP2D2.X() : aP2D2.Y();
415
416     Standard_Boolean bIsLower = Standard_False, found = Standard_False;
417     Standard_Boolean bIsFirst = Standard_False;
418     Standard_Real aScPr = 0.;
419
420     if (fabs (aParameter - aParameter1) < aParTolerance) {
421       bIsLower = (aParameter < aParameter2);
422       bIsFirst = Standard_True;
423       aScPr = aDir2D * aVec2D1;
424     }
425     else if (fabs (aParameter - aParameter2) < aParTolerance) {
426       bIsLower = (aParameter < aParameter1);
427       bIsFirst = Standard_False;
428       aScPr = aDir2D * aVec2D2;
429     }
430     found = (fabs(aScPr) > aParTolerance);
431
432     if(found) {
433       Handle(Geom2d_Curve) aTmpC1, aTmpC2;
434   
435       aTmpC1 = Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
436       Handle(Geom2d_TrimmedCurve) aC1 = new Geom2d_TrimmedCurve(aTmpC1, f, l);
437
438       aTmpC2 = Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
439       Handle(Geom2d_TrimmedCurve) aC2 = new Geom2d_TrimmedCurve(aTmpC2, f, l);
440       gp_Vec2d aTrV;
441
442       if(i == 0) {
443         if(bIsLower)
444           aTrV.SetX(aPeriod);
445         else
446           aTrV.SetX(-aPeriod);
447         aTrV.SetY(0.);
448       }
449       else {
450         if(bIsLower)
451           aTrV.SetY(aPeriod);
452         else
453           aTrV.SetY(-aPeriod);
454         aTrV.SetX(0.);
455       }
456       aC2->Translate(aTrV);
457       //
458       IsReversed = (aScPr < 0.);
459       Standard_Boolean bIsReverseOrder = (!IsReversed) ? !bIsFirst : bIsFirst;
460
461       if(bIsReverseOrder) {
462         BB.UpdateEdge(aSp, aC2, aC1, theFace, aTol);
463       }
464       else {
465         BB.UpdateEdge(aSp, aC1, aC2, theFace, aTol);
466       }
467       return Standard_True;
468     }
469   }
470   return Standard_False;
471 }
472 //=======================================================================
473 //function :IsSplitToReverse1
474 //purpose  : 
475 //=======================================================================
476   Standard_Boolean BOPTools_Tools3D::IsSplitToReverse1 (const TopoDS_Edge& aEF1,
477                                                         const TopoDS_Edge& aEF2,
478                                                         IntTools_Context& aContext)
479 {
480   Standard_Boolean aFlag;
481   Standard_Real aT1, aT2, aScPr, a, b;
482   gp_Vec aV1, aV2;
483   gp_Pnt aP;
484   
485   
486   Handle(Geom_Curve)aC1=BRep_Tool::Curve(aEF1, a, b);
487   aT1=BOPTools_Tools2D::IntermediatePoint(a, b);
488   aC1->D0(aT1, aP);
489   aFlag=BOPTools_Tools2D::EdgeTangent(aEF1, aT1, aV1);
490
491   if(!aFlag) {
492     return Standard_False;
493   }
494
495   gp_Dir aDT1(aV1);
496   //
497   aFlag=aContext.ProjectPointOnEdge(aP, aEF2, aT2);
498   //
499   aFlag=BOPTools_Tools2D::EdgeTangent(aEF2, aT2, aV2);
500   if(!aFlag) {
501     return Standard_False;
502   }
503
504   gp_Dir aDT2(aV2);
505
506   aScPr=aDT1*aDT2;
507
508   return (aScPr<0.);
509 }
510
511 //=======================================================================
512 //function : EdgeOrientation
513 //purpose  : 
514 //=======================================================================
515   TopAbs_Orientation BOPTools_Tools3D::EdgeOrientation (const TopoDS_Edge& aE,
516                                                         const TopoDS_Face& aF1,
517                                                         const TopoDS_Face& aF2)
518 {
519   Standard_Real aScPr;
520   gp_Dir aDTE, aDNF1, aDNF2, aDTN;
521
522   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE, aF1, aDNF1);
523   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE, aF2, aDNF2);
524   
525   aDTN=aDNF1^aDNF2;
526   
527   BOPTools_Tools2D::TangentOnEdge(aE, aDTE);
528   
529   aScPr=aDTN*aDTE;
530
531   TopAbs_Orientation anOr;
532
533   anOr=TopAbs_FORWARD;
534   if (aScPr<0.) {
535     anOr=TopAbs_REVERSED;
536   }
537   return anOr;
538 }
539 //=======================================================================
540 //function : IsTouchCase
541 //purpose  : 
542 //=======================================================================
543   Standard_Boolean BOPTools_Tools3D::IsTouchCase(const TopoDS_Edge& aE,
544                                                  const TopoDS_Face& aF1,
545                                                  const TopoDS_Face& aF2)
546 {
547   gp_Dir aDNF1, aDNF2;
548   
549
550   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE, aF1, aDNF1);
551   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE, aF2, aDNF2);
552
553   Standard_Boolean bIsDirsCoinside;
554   bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
555   return bIsDirsCoinside;
556 }
557 //=======================================================================
558 //function : GetNormalToFaceOnEdge
559 //purpose  : 
560 //=======================================================================
561   void BOPTools_Tools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
562                                                 const TopoDS_Face& aF,
563                                                 gp_Dir& aDNF)
564 {
565   Standard_Real aT, aT1, aT2;
566   
567   BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
568   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
569
570   BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
571
572   if (aF.Orientation()==TopAbs_REVERSED){
573     aDNF.Reverse();
574   }
575 }
576
577 //=======================================================================
578 //function : GetNormalToFaceOnEdge
579 //purpose  : 
580 //=======================================================================
581   void BOPTools_Tools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
582                                                 const TopoDS_Face& aF1,
583                                                 const Standard_Real aT, 
584                                                 gp_Dir& aDNF1)
585 {
586   Standard_Real U, V, aTolPC;
587   gp_Pnt2d aP2D;
588   gp_Pnt aP;
589   gp_Vec aD1U, aD1V;
590
591   Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
592   
593   Handle(Geom2d_Curve)aC2D1;
594   BOPTools_Tools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC, Standard_True);
595
596   aC2D1->D0(aT, aP2D);
597   U=aP2D.X();
598   V=aP2D.Y();
599   
600   aS1->D1(U, V, aP, aD1U, aD1V);
601   gp_Dir aDD1U(aD1U); 
602   gp_Dir aDD1V(aD1V); 
603   
604   aDNF1=aDD1U^aDD1V; 
605 }
606
607 //=======================================================================
608 //function : GetBiNormal
609 //purpose  :
610 //=======================================================================
611   void BOPTools_Tools3D::GetBiNormal(const TopoDS_Edge& aE,
612                                      const TopoDS_Face& aF,
613                                      const Standard_Real aT, 
614                                      gp_Dir& aDB)
615 {
616   gp_Dir aDNF, aDT;
617   //
618   // Normal to the face aF at parameter aT
619   BOPTools_Tools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
620   if (aF.Orientation()==TopAbs_REVERSED){
621     aDNF.Reverse();
622   }
623   //
624   // Split tangent on aF at parameter aT
625   BOPTools_Tools3D::GetTangentToEdge(aE, aT, aDT);
626
627   if (aF.Orientation()==TopAbs_REVERSED){
628     aDT.Reverse();
629   }
630   // Binormal 
631   aDB=aDNF^aDT;
632 }
633
634 //=======================================================================
635 //function : :GetBiNormal
636 //purpose  :
637 //=======================================================================
638   void BOPTools_Tools3D::GetBiNormal(const TopoDS_Edge& aSp,
639                                      const TopoDS_Face& aF,
640                                      gp_Dir& aDB)
641 {
642   gp_Dir aDNF, aDD1Sp;
643   //
644   // Normal to the face aF at parameter aT
645   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSp, aF, aDNF);
646   //
647   // Split tangent on aF at parameter aT
648   BOPTools_Tools3D::GetTangentToEdge(aSp, aDD1Sp);
649
650   if (aF.Orientation()==TopAbs_REVERSED){
651     aDD1Sp.Reverse();
652   }
653   // Binormal 
654   aDB=aDNF^aDD1Sp;
655 }
656 //=======================================================================
657 //function : GetTangentToEdge
658 //purpose  : 
659 //=======================================================================
660   Standard_Boolean BOPTools_Tools3D::GetTangentToEdge(const TopoDS_Edge& anEdge, 
661                                                       gp_Dir& aDT)
662 {
663   Standard_Boolean isdgE;
664   
665   Standard_Real aT1, aT2, aT;
666   
667   isdgE = BRep_Tool::Degenerated(anEdge); 
668   if (isdgE) {
669     return Standard_False;
670   }
671   
672   Handle(Geom_Curve) aC=BRep_Tool::Curve(anEdge, aT1, aT2);
673   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
674
675   BOPTools_Tools3D::GetTangentToEdge(anEdge, aT, aDT);
676
677   return Standard_True;
678 }
679 //=======================================================================
680 //function : GetTangentToEdge
681 //purpose  : 
682 //=======================================================================
683   Standard_Boolean BOPTools_Tools3D::GetTangentToEdge(const TopoDS_Edge& anEdge, 
684                                                       const Standard_Real aT,
685                                                       gp_Dir& aDT)
686 {
687   Standard_Boolean isdgE;
688   Standard_Real first, last;
689   
690   isdgE = BRep_Tool::Degenerated(anEdge); 
691   if (isdgE) {
692     return Standard_False;
693   }
694
695   Handle(Geom_Curve) aC=BRep_Tool::Curve(anEdge, first, last);
696   gp_Pnt aP;
697   gp_Vec aTau;
698   aC->D1(aT, aP, aTau);
699   gp_Dir aD(aTau);
700   if (anEdge.Orientation() == TopAbs_REVERSED){
701     aD.Reverse();
702   }
703   aDT=aD;
704
705   return Standard_True;
706 }
707 //=======================================================================
708 //function : :IsSplitToReverse
709 //purpose  : 
710 //=======================================================================
711   Standard_Boolean BOPTools_Tools3D:: IsSplitToReverse(const TopoDS_Edge& aE,
712                                                        const TopoDS_Edge& aSp)
713 {
714   Standard_Real t1, t2, aT;
715   
716   Handle(Geom_Curve)aCE=BRep_Tool::Curve(aE, t1, t2);
717   Handle(Geom_Curve)aCSp=BRep_Tool::Curve(aSp,t1, t2);
718   
719   aT=BOPTools_Tools2D::IntermediatePoint(t1, t2);
720   
721   gp_Vec aD1E, aD1Sp;
722   gp_Pnt aP;
723   
724   aCE->D1 (aT, aP, aD1E);
725   aCSp->D1(aT, aP, aD1Sp);
726   
727   gp_Dir aDD1E (aD1E); 
728   gp_Dir aDD1Sp(aD1Sp); 
729   
730   if (aE.Orientation()==TopAbs_REVERSED) {
731     aDD1E.Reverse();
732   }
733   if (aSp.Orientation()==TopAbs_REVERSED) {
734     aDD1Sp.Reverse();
735   }
736   
737   aT=aDD1E*aDD1Sp;
738   
739   return (aT<0.); 
740 }
741
742 //=======================================================================
743 //function : GetAdjacentFace
744 //purpose  :
745 //=======================================================================
746   Standard_Boolean BOPTools_Tools3D::GetAdjacentFace(const TopoDS_Face& aFaceObj,
747                                                      const TopoDS_Edge& anEObj,
748                  const TopTools_IndexedDataMapOfShapeListOfShape& anEdgeFaceMap,
749                                                      TopoDS_Face& anAdjF)
750 {
751   const TopTools_ListOfShape& aListOfAdjFaces=anEdgeFaceMap.FindFromKey(anEObj);
752   TopTools_ListIteratorOfListOfShape anIt(aListOfAdjFaces);
753   TopoDS_Shape anAdjShape;
754   for (; anIt.More(); anIt.Next()) {
755     if (anIt.Value()!=aFaceObj) {
756       anAdjShape=anIt.Value();
757       break;
758     }
759   }
760
761   if (!anAdjShape.IsNull()) {
762     anAdjF=TopoDS::Face(anAdjShape);
763     return Standard_True;
764   }
765   else {
766     return Standard_False;
767   }
768 }
769 //=======================================================================
770 //function :  IsKeepTwice
771 //purpose  :
772 //=======================================================================
773   Standard_Boolean BOPTools_Tools3D::IsKeepTwice(const TopoDS_Face& aF1,
774                                                  const TopoDS_Face& aF2,
775                                                  const TopoDS_Face& aF2Adj,
776                                                  const TopoDS_Edge& aSpEF2)
777 {
778   if( !CheckKeepArguments(aF1, aF2, aF2Adj) ) {
779     return Standard_False;
780   }
781
782   Standard_Real aT1, aT2, aT, dt=1.e-7, A, B, C, D, d2, d2Adj;
783   gp_Dir aDNF1, aDNF2, DBF2, aDNF2Adj, DBF2Adj;
784   gp_Vec aD1Sp;
785   gp_Pnt aP, aPF2, aPF2Adj;
786
787   Handle(Geom_Curve) aC3D=BRep_Tool::Curve(aSpEF2, aT1, aT2);
788   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
789   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF1, aT, aDNF1);
790   
791   //
792   // Split tangent on F2
793   aC3D->D1(aT, aP, aD1Sp);
794   gp_Dir aDD1Sp(aD1Sp); 
795   
796   if (aSpEF2.Orientation()==TopAbs_REVERSED) {
797     aDD1Sp.Reverse();
798   }
799   // Split Normal on F2
800   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2, aT, aDNF2);
801   if (aF2.Orientation()==TopAbs_REVERSED) {
802     aDNF2.Reverse();
803   }
804   // Binormal on F2
805   DBF2=aDNF2^aDD1Sp;
806   
807   // Point near aP
808   aPF2.SetCoord(aP.X()+dt*DBF2.X(), 
809                 aP.Y()+dt*DBF2.Y(),
810                 aP.Z()+dt*DBF2.Z());
811                 
812   
813   //
814   // Split tangent on F2Adj
815   aDD1Sp.Reverse();
816   // Split Normal on F2Adj
817   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSpEF2, aF2Adj, aT, aDNF2Adj);
818   if (aF2Adj.Orientation()==TopAbs_REVERSED) {
819     aDNF2Adj.Reverse();
820   }
821   // Binormal on F2Adj
822   DBF2Adj=aDNF2Adj^aDD1Sp;
823   
824   // Point near aP
825   aPF2Adj.SetCoord(aP.X()+dt*DBF2Adj.X(), 
826                    aP.Y()+dt*DBF2Adj.Y(),
827                    aP.Z()+dt*DBF2Adj.Z());
828   //
829   // Tangent Plane on F1
830   gp_Pln aPlnN1(aP, aDNF1);
831   aPlnN1.Coefficients(A, B, C, D);
832   //
833   d2   = A*aPF2.X()    + B*aPF2.Y()   + C*aPF2.Z()    + D;
834   d2Adj= A*aPF2Adj.X() + B*aPF2Adj.Y()+ C*aPF2Adj.Z() + D;
835   //
836   if (fabs(d2)<1.e-10) {
837     d2=0.;
838   }
839   if (fabs(d2Adj)<1.e-10) {
840     d2Adj=0.;
841   }
842   //
843   aT=d2*d2Adj;
844   //
845   return  (aT >= 0.);
846 }
847
848 //=======================================================================
849 //function : SenseFlag
850 //purpose  :
851 //=======================================================================
852   Standard_Integer BOPTools_Tools3D::SenseFlag (const gp_Dir& aDNF1,
853                                                 const gp_Dir& aDNF2)
854 {
855   Standard_Boolean bIsDirsCoinside;
856   bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
857   if (!bIsDirsCoinside) {
858     return 0;
859   }
860   
861   Standard_Real aScPr;
862   
863   aScPr=aDNF1*aDNF2;
864   if (aScPr<0.) {
865     return -1;
866   }
867   else if (aScPr>0.) {
868     return 1;
869   }
870   return -1;
871 }
872
873 //=======================================================================
874 //function : GetNormalToSurface
875 //purpose  :
876 //=======================================================================
877   Standard_Boolean BOPTools_Tools3D::GetNormalToSurface (const Handle(Geom_Surface)& aS,
878                                                          const Standard_Real U,
879                                                          const Standard_Real V,
880                                                          gp_Dir& aDNS)
881 {
882   Standard_Boolean bFlag;
883   
884   gp_Pnt aP;
885   gp_Vec aD1U, aD1V;
886
887   aS->D1(U, V, aP, aD1U, aD1V);
888   
889   gp_Dir aDD1U(aD1U); 
890   gp_Dir aDD1V(aD1V); 
891   
892   bFlag=IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
893   if (!bFlag) {
894     return bFlag;
895   }
896   
897   aDNS=aDD1U^aDD1V;
898   return bFlag;
899 }
900
901 //=======================================================================
902 //function : GetNormalToSurface
903 //purpose  : local modification
904 //=======================================================================
905
906 static void GetApproxNormalToFaceOnEdgeEx(const TopoDS_Edge& aE,
907                                           const TopoDS_Face& aF,
908                                           const Standard_Real aT,
909                                           const Standard_Real aDT,
910                                           gp_Pnt& aPNear,
911                                           gp_Dir& aDNF)
912 {
913   Standard_Real aFirst, aLast;
914   Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
915   
916   if (aC2D.IsNull()) {
917     return;
918   }
919
920   //gp_Pnt aPNear;
921   gp_Pnt2d aPx2DNear;
922   BOPTools_Tools3D::PointNearEdge (aE, aF, aT, aDT, aPx2DNear, aPNear);
923   
924   Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
925   
926   BOPTools_Tools3D::GetNormalToSurface (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
927   
928   if (aF.Orientation()==TopAbs_REVERSED){
929     aDNF.Reverse();
930   }
931 }
932
933 //=======================================================================
934 //function : GetPlanes
935 //purpose  :
936 //=======================================================================
937   void BOPTools_Tools3D::GetPlanes (const TopoDS_Edge& aSpx,
938                                     const TopoDS_Edge& anEx,
939                                     const TopTools_IndexedDataMapOfShapeListOfShape& anEFMapx,
940                                     const TopoDS_Edge& anE1,
941                                     const TopoDS_Face& aF1,
942                                     TopAbs_State& aStPF1,
943                                     IntTools_Context& aContext)
944 {
945   Standard_Boolean bIsAdjExists;
946
947   Standard_Real aT, aT1, aT2;
948   gp_Dir aDNFx1, aDNFx2; 
949   gp_Pnt aPx, aPx1, aPx2, aPF1;
950   TopoDS_Face aFx1, aFx2;
951   //
952   // Point
953   Handle(Geom_Curve)aC3D =BRep_Tool::Curve(aSpx, aT1, aT2);
954   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
955   
956   aC3D->D0(aT, aPx);
957   //
958   // 1.1. Fx1, Fx2 and theirs normals
959   TopAbs_Orientation anOrEx, anOr;
960   anOrEx=anEx.Orientation();
961
962   TopoDS_Edge aSpxSimm=anEx;
963   if (anOrEx==TopAbs_FORWARD) {
964     aSpxSimm.Orientation(TopAbs_REVERSED);
965   }
966   else if (anOrEx==TopAbs_REVERSED){
967     aSpxSimm.Orientation(TopAbs_FORWARD);
968   }
969   //
970   
971   const TopTools_ListOfShape& aLF=anEFMapx.FindFromKey(anEx);
972   TopTools_ListIteratorOfListOfShape anIt(aLF);
973   
974   for (; anIt.More(); anIt.Next()) {
975     const TopoDS_Shape& aFE=anIt.Value();
976     aFx1=TopoDS::Face(aFE);
977     anOr=BOPTools_Tools3D::Orientation(anEx, aFx1);
978     if (anOr==anOrEx){
979       break;
980     }
981   }
982   
983   //-- EJG
984   Standard_Boolean aMoreShift = Standard_False;
985   Standard_Real aF2Tol = BRep_Tool::Tolerance(aFx1);
986   Standard_Real aF1Tol = BRep_Tool::Tolerance(aF1);
987   Standard_Real aETol = BRep_Tool::Tolerance(anEx);
988   if( aETol > 1.e-5 && (aF2Tol > 1.e-5 && aF1Tol > 1.e-5) ) 
989      aMoreShift = Standard_True;
990   Standard_Real aDT = 9.1e-5;
991   if( aMoreShift ) {
992     GetApproxNormalToFaceOnEdgeEx(anEx, aFx1, aT, aDT, aPx1, aDNFx1);
993   }
994   else {
995     //-- EJG
996     BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (anEx, aFx1, aT, aPx1, aDNFx1);
997   }
998
999   bIsAdjExists=BOPTools_Tools3D::GetAdjacentFace (aFx1, anEx, anEFMapx, aFx2);
1000
1001   if (!bIsAdjExists) {
1002     //-- EJG
1003     if(  aMoreShift ) {
1004       GetApproxNormalToFaceOnEdgeEx(aSpxSimm, aFx1, aT, aDT, aPx2, aDNFx2);
1005     }
1006     else {
1007       //-- EJG
1008       BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aSpxSimm, aFx1, aT, aPx2, aDNFx2); 
1009     }
1010
1011     aContext.ProjectPointOnEdge(aPx, anE1, aT1);
1012     PointNearE (anE1, aF1, aT1, aPF1, aMoreShift);
1013   }
1014
1015   else {// if (bIsAdjExists)
1016     BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aSpxSimm, aFx2, aT, aPx2, aDNFx2);
1017     //  
1018     aContext.ProjectPointOnEdge(aPx, anE1, aT1);
1019     PointNearE (anE1, aF1, aT1, aPF1, aMoreShift);
1020   }
1021   
1022   {
1023     Standard_Real d12, d1, anAlfa12, anAlfa1, aTwoPI;
1024     
1025     aTwoPI = M_PI + M_PI;
1026     
1027     gp_Vec aVx1(aPx, aPx1);
1028     gp_Dir aDBx1 (aVx1);
1029     gp_Pln aPlnToCompare (aPx, aDNFx1);
1030     
1031     gp_Vec aVx2(aPx, aPx2);
1032     gp_Dir aDBx2 (aVx2);
1033     
1034     anAlfa12=aDBx1.Angle(aDBx2);
1035     d12=BOPTools_Tools3D::SignDistance(aPx2, aPlnToCompare);
1036     if (d12 < 0.) {
1037       anAlfa12=aTwoPI-anAlfa12;
1038     }
1039     
1040     gp_Vec aVF1(aPx, aPF1);
1041     gp_Dir aDBF1 (aVF1);
1042     anAlfa1=aDBx1.Angle(aDBF1);
1043     d1=BOPTools_Tools3D::SignDistance(aPF1, aPlnToCompare);
1044     if (d1 < 0.) {
1045       anAlfa1=aTwoPI-anAlfa1;
1046     }
1047     
1048     aStPF1=TopAbs_OUT;
1049     if (anAlfa1 > anAlfa12) {
1050       aStPF1=TopAbs_IN;
1051     }
1052   }
1053 }
1054   
1055 //=======================================================================
1056 //function : Orientation
1057 //purpose  :
1058 //=======================================================================
1059   TopAbs_Orientation BOPTools_Tools3D::Orientation(const TopoDS_Edge& anE,
1060                                                    const TopoDS_Face& aF)
1061 {
1062   TopAbs_Orientation anOr=TopAbs_INTERNAL;
1063
1064   TopExp_Explorer anExp;
1065   anExp.Init(aF, TopAbs_EDGE);
1066   for (; anExp.More(); anExp.Next()) {
1067     const TopoDS_Edge& anEF1=TopoDS::Edge(anExp.Current());
1068     if (anEF1.IsEqual(anE)) {
1069       anOr=anEF1.Orientation();
1070       break;
1071     }
1072   }
1073   return anOr;
1074 }
1075
1076 //=======================================================================
1077 //function : SignDistance
1078 //purpose  :
1079 //=======================================================================
1080   Standard_Real BOPTools_Tools3D::SignDistance(const gp_Pnt& aP, 
1081                                                const gp_Pln& aPln)
1082 {
1083   Standard_Real A, B, C, D, d;
1084   aPln.Coefficients(A, B, C, D);
1085   //
1086   d   = A*aP.X() + B*aP.Y() + C*aP.Z() + D;
1087   
1088   return d;
1089 }
1090
1091 //=======================================================================
1092 // function: IsValidArea
1093 // purpose: 
1094 //=======================================================================
1095   Standard_Boolean BOPTools_Tools3D::IsValidArea (const TopoDS_Face& aF, 
1096                                                   Standard_Boolean& bNegativeFlag)
1097                                
1098 {
1099   Standard_Boolean bFlag;
1100   Standard_Real aMass, dM=1.e-16;
1101   GProp_GProps G;
1102   BRepGProp::SurfaceProperties(aF,G);
1103   aMass=G.Mass();
1104   //
1105   bFlag=(fabs(aMass)-dM > 0.);
1106   bNegativeFlag=(aMass < dM);
1107
1108   if( bNegativeFlag ) {
1109     Bnd_Box boxF;
1110     BRepBndLib::AddClose(aF, boxF);
1111     Standard_Real aXmin = 0, aYmin = 0., aZmin = 0., aXmax = 0., aYmax = 0., aZmax = 0.;
1112     boxF.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
1113     Standard_Boolean bigX = (fabs(aXmax-aXmin) >= 1.e+10);
1114     Standard_Boolean bigY = (fabs(aYmax-aYmin) >= 1.e+10);
1115     Standard_Boolean bigZ = (fabs(aZmax-aZmin) >= 1.e+10);
1116     if( !bigX && (!bigY && !bigZ) ) {
1117       TopExp_Explorer anExp;
1118       Standard_Integer nbW = 0;
1119       for(anExp.Init(aF, TopAbs_WIRE); anExp.More(); anExp.Next()) {
1120         const TopoDS_Wire& aW = TopoDS::Wire(anExp.Current());
1121         nbW++;
1122       }
1123       if( nbW == 1 ) {
1124         TopTools_IndexedDataMapOfShapeListOfShape mapVE;
1125         mapVE.Clear();
1126         TopExp::MapShapesAndAncestors(aF,TopAbs_VERTEX,TopAbs_EDGE,mapVE);
1127         Standard_Integer nbKeys = mapVE.Extent(), iKey = 0;
1128         Standard_Boolean changeFlag = Standard_True;
1129         for( iKey = 1; iKey <= nbKeys; iKey++ ) {
1130           const TopoDS_Vertex& iV = TopoDS::Vertex(mapVE.FindKey(iKey));
1131           if( iV.IsNull() ) continue;
1132           Standard_Real TolV = BRep_Tool::Tolerance(iV);
1133           const TopTools_ListOfShape& iLE = mapVE.FindFromIndex(iKey);
1134           Standard_Integer nbE = iLE.Extent();
1135           if( nbE != 2 ) {
1136             changeFlag = Standard_False;
1137             break;
1138           }
1139           const TopoDS_Edge& iE1 = TopoDS::Edge(iLE.First());
1140           const TopoDS_Edge& iE2 = TopoDS::Edge(iLE.Last());
1141           if(BRep_Tool::Degenerated(iE1) ||
1142              BRep_Tool::Degenerated(iE2) ) continue;
1143           Standard_Real iPE1 = BRep_Tool::Parameter(iV,iE1);
1144           Standard_Real iPE2 = BRep_Tool::Parameter(iV,iE2);
1145           Standard_Real pF1 = 0., pL1 = 0., pF2 = 0., pL2 = 0.;
1146           Handle(Geom_Curve) aC3D1 = BRep_Tool::Curve(iE1,pF1,pL1);
1147           Handle(Geom_Curve) aC3D2 = BRep_Tool::Curve(iE2,pF2,pL2);
1148           if( aC3D1.IsNull() || aC3D2.IsNull() ) {
1149             changeFlag = Standard_False;
1150             break;
1151           }
1152           if( Abs(Abs(pL1-pF1)-Abs(pL2-pF2)) <= 1.e-10 ) {
1153             changeFlag = Standard_False;
1154             break;
1155           }
1156           gp_Pnt aPnt1 = aC3D1->Value(iPE1);
1157           gp_Pnt aPnt2 = aC3D2->Value(iPE2);
1158           Standard_Real dist = aPnt1.Distance(aPnt2);
1159           Standard_Real TolE1 = BRep_Tool::Tolerance(iE1);
1160           Standard_Real TolE2 = BRep_Tool::Tolerance(iE2);
1161           if( dist > (/*TolV+*/TolE1+TolE2) ) {
1162             changeFlag = Standard_False;
1163             break;
1164           }
1165         }
1166         if( changeFlag ) bNegativeFlag = 0;
1167       }
1168     }
1169   }
1170
1171   //
1172   return bFlag;
1173 }
1174
1175 //=======================================================================
1176 // function: PointNearE
1177 // purpose: 
1178 //=======================================================================
1179 void PointNearE (const TopoDS_Edge& aE,
1180                  const TopoDS_Face& aF,
1181                  const Standard_Real aT,
1182                  gp_Pnt& aPInFace,
1183                  const Standard_Boolean aSt) 
1184 {
1185   Standard_Real aT1, aT2;
1186   //
1187   // 1. a Point on Edge aPOnEdge
1188   Handle(Geom_Curve)aC=BRep_Tool::Curve(aE, aT1, aT2);
1189   gp_Pnt aPOnEdge;
1190   gp_Pnt2d aPInFace2D;
1191   //
1192   aC->D0 (aT, aPOnEdge);
1193   //
1194   // 2. a Point inside Face near aPOnEdge aPInFace;
1195   TopoDS_Face aFF=aF;
1196   TopoDS_Edge aERight;
1197   aFF.Orientation(TopAbs_FORWARD);
1198   BOPTools_Tools3D::OrientEdgeOnFace (aE, aFF, aERight);
1199   //
1200   //
1201   Standard_Real aTolE, aDt2D;
1202   GeomAbs_SurfaceType aType;
1203   {
1204     aDt2D=BOPTools_Tools3D::MinStepIn2d();
1205     //
1206     Handle(Geom_Surface) aS=BRep_Tool::Surface(aFF);
1207     GeomAdaptor_Surface aGASF(aS);
1208     aType=aGASF.GetType();
1209     if (aType==GeomAbs_Plane) {
1210       aTolE=BRep_Tool::Tolerance(aE);
1211       if (aTolE>aDt2D) {
1212         aDt2D=aTolE;
1213       }
1214     }
1215     
1216   }
1217
1218   //-- EJG
1219   if( aSt )
1220     if( aDt2D < 1.e-4)
1221       aDt2D *= 10.;
1222   //-- EJG
1223
1224   //
1225   BOPTools_Tools3D::PointNearEdge (aERight, aFF, aT, aDt2D, aPInFace2D, aPInFace);
1226   //
1227   if (BRep_Tool::IsClosed(aE, aF)) {
1228     Standard_Real X, Y, UMin, UMax, VMin, VMax;
1229     X=aPInFace2D.X();
1230     Y=aPInFace2D.Y();
1231     BRepTools::UVBounds(aF, UMin, UMax, VMin, VMax);
1232     if (!(X >= UMin && X <= UMax && Y >= VMin && Y <= VMax)) {
1233       aERight.Reverse();
1234       BOPTools_Tools3D::PointNearEdge (aERight, aFF, aT, aPInFace2D, aPInFace);
1235     }
1236   }
1237   
1238 }
1239
1240 static Standard_Boolean PseudoSDFaces(const BRepAdaptor_Surface& BS1,
1241                                       const BRepAdaptor_Surface& BS2)
1242 {
1243   Standard_Real TolF1 = BS1.Tolerance();
1244   Standard_Real TolF2 = BS2.Tolerance();
1245
1246   gp_Pln Pln1 = BS1.Plane();
1247   gp_Pln Pln2 = BS2.Plane();
1248   
1249   TopExp_Explorer anExpE;
1250   Standard_Real pF = 0., pL = 0.;
1251
1252
1253   const TopoDS_Face& aF1 = BS1.Face();
1254   Standard_Real maxTolE1 = 1.e-7, maxTolV1 = 1.e-7;
1255   Standard_Integer nbE1 = 0, nbOnE1 = 0;
1256   for(anExpE.Init(aF1, TopAbs_EDGE); anExpE.More(); anExpE.Next()) {
1257     const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
1258     nbE1++;
1259     Standard_Real aTolE = BRep_Tool::Tolerance(aE);
1260     if( aTolE > maxTolE1 ) maxTolE1 = aTolE;
1261     Handle(Geom_Curve) aC3D = BRep_Tool::Curve(aE, pF, pL);
1262     if( !aC3D.IsNull() ) {
1263       Standard_Real pM = BOPTools_Tools2D::IntermediatePoint(pF, pL);
1264       gp_Pnt mPnt = aC3D->Value(pM);
1265       Standard_Real distMP = Pln2.Distance(mPnt);
1266
1267       if( distMP <= aTolE )
1268         nbOnE1++;
1269       else {
1270         TopoDS_Vertex Vf, Vl;
1271         TopExp::Vertices(aE,Vf,Vl);
1272         if( !Vf.IsNull() && !Vl.IsNull() ) {
1273           Standard_Real aTolVf = BRep_Tool::Tolerance(Vf);
1274           Standard_Real aTolVl = BRep_Tool::Tolerance(Vl);
1275           gp_Pnt aPntF = BRep_Tool::Pnt(Vf);
1276           gp_Pnt aPntL = BRep_Tool::Pnt(Vl);
1277           Standard_Real distF = Pln2.Distance(aPntF);
1278           Standard_Real distL = Pln2.Distance(aPntL);
1279           if( distF <= aTolVf && distL <= aTolVl )
1280             nbOnE1++;
1281         }
1282         else if( !Vf.IsNull() && Vl.IsNull() ) {
1283           Standard_Real aTolVf = BRep_Tool::Tolerance(Vf);
1284           gp_Pnt aPntF = BRep_Tool::Pnt(Vf);
1285           Standard_Real distF = Pln2.Distance(aPntF);
1286           if( distF <= aTolVf )
1287             nbOnE1++;
1288         }
1289         else if( Vf.IsNull() && !Vl.IsNull() ) {
1290           Standard_Real aTolVl = BRep_Tool::Tolerance(Vl);
1291           gp_Pnt aPntL = BRep_Tool::Pnt(Vl);
1292           Standard_Real distL = Pln2.Distance(aPntL);
1293           if( distL <= aTolVl )
1294             nbOnE1++;
1295         }
1296         else
1297           continue;
1298       }
1299     }
1300   }
1301
1302   Standard_Boolean procF1 = ((maxTolE1/TolF1) >= 1000. ||
1303                              (TolF1/maxTolE1) >= 1000.) ? Standard_True : Standard_False;
1304   procF1 = (procF1 && (nbE1 > 1 && nbOnE1 > 1) );
1305
1306   if( !procF1 )
1307     return Standard_False;
1308
1309   const TopoDS_Face& aF2 = BS1.Face();
1310   Standard_Real maxTolE2 = 1.e-7, maxTolV2 = 1.e-7;
1311   Standard_Integer nbE2 = 0, nbOnE2 = 0;
1312   for(anExpE.Init(aF2, TopAbs_EDGE); anExpE.More(); anExpE.Next()) {
1313     const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
1314     nbE2++;
1315     Standard_Real aTolE = BRep_Tool::Tolerance(aE);
1316     if( aTolE > maxTolE2 ) maxTolE2 = aTolE;
1317     Handle(Geom_Curve) aC3D = BRep_Tool::Curve(aE, pF, pL);
1318     if( !aC3D.IsNull() ) {
1319       Standard_Real pM = BOPTools_Tools2D::IntermediatePoint(pF, pL);
1320       gp_Pnt mPnt = aC3D->Value(pM);
1321       Standard_Real distMP = Pln1.Distance(mPnt);
1322       if( distMP <= aTolE )
1323         nbOnE2++;
1324       else {
1325         TopoDS_Vertex Vf, Vl;
1326         TopExp::Vertices(aE,Vf,Vl);
1327         if( !Vf.IsNull() && !Vl.IsNull() ) {
1328           Standard_Real aTolVf = BRep_Tool::Tolerance(Vf);
1329           Standard_Real aTolVl = BRep_Tool::Tolerance(Vl);
1330           gp_Pnt aPntF = BRep_Tool::Pnt(Vf);
1331           gp_Pnt aPntL = BRep_Tool::Pnt(Vl);
1332           Standard_Real distF = Pln1.Distance(aPntF);
1333           Standard_Real distL = Pln1.Distance(aPntL);
1334           if( distF <= aTolVf && distL <= aTolVl )
1335             nbOnE2++;
1336         }
1337         else if( !Vf.IsNull() && Vl.IsNull() ) {
1338           Standard_Real aTolVf = BRep_Tool::Tolerance(Vf);
1339           gp_Pnt aPntF = BRep_Tool::Pnt(Vf);
1340           Standard_Real distF = Pln1.Distance(aPntF);
1341           if( distF <= aTolVf )
1342             nbOnE2++;
1343         }
1344         else if( Vf.IsNull() && !Vl.IsNull() ) {
1345           Standard_Real aTolVl = BRep_Tool::Tolerance(Vl);
1346           gp_Pnt aPntL = BRep_Tool::Pnt(Vl);
1347           Standard_Real distL = Pln1.Distance(aPntL);
1348           if( distL <= aTolVl )
1349             nbOnE2++;
1350         }
1351         else
1352           continue;
1353       }
1354     }
1355   }
1356
1357   Standard_Boolean procF2 = ((maxTolE2/TolF2) >= 1000. ||
1358                              (TolF2/maxTolE2) >= 1000.) ? Standard_True : Standard_False;
1359   procF2 = (procF2 && (nbE2 > 1 && nbOnE2 > 1) );
1360
1361   return (procF1 && procF2);
1362
1363 }
1364
1365 Standard_Boolean CheckKeepArguments(const TopoDS_Face& F1,
1366                                     const TopoDS_Face& F2,
1367                                     const TopoDS_Face& F3)
1368 {
1369   BRepAdaptor_Surface aBS1(F1);
1370   BRepAdaptor_Surface aBS2(F2);
1371   BRepAdaptor_Surface aBS3(F3);
1372   
1373   GeomAbs_SurfaceType aT1 = aBS1.GetType();
1374   GeomAbs_SurfaceType aT2 = aBS2.GetType();
1375   GeomAbs_SurfaceType aT3 = aBS3.GetType();
1376   
1377   if(aT1 == GeomAbs_Cylinder ||
1378      aT1 == GeomAbs_Cone ||
1379      aT1 ==  GeomAbs_Sphere ||
1380      aT1 == GeomAbs_Torus ) return Standard_True;
1381
1382   if(aT2 == GeomAbs_Cylinder ||
1383      aT2 == GeomAbs_Cone ||
1384      aT3 ==  GeomAbs_Sphere ||
1385      aT3 == GeomAbs_Torus ) return Standard_True;
1386
1387   if(aT3 == GeomAbs_Cylinder ||
1388      aT3 == GeomAbs_Cone ||
1389      aT3 ==  GeomAbs_Sphere ||
1390      aT3 == GeomAbs_Torus ) return Standard_True;
1391
1392   if( aT1 == GeomAbs_Plane && aT2 == GeomAbs_Plane ) {
1393     if( PseudoSDFaces(aBS1, aBS2) )
1394       return Standard_False;
1395   }
1396   else if( aT1 == GeomAbs_Plane && aT3 == GeomAbs_Plane ) {
1397     if( PseudoSDFaces(aBS1, aBS3) )
1398       return Standard_False;
1399   }
1400   else if( aT2 == GeomAbs_Plane && aT3 == GeomAbs_Plane ) {
1401     if( PseudoSDFaces(aBS2, aBS3) )
1402       return Standard_False;
1403   }
1404   else
1405     return Standard_True;
1406   return Standard_True;
1407 }