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