0030675: Visualization - remove redundant proxy classes in hierarchy of PrsMgr_Presen...
[occt.git] / src / BOPTools / BOPTools_AlgoTools3D.cxx
1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
3 //
4 // This file is part of Open CASCADE Technology software library.
5 //
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
11 //
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
14
15
16 #include <Bnd_Box.hxx>
17 #include <BOPTools_AlgoTools2D.hxx>
18 #include <BOPTools_AlgoTools3D.hxx>
19 #include <BRep_Builder.hxx>
20 #include <BRep_CurveRepresentation.hxx>
21 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
22 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
23 #include <BRep_PointRepresentation.hxx>
24 #include <BRep_TEdge.hxx>
25 #include <BRep_TFace.hxx>
26 #include <BRep_Tool.hxx>
27 #include <BRep_TVertex.hxx>
28 #include <BRepBndLib.hxx>
29 #include <BRepGProp.hxx>
30 #include <BRepTools.hxx>
31 #include <Geom2d_Curve.hxx>
32 #include <Geom2d_Line.hxx>
33 #include <Geom2d_TrimmedCurve.hxx>
34 #include <Geom2dAdaptor_Curve.hxx>
35 #include <Geom2dHatch_Hatcher.hxx>
36 #include <Geom_BezierSurface.hxx>
37 #include <Geom_BSplineSurface.hxx>
38 #include <Geom_Curve.hxx>
39 #include <Geom_RectangularTrimmedSurface.hxx>
40 #include <Geom_Surface.hxx>
41 #include <GeomAdaptor_Surface.hxx>
42 #include <gp_Cylinder.hxx>
43 #include <gp_Dir.hxx>
44 #include <gp_Dir2d.hxx>
45 #include <gp_Lin2d.hxx>
46 #include <gp_Pln.hxx>
47 #include <gp_Pnt.hxx>
48 #include <gp_Pnt2d.hxx>
49 #include <gp_Vec.hxx>
50 #include <gp_Vec2d.hxx>
51 #include <GProp_GProps.hxx>
52 #include <HatchGen_Domain.hxx>
53 #include <IntTools_Context.hxx>
54 #include <IntTools_Tools.hxx>
55 #include <Poly_Triangulation.hxx>
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58 #include <TopoDS.hxx>
59 #include <TopoDS_Edge.hxx>
60 #include <TopoDS_Face.hxx>
61 #include <TopoDS_Shape.hxx>
62 #include <TopoDS_Vertex.hxx>
63 #include <TopTools_IndexedMapOfShape.hxx>
64
65 static void Add(const TopoDS_Shape& aS,
66                 TopTools_IndexedMapOfShape& myShapes, 
67                 Standard_Boolean& bHasGeometry);
68 static 
69   Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
70
71 //=======================================================================
72 //function : DoSplitSEAMOnFace
73 //purpose  : 
74 //=======================================================================
75 void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
76                                               const TopoDS_Face& aF)
77 {
78   Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft;
79   Standard_Real aTol, a, b, anUPeriod, anVPeriod, aT, anU, dU, anU1;
80   Standard_Real aScPr, anV, dV, anV1;
81   Standard_Real aUmin, aUmax, aVmin, aVmax;
82   gp_Pnt2d aP2D;
83   gp_Vec2d aVec2D;
84   Handle(Geom2d_Curve) aTmpC1, aTmpC2;
85   Handle(Geom2d_Curve) C2D1;
86   Handle(Geom2d_Line) aLD1;
87   Handle(Geom_Surface) aS;
88   BRep_Builder BB;
89   TopoDS_Edge aSp;
90   //
91   bIsLeft = Standard_False;
92   aSp=aSplit;
93   aSp.Orientation(TopAbs_FORWARD);
94   aTol=BRep_Tool::Tolerance(aSp);
95   //
96   aS=BRep_Tool::Surface(aF);
97   //
98   aS->Bounds(aUmin, aUmax, aVmin, aVmax);
99   //
100   bIsUPeriodic=aS->IsUPeriodic();
101   bIsVPeriodic=aS->IsVPeriodic();
102   //
103   anUPeriod = bIsUPeriodic ? aS->UPeriod() : 0.;
104   anVPeriod = bIsVPeriodic ? aS->VPeriod() : 0.;
105   //
106   if (!bIsUPeriodic && !bIsVPeriodic) {
107     Standard_Boolean bIsUClosed, bIsVClosed;
108     Handle(Geom_BSplineSurface) aBS;
109     Handle(Geom_BezierSurface) aBZ;
110     Handle(Geom_RectangularTrimmedSurface) aRTS;
111     //
112     bIsUClosed=Standard_False;
113     bIsVClosed=Standard_False;
114     aBS=Handle(Geom_BSplineSurface)::DownCast(aS);
115     aBZ=Handle(Geom_BezierSurface) ::DownCast(aS);
116     aRTS=Handle(Geom_RectangularTrimmedSurface)::DownCast(aS);
117     //
118     if (!aBS.IsNull()) {
119       bIsUClosed=aBS->IsUClosed();
120       bIsVClosed=aBS->IsVClosed();
121     }
122     else if (!aBZ.IsNull()) {
123       bIsUClosed=aBZ->IsUClosed();
124       bIsVClosed=aBZ->IsVClosed();
125     }
126     else if (!aRTS.IsNull()) {
127       Handle(Geom_Surface) aSB;
128       //
129       aSB=aRTS->BasisSurface();
130       bIsUPeriodic=aSB->IsUPeriodic();
131       bIsVPeriodic=aSB->IsVPeriodic();
132       //
133       if (!(bIsUPeriodic || bIsVPeriodic)) {
134         return;
135       }
136       anUPeriod = bIsUPeriodic ? aSB->UPeriod() : 0.;
137       anVPeriod = bIsVPeriodic ? aSB->VPeriod() : 0.;
138     }
139     //
140     if (aRTS.IsNull()) {
141       if (!bIsUClosed && !bIsVClosed) {
142         return;
143       }
144       //
145       if (bIsUClosed) {
146         anUPeriod=aUmax-aUmin;
147       }
148       if (bIsVClosed) {
149         anVPeriod=aVmax-aVmin;
150       }
151     }
152   }
153   //
154   //---------------------------------------------------
155   C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
156   //
157   aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
158   C2D1->D1(aT, aP2D, aVec2D);
159   gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.);
160   //
161   anU=aP2D.X();
162   anV=aP2D.Y();
163   //
164   anU1=anU;
165   anV1=anV;
166   //
167   GeomAdaptor_Surface aGAS(aS);
168   dU = aGAS.UResolution(aTol);
169   dV = aGAS.VResolution(aTol);
170   //
171   if (anUPeriod > 0.){
172     if (fabs (anU-aUmin) < dU) {
173       bIsLeft=Standard_True;
174       anU1=anU+anUPeriod;
175     }
176     else if (fabs (anU-aUmax) < dU) {
177       bIsLeft=Standard_False;
178       anU1=anU-anUPeriod;
179     }
180   }
181   //
182   if (anVPeriod > 0.) {
183     if (fabs (anV-aVmin) < dV) {
184       bIsLeft=Standard_True;
185       anV1=anV+anVPeriod;
186     }
187     else if (fabs (anV-aVmax) < dV) {
188       bIsLeft=Standard_False;
189       anV1=anV-anVPeriod;
190     }
191   }
192   //
193   if (anU1==anU && anV1==anV) {
194     return;
195   }
196   //
197   aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
198   //
199   aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
200   Handle(Geom2d_TrimmedCurve) aC1 = 
201     new Geom2d_TrimmedCurve(aTmpC1, a, b);
202   //
203   aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
204   Handle(Geom2d_TrimmedCurve) aC2 = 
205     new Geom2d_TrimmedCurve(aTmpC2, a, b);
206   gp_Vec2d aTrV(anU1-anU, anV1-anV);
207   aC2->Translate(aTrV);
208   //
209   if (!bIsLeft) {
210     if (aScPr<0.) {
211       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
212     }
213     else {
214       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
215     }
216   }
217   else {
218     if (aScPr<0.) {
219       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
220     }
221     else {
222       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
223     }
224   }
225 }
226 //=======================================================================
227 //function : GetNormalToFaceOnEdge
228 //purpose  : 
229 //=======================================================================
230 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
231                                                   const TopoDS_Face& aF,
232                                                   gp_Dir& aDNF,
233                                                   const Handle(IntTools_Context)& theContext)
234 {
235   Standard_Real aT, aT1, aT2;
236   
237   BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
238   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
239
240   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF, theContext);
241
242   if (aF.Orientation()==TopAbs_REVERSED){
243     aDNF.Reverse();
244   }
245 }
246 //=======================================================================
247 //function : GetNormalToFaceOnEdge
248 //purpose  : 
249 //=======================================================================
250 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
251                                                   const TopoDS_Face& aF1,
252                                                   const Standard_Real aT, 
253                                                   gp_Dir& aDNF1,
254                                                   const Handle(IntTools_Context)& theContext)
255 {
256   Standard_Real U, V, aTolPC;
257   gp_Pnt2d aP2D;
258   gp_Pnt aP;
259   gp_Vec aD1U, aD1V;
260
261   Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
262   
263   Handle(Geom2d_Curve)aC2D1;
264   BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC, theContext);
265
266   aC2D1->D0(aT, aP2D);
267   U=aP2D.X();
268   V=aP2D.Y();
269   
270   aS1->D1(U, V, aP, aD1U, aD1V);
271   gp_Dir aDD1U(aD1U); 
272   gp_Dir aDD1V(aD1V); 
273   
274   aDNF1=aDD1U^aDD1V; 
275 }
276 //=======================================================================
277 //function : SenseFlag
278 //purpose  :
279 //=======================================================================
280 Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1,
281                                                   const gp_Dir& aDNF2)
282 {
283   Standard_Boolean bIsDirsCoinside;
284   //
285   bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
286   if (!bIsDirsCoinside) {
287     return 0;
288   }
289   
290   Standard_Real aScPr;
291   
292   aScPr=aDNF1*aDNF2;
293   if (aScPr<0.) {
294     return -1;
295   }
296   else if (aScPr>0.) {
297     return 1;
298   }
299   return -1;
300 }
301 //=======================================================================
302 //function : GetNormalToSurface
303 //purpose  :
304 //=======================================================================
305 Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface
306   (const Handle(Geom_Surface)& aS,
307    const Standard_Real U,
308    const Standard_Real V,
309    gp_Dir& aDNS)
310 {
311   gp_Pnt aP;
312   gp_Vec aD1U, aD1V;
313
314   aS->D1(U, V, aP, aD1U, aD1V);
315
316   Standard_Real aLenU = aD1U.SquareMagnitude();
317   if (aLenU < gp::Resolution())
318     return Standard_False;
319
320   Standard_Real aLenV = aD1V.SquareMagnitude();
321   if (aLenV < gp::Resolution())
322     return Standard_False;
323
324   gp_Dir aDD1U(aD1U);
325   gp_Dir aDD1V(aD1V);
326
327   Standard_Boolean bFlag = IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
328   if (!bFlag)
329     return bFlag;
330
331   aDNS = aDD1U^aDD1V;
332   return bFlag;
333 }
334 //=======================================================================
335 //function : GetApproxNormalToFaceOnEdge
336 //purpose  : 
337 //=======================================================================
338 Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
339   (const TopoDS_Edge& aE,
340    const TopoDS_Face& aF,
341    const Standard_Real aT,
342    gp_Pnt& aPNear,
343    gp_Dir& aDNF,
344    Standard_Real aDt2D)
345 {
346   gp_Pnt2d aPx2DNear;
347   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge
348     (aE, aF, aT, aDt2D, aPx2DNear, aPNear);
349   if (iErr != 1) {
350     Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
351   
352     BOPTools_AlgoTools3D::GetNormalToSurface 
353       (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
354   
355     if (aF.Orientation()==TopAbs_REVERSED){
356       aDNF.Reverse();
357     }
358   }
359   //
360   return (iErr == 0);
361 }
362 //=======================================================================
363 //function : GetApproxNormalToFaceOnEdge
364 //purpose  : 
365 //=======================================================================
366 Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge 
367   (const TopoDS_Edge& aE,
368    const TopoDS_Face& aF,
369    const Standard_Real aT,
370    gp_Pnt& aPNear,
371    gp_Dir& aDNF,
372    const Handle(IntTools_Context)& theContext)
373 {
374   gp_Pnt2d aPx2DNear;
375   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge 
376     (aE, aF, aT, aPx2DNear, aPNear, theContext);
377   if (iErr != 1) {
378     Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
379   
380     BOPTools_AlgoTools3D::GetNormalToSurface 
381       (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
382   
383     if (aF.Orientation()==TopAbs_REVERSED){
384       aDNF.Reverse();
385     }
386   }
387   //
388   return (iErr == 0);
389 }
390 //=======================================================================
391 //function : GetApproxNormalToFaceOnEdge
392 //purpose  : 
393 //=======================================================================
394 Standard_Boolean BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge 
395   (const TopoDS_Edge& aE,
396    const TopoDS_Face& aF,
397    const Standard_Real aT,
398    const Standard_Real theStep,
399    gp_Pnt& aPNear,
400    gp_Dir& aDNF,
401    const Handle(IntTools_Context)& theContext)
402 {
403   gp_Pnt2d aPx2DNear;
404   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge 
405     (aE, aF, aT, theStep, aPx2DNear, aPNear, theContext);
406   if (iErr != 1) {
407     Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
408   
409     BOPTools_AlgoTools3D::GetNormalToSurface 
410       (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
411   
412     if (aF.Orientation()==TopAbs_REVERSED){
413       aDNF.Reverse();
414     }
415   }
416   //
417   return (iErr == 0);
418 }
419 //=======================================================================
420 //function : PointNearEdge
421 //purpose  : 
422 //=======================================================================
423 Standard_Integer BOPTools_AlgoTools3D::PointNearEdge 
424   (const TopoDS_Edge& aE,
425    const TopoDS_Face& aF,
426    const Standard_Real aT, 
427    const Standard_Real aDt2D, 
428    gp_Pnt2d& aPx2DNear,
429    gp_Pnt& aPxNear)
430 {
431   Standard_Real aFirst, aLast, aETol, aFTol, transVal;
432   GeomAbs_SurfaceType aTS;
433   Handle(Geom2d_Curve) aC2D;
434   Handle(Geom_Surface) aS;
435   //
436   aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
437   Standard_Integer iErr = aC2D.IsNull() ? 1 : 0;
438   if (iErr) {
439     return iErr;
440   }
441   //
442   aS=BRep_Tool::Surface(aF);
443   //
444   gp_Pnt2d aPx2D;
445   gp_Vec2d aVx2D;
446   aC2D->D1 (aT, aPx2D, aVx2D);
447   gp_Dir2d aDx2D(aVx2D);
448   
449   gp_Dir2d aDP;
450   aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
451   
452   if (aE.Orientation()==TopAbs_REVERSED){
453     aDP.Reverse();
454   }
455
456   if (aF.Orientation()==TopAbs_REVERSED) {
457     aDP.Reverse();
458   }
459   //
460   aETol = BRep_Tool::Tolerance(aE);
461   aFTol = BRep_Tool::Tolerance(aF);
462   // NPAL19220
463   GeomAdaptor_Surface aGAS(aS);
464   aTS=aGAS.GetType();
465   if (aTS==GeomAbs_BSplineSurface) {
466     if (aETol > 1.e-5) {
467       aFTol=aETol;
468     }
469   }
470   if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
471     //
472     if(aTS!=GeomAbs_Sphere) {
473       gp_Vec2d transVec( aDP );
474       transVal = aDt2D + aETol + aFTol;
475       if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
476         Standard_Real aR, dT;
477         //
478         gp_Cylinder aCyl=aGAS.Cylinder();
479         aR=aCyl.Radius();
480         dT=1.-transVal/aR;
481         if (dT>=-1 && dT<=1) {
482           dT=acos(dT);
483           transVal=dT;
484         }
485       }
486       //
487       transVec.Multiply(transVal);
488       aPx2DNear = aPx2D.Translated( transVec );
489     }
490     else {
491       aPx2DNear.SetCoord 
492         (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
493     }
494   }
495   else {
496     aPx2DNear.SetCoord 
497       (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
498   }
499   //
500   aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
501   return iErr;
502 }
503 //=======================================================================
504 //function : PointNearEdge
505 //purpose  : 
506 //=======================================================================
507 Standard_Integer BOPTools_AlgoTools3D::PointNearEdge 
508   (const TopoDS_Edge& aE,
509    const TopoDS_Face& aF,
510    const Standard_Real aT, 
511    gp_Pnt2d& aPx2DNear,
512    gp_Pnt& aPxNear,
513    const Handle(IntTools_Context)& theContext)
514 {
515   Standard_Real aTolE, aTolF, dTx, dT2D;
516   Handle(Geom_Surface) aS;
517   GeomAdaptor_Surface aGAS;
518   //
519   dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5;
520   //
521   aS = BRep_Tool::Surface(aF);
522   aGAS.Load(aS);
523   if (aGAS.GetType()==GeomAbs_Cylinder ||
524       aGAS.GetType()==GeomAbs_Sphere) {
525     dT2D=10.*dT2D;
526   }
527   //
528   aTolE = BRep_Tool::Tolerance(aE);
529   aTolF = BRep_Tool::Tolerance(aF);
530   dTx = 2.*(aTolE + aTolF);
531   if (dTx > dT2D) {
532     dT2D=dTx;
533   }
534   //
535   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge 
536     (aE, aF, aT, dT2D, aPx2DNear, aPxNear);
537   if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) {
538     gp_Pnt aP;
539     gp_Pnt2d aP2d;
540     //
541     iErr = BOPTools_AlgoTools3D::PointInFace
542       (aF, aE, aT, dT2D, aP, aP2d, theContext);
543     if (iErr == 0) {
544       aPxNear = aP;
545       aPx2DNear = aP2d;
546     }
547     else {
548       iErr = 2; // point is out of the face
549     }
550   }
551   //
552   return iErr;
553 }
554
555 //=======================================================================
556 //function : PointNearEdge
557 //purpose  : 
558 //=======================================================================
559 Standard_Integer BOPTools_AlgoTools3D::PointNearEdge 
560   (const TopoDS_Edge& aE,
561    const TopoDS_Face& aF,
562    const Standard_Real aT, 
563    const Standard_Real theStep,
564    gp_Pnt2d& aPx2DNear,
565    gp_Pnt& aPxNear,
566    const Handle(IntTools_Context)& theContext)
567 {
568   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge 
569     (aE, aF, aT, theStep, aPx2DNear, aPxNear);
570   if ((iErr != 1) && !theContext->IsPointInOnFace(aF, aPx2DNear)) {
571     gp_Pnt aP;
572     gp_Pnt2d aP2d;
573     //
574     iErr = BOPTools_AlgoTools3D::PointInFace
575       (aF, aE, aT, theStep, aP, aP2d, theContext);
576     if (iErr == 0) {
577       aPxNear = aP;
578       aPx2DNear = aP2d;
579     }
580     else {
581       iErr = 2; // point is out of the face
582     }
583   }
584   //
585   return iErr;
586 }
587 //=======================================================================
588 // function: PointNearEdge
589 // purpose: 
590 //=======================================================================
591 Standard_Integer BOPTools_AlgoTools3D::PointNearEdge
592   (const TopoDS_Edge& aE,
593    const TopoDS_Face& aF, 
594    gp_Pnt2d& aPInFace2D, 
595    gp_Pnt& aPInFace,
596    const Handle(IntTools_Context)& theContext)
597 {
598   Standard_Real aT, aT1, aT2;
599   //
600   // 1. compute parameter on edge
601   BRep_Tool::Range(aE, aT1, aT2);
602   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
603   //
604   // 2. compute point inside the face near the edge
605   TopoDS_Face aFF=aF;
606   TopoDS_Edge aERight;
607   aFF.Orientation(TopAbs_FORWARD);
608   BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight);
609   //
610   Standard_Integer iErr = BOPTools_AlgoTools3D::PointNearEdge 
611     (aERight, aFF, aT, aPInFace2D, aPInFace, theContext);
612   //
613   return iErr;
614 }
615 //=======================================================================
616 //function : MinStepIn2d
617 //purpose  : 
618 //=======================================================================
619 Standard_Real BOPTools_AlgoTools3D::MinStepIn2d()
620 {
621   Standard_Real dt=1.e-5;
622   return dt;
623
624 //=======================================================================
625 //function : IsEmptyShape
626 //purpose  : 
627 //=======================================================================
628 Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape
629   (const TopoDS_Shape& aS)
630 {
631   Standard_Boolean bHasGeometry=Standard_False;
632   //
633   TopTools_IndexedMapOfShape myShapes;
634   //
635   Add(aS, myShapes, bHasGeometry);
636
637   return !bHasGeometry;
638 }
639 //=======================================================================
640 //function : Add
641 //purpose  : 
642 //=======================================================================
643 void Add(const TopoDS_Shape& aS,
644          TopTools_IndexedMapOfShape& myShapes, 
645          Standard_Boolean& bHasGeometry)
646 {
647   Standard_Integer anIndex; 
648   //
649   if (bHasGeometry) {
650     return;
651   }
652   //
653   if (aS.IsNull()) {
654     return;
655   }
656   //
657   TopoDS_Shape aSx = aS;
658   //
659   anIndex=myShapes.FindIndex(aSx);
660   if (!anIndex) {
661     bHasGeometry=HasGeometry (aSx);
662     if (bHasGeometry) {
663       return;
664     }
665     //
666     TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
667     for(; anIt.More(); anIt.Next()) {
668       const TopoDS_Shape& aSy=anIt.Value();
669       Add(aSy, myShapes, bHasGeometry);
670       //
671       if (bHasGeometry) {
672         return;
673       }
674       //
675       myShapes.Add(aSx);
676     }
677   }
678 }
679 //=======================================================================
680 //function : HasGeometry
681 //purpose  : 
682 //=======================================================================
683 Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
684 {
685   Standard_Boolean bHasGeometry=Standard_True;
686   TopAbs_ShapeEnum aType= aS.ShapeType();
687
688   if (aType == TopAbs_VERTEX) {
689     return bHasGeometry;
690   }
691   //
692   else if (aType == TopAbs_EDGE) {
693     Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
694     BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
695
696     while (itrc.More()) {
697       const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
698       if (CR->IsCurve3D()) {
699         if (!CR->Curve3D().IsNull()) {
700           return bHasGeometry;
701         }
702       }
703       else if (CR->IsCurveOnSurface()) {
704         return bHasGeometry;
705       }
706       else if (CR->IsRegularity()) {
707         return bHasGeometry;
708       }
709       else if (!CR->Polygon3D().IsNull()) {
710         return bHasGeometry;
711       }
712       else if (CR->IsPolygonOnTriangulation()) {
713         return bHasGeometry;
714       }
715       else if (CR->IsPolygonOnSurface()) {
716         return bHasGeometry;
717       }
718       itrc.Next();
719     }
720   }
721   //
722   else if (aType == TopAbs_FACE) {
723     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
724     if (!TF->Surface().IsNull())  {
725       return bHasGeometry;
726     }
727     Handle(Poly_Triangulation) Tr = TF->Triangulation();
728     if (!Tr.IsNull()) {
729       return bHasGeometry;
730     }
731   }
732   
733   return !bHasGeometry;
734 }
735 //=======================================================================
736 //function : OrientEdgeOnFace
737 //purpose  : 
738 //=======================================================================
739 void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
740                                              const TopoDS_Face& aF,
741                                              TopoDS_Edge& aERight)
742 {
743   if (BRep_Tool::IsClosed(aE, aF)) {
744     aERight=aE;
745     aERight.Orientation(aE.Orientation());
746
747     Standard_Integer iFoundCount = 0;
748     TopoDS_Edge anEdge = aE;
749     TopExp_Explorer anExp(aF, TopAbs_EDGE);
750
751     for (; anExp.More(); anExp.Next()) {
752       const TopoDS_Shape& aSS=anExp.Current();
753       
754       if (aSS.IsSame(aE)) {
755         anEdge = TopoDS::Edge(aSS);
756         iFoundCount++;
757       }
758     }
759     
760     if(iFoundCount == 1) {
761       aERight = anEdge;
762     }
763     return;
764   }
765   
766   TopExp_Explorer anExp(aF, TopAbs_EDGE);
767   for (; anExp.More(); anExp.Next()) {
768     const TopoDS_Shape& aSS=anExp.Current();
769     if (aSS.IsSame(aE)) {
770       aERight=aE;
771       aERight.Orientation(aSS.Orientation());
772       return;
773     }
774   }
775   aERight=aE;
776   aERight.Orientation(aE.Orientation());
777 }
778 //=======================================================================
779 //function : PointInFace
780 //purpose  :
781 //=======================================================================
782 Standard_Integer BOPTools_AlgoTools3D::PointInFace
783   (const TopoDS_Face& theF,
784    gp_Pnt& theP,
785    gp_Pnt2d& theP2D,
786    const Handle(IntTools_Context)& theContext)
787 {
788   Standard_Integer i, iErr = 1;
789   Standard_Real aUMin, aUMax, aVMin, aVMax, aUx;
790   //
791   theContext->UVBounds(theF, aUMin, aUMax, aVMin, aVMax);
792   //
793   gp_Dir2d aD2D(0. , 1.);
794   aUx = IntTools_Tools::IntermediatePoint(aUMin, aUMax);
795   //
796   for (i = 0; i < 2; ++i) {
797     gp_Pnt2d aP2D(aUx, 0.);
798     Handle(Geom2d_Line) aL2D = new Geom2d_Line (aP2D, aD2D);
799     iErr = BOPTools_AlgoTools3D::PointInFace
800       (theF, aL2D, theP, theP2D, theContext);
801     if (iErr == 0) {
802       // done
803       break;
804     }
805     else {
806       // possible reason - incorrect computation of the 2d box of the face.
807       // try to compute the point with the translated line.
808       aUx = aUMax - (aUx - aUMin);
809     }
810   }
811   //
812   return iErr;
813 }
814 //=======================================================================
815 //function : PointInFace
816 //purpose  :
817 //=======================================================================
818 Standard_Integer BOPTools_AlgoTools3D::PointInFace
819   (const TopoDS_Face& theF,
820    const TopoDS_Edge& theE,
821    const Standard_Real theT,
822    const Standard_Real theDt2D,
823    gp_Pnt& theP,
824    gp_Pnt2d& theP2D,
825    const Handle(IntTools_Context)& theContext)
826 {
827   Standard_Integer iErr;
828   Standard_Real f, l;
829   Handle(Geom2d_Curve) aC2D;
830   //
831   iErr = 0;
832   aC2D = BRep_Tool::CurveOnSurface (theE, theF, f, l);
833   if (aC2D.IsNull()) {
834     iErr = 5;
835     return iErr;
836   }
837   //
838   gp_Pnt2d aP2D;
839   gp_Vec2d aV2D;
840   //
841   aC2D->D1(theT, aP2D, aV2D);
842   gp_Dir2d aD2Dx(aV2D);
843   //
844   gp_Dir2d aD2D;
845   aD2D.SetCoord (-aD2Dx.Y(), aD2Dx.X());
846   //
847   if (theE.Orientation()==TopAbs_REVERSED){
848     aD2D.Reverse();
849   }
850   //
851   if (theF.Orientation()==TopAbs_REVERSED) {
852     aD2D.Reverse();
853   }
854   //
855   Handle(Geom2d_Line) aL2D = new Geom2d_Line(aP2D, aD2D);
856   Handle(Geom2d_TrimmedCurve) aL2DTrim =
857     new Geom2d_TrimmedCurve(aL2D, 0., Precision::Infinite());
858   //
859   iErr = BOPTools_AlgoTools3D::PointInFace
860     (theF, aL2DTrim, theP, theP2D, theContext, theDt2D);
861   //
862   return iErr;
863 }
864 //=======================================================================
865 //function : PointInFace
866 //purpose  :
867 //=======================================================================
868 Standard_Integer BOPTools_AlgoTools3D::PointInFace
869   (const TopoDS_Face& theF,
870    const Handle(Geom2d_Curve)& theL2D,
871    gp_Pnt& theP,
872    gp_Pnt2d& theP2D,
873    const Handle(IntTools_Context)& theContext,
874    const Standard_Real theDt2D)
875 {
876   Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
877   Standard_Integer iErr, aIH, aNbDomains;
878   Standard_Real aVx, aV1, aV2;
879   //
880   Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(theF);
881   //
882   Geom2dAdaptor_Curve aHCur(theL2D);
883   //
884   aHatcher.ClrHatchings();
885   aIH = aHatcher.AddHatching(aHCur);
886   //
887   iErr = 0;
888   for (;;) {
889     aHatcher.Trim();
890     bIsDone = aHatcher.TrimDone(aIH);
891     if (!bIsDone) {
892       iErr = 1;
893       break;
894     }
895     //
896     aHatcher.ComputeDomains(aIH);
897     bIsDone = aHatcher.IsDone(aIH);
898     if (!bIsDone) {
899       iErr = 2;
900       break;
901     }
902     //
903     aNbDomains = aHatcher.NbDomains(aIH);
904     if (aNbDomains == 0) {
905       iErr = 2;
906       break;
907     }
908     //
909     const HatchGen_Domain& aDomain = aHatcher.Domain (aIH, 1);
910     bHasFirstPoint = aDomain.HasFirstPoint();
911     if (!bHasFirstPoint) {
912       iErr = 3;
913       break;
914     }
915     //
916     bHasSecondPoint = aDomain.HasSecondPoint();
917     if (!bHasSecondPoint) {
918       iErr = 4;
919       break;
920     }
921     //
922     aV1 = aDomain.FirstPoint().Parameter();
923     aV2 = aDomain.SecondPoint().Parameter();
924     //
925     aVx = (theDt2D > 0. && (aV2 - aV1) > theDt2D) ? (aV1 + theDt2D) :
926       IntTools_Tools::IntermediatePoint(aV1, aV2);
927     //
928     Handle(Geom_Surface) aS = BRep_Tool::Surface(theF);
929     //
930     theL2D->D0(aVx, theP2D);
931     aS->D0(theP2D.X(), theP2D.Y(), theP);
932     break;
933   }
934   //
935   aHatcher.RemHatching(aIH);
936   return iErr;
937 }