1231b73f99afa43acf9d1f1dfbb22f47e69108c1
[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 #include <BOPTools_AlgoTools3D.ixx>
16
17 #include <TopExp.hxx>
18 #include <TopExp_Explorer.hxx>
19
20 #include <TopoDS.hxx>
21 #include <TopoDS_Shape.hxx>
22 #include <TopoDS_Edge.hxx>
23 #include <TopoDS_Face.hxx>
24 #include <TopoDS_Vertex.hxx>
25
26 #include <BOPCol_IndexedMapOfShape.hxx>
27 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
28
29 #include <BRep_Builder.hxx>
30 #include <BRep_Tool.hxx>
31 #include <BRepTools.hxx>
32 #include <BRepAdaptor_Surface.hxx>
33
34 #include <gp_Vec2d.hxx>
35 #include <gp_Pnt2d.hxx>
36 #include <gp_Lin2d.hxx>
37 #include <gp_Dir2d.hxx>
38 #include <gp_Vec.hxx>
39 #include <gp_Dir.hxx>
40 #include <gp_Pln.hxx>
41
42 #include <Geom2d_Curve.hxx>
43 #include <Geom2d_TrimmedCurve.hxx>
44 #include <Geom2d_Line.hxx>
45
46 #include <Geom_Curve.hxx>
47 #include <Geom_Surface.hxx>
48 #include <Geom_BSplineSurface.hxx>
49 #include <Geom_BezierSurface.hxx>
50
51 #include <GeomAdaptor_Surface.hxx>
52
53 #include <IntTools_Tools.hxx>
54
55 #include <BOPTools_AlgoTools2D.hxx>
56
57 #include <GProp_GProps.hxx>
58 #include <BRepGProp.hxx>
59 #include <BRepBndLib.hxx>
60 #include <Bnd_Box.hxx>
61 #include <gp_Cylinder.hxx>
62 #include <BRep_TVertex.hxx>
63 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
64 #include <BRep_PointRepresentation.hxx>
65 #include <BRep_TEdge.hxx>
66 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
67 #include <BRep_CurveRepresentation.hxx>
68 #include <BRep_TFace.hxx>
69 #include <Poly_Triangulation.hxx>
70 #include <BRep_Builder.hxx>
71 #include <IntTools_Context.hxx>
72 #include <Geom2dAdaptor_Curve.hxx>
73 #include <Geom2dHatch_Hatcher.hxx>
74 #include <HatchGen_Domain.hxx>
75
76 static void Add(const TopoDS_Shape& aS,
77                 BOPCol_IndexedMapOfShape& myShapes, 
78                 Standard_Boolean& bHasGeometry);
79 static 
80   Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
81
82 //=======================================================================
83 //function : DoSplitSEAMOnFace
84 //purpose  : 
85 //=======================================================================
86 void BOPTools_AlgoTools3D::DoSplitSEAMOnFace (const TopoDS_Edge& aSplit,
87                                               const TopoDS_Face& aF)
88 {
89   Standard_Boolean bIsUPeriodic, bIsVPeriodic, bIsLeft;
90   Standard_Real aTol, a, b, anUPeriod, anVPeriod, aT, anU, dU, anU1;
91   Standard_Real aScPr, anV, dV, anV1;
92   gp_Pnt2d aP2D;
93   gp_Vec2d aVec2D;
94   Handle(Geom2d_Curve) aTmpC1, aTmpC2;
95   Handle(Geom2d_Curve) C2D1;
96   Handle(Geom2d_Line) aLD1;
97   Handle(Geom_Surface) aS;
98   BRep_Builder BB;
99   TopoDS_Edge aSp;
100   //
101   bIsLeft = Standard_False;
102   aSp=aSplit;
103   aSp.Orientation(TopAbs_FORWARD);
104   aTol=BRep_Tool::Tolerance(aSp);
105   //
106   aS=BRep_Tool::Surface(aF);
107   bIsUPeriodic=aS->IsUPeriodic();
108   bIsVPeriodic=aS->IsVPeriodic();
109   //
110   anUPeriod = bIsUPeriodic ? aS->UPeriod() : 0.;
111   anVPeriod = bIsVPeriodic ? aS->VPeriod() : 0.;
112   //
113   if (!bIsUPeriodic && !bIsVPeriodic) {
114     Standard_Boolean bIsUClosed, bIsVClosed;
115     Standard_Real aUmin = 0., aUmax = 0., aVmin = 0., aVmax = 0.;
116     Handle(Geom_BSplineSurface) aBS;
117     Handle(Geom_BezierSurface) aBZ;
118     //
119     bIsUClosed=Standard_False;
120     bIsVClosed=Standard_False;
121     aBS=Handle(Geom_BSplineSurface)::DownCast(aS);
122     aBZ=Handle(Geom_BezierSurface) ::DownCast(aS);
123     //
124     if (!aBS.IsNull()) {
125       bIsUClosed=aBS->IsUClosed();
126       bIsVClosed=aBS->IsVClosed();
127       aBS->Bounds(aUmin, aUmax, aVmin, aVmax);
128     }
129     else if (!aBZ.IsNull()) {
130       bIsUClosed=aBZ->IsUClosed();
131       bIsVClosed=aBZ->IsVClosed();
132       aBZ->Bounds(aUmin, aUmax, aVmin, aVmax);
133     }
134     if (!bIsUClosed && !bIsVClosed) {
135       return;
136     }
137     //
138     if (bIsUClosed) {
139       anUPeriod=aUmax-aUmin;
140     }
141     if (bIsVClosed) {
142       anVPeriod=aVmax-aVmin;
143     }
144   }
145   //
146   C2D1=BRep_Tool::CurveOnSurface(aSp, aF, a, b);
147   //
148   aT=BOPTools_AlgoTools2D::IntermediatePoint(a, b);
149   C2D1->D1(aT, aP2D, aVec2D);
150   gp_Dir2d aDir2D1(aVec2D), aDOX(-1.,0.), aDOY(0.,1.);
151   //
152   anU=aP2D.X();
153   anV=aP2D.Y();
154   //
155   anU1=anU;
156   anV1=anV;
157   //
158   GeomAdaptor_Surface aGAS(aS);
159   dU = aGAS.UResolution(aTol);
160   dV = aGAS.VResolution(aTol);
161   //
162   if (anUPeriod > 0.){
163     if (fabs (anU) < dU) {
164       bIsLeft=Standard_True;
165       anU1=anU+anUPeriod;
166     }
167     else if (fabs (anU-anUPeriod) < dU) {
168       bIsLeft=Standard_False;
169       anU1=anU-anUPeriod;
170     }
171   }
172   //
173   if (anVPeriod > 0.) {
174     if (fabs (anV) < dV) {
175       bIsLeft=Standard_True;
176       anV1=anV+anVPeriod;
177     }
178     else if (fabs (anV-anVPeriod) < dV) {
179       bIsLeft=Standard_False;
180       anV1=anV-anVPeriod;
181     }
182   }
183   //
184   if (anU1==anU && anV1==anV) {
185     return;
186   }
187   //
188   aScPr = (anU1==anU) ? aDir2D1*aDOX : aDir2D1*aDOY;
189   //
190   aTmpC1=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
191   Handle(Geom2d_TrimmedCurve) aC1 = 
192     new Geom2d_TrimmedCurve(aTmpC1, a, b);
193   //
194   aTmpC2=Handle(Geom2d_Curve)::DownCast(C2D1->Copy());
195   Handle(Geom2d_TrimmedCurve) aC2 = 
196     new Geom2d_TrimmedCurve(aTmpC2, a, b);
197   gp_Vec2d aTrV(anU1-anU, anV1-anV);
198   aC2->Translate(aTrV);
199   //
200   if (!bIsLeft) {
201     if (aScPr<0.) {
202       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
203     }
204     else {
205       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
206     }
207   }
208   else {
209     if (aScPr<0.) {
210       BB.UpdateEdge(aSp, aC1, aC2, aF, aTol);
211     }
212     else {
213       BB.UpdateEdge(aSp, aC2, aC1, aF, aTol);
214     }
215   }
216 }
217 //=======================================================================
218 //function : GetNormalToFaceOnEdge
219 //purpose  : 
220 //=======================================================================
221 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
222                                                   const TopoDS_Face& aF,
223                                                   gp_Dir& aDNF)
224 {
225   Standard_Real aT, aT1, aT2;
226   
227   BRep_Tool::CurveOnSurface(aE, aF, aT1, aT2);
228   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
229
230   BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (aE, aF, aT, aDNF);
231
232   if (aF.Orientation()==TopAbs_REVERSED){
233     aDNF.Reverse();
234   }
235 }
236 //=======================================================================
237 //function : GetNormalToFaceOnEdge
238 //purpose  : 
239 //=======================================================================
240 void BOPTools_AlgoTools3D::GetNormalToFaceOnEdge (const TopoDS_Edge& aE,
241                                                   const TopoDS_Face& aF1,
242                                                   const Standard_Real aT, 
243                                                   gp_Dir& aDNF1)
244 {
245   Standard_Real U, V, aTolPC;
246   gp_Pnt2d aP2D;
247   gp_Pnt aP;
248   gp_Vec aD1U, aD1V;
249
250   Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
251   
252   Handle(Geom2d_Curve)aC2D1;
253   BOPTools_AlgoTools2D::CurveOnSurface(aE, aF1, aC2D1, aTolPC);
254
255   aC2D1->D0(aT, aP2D);
256   U=aP2D.X();
257   V=aP2D.Y();
258   
259   aS1->D1(U, V, aP, aD1U, aD1V);
260   gp_Dir aDD1U(aD1U); 
261   gp_Dir aDD1V(aD1V); 
262   
263   aDNF1=aDD1U^aDD1V; 
264 }
265 //=======================================================================
266 //function : SenseFlag
267 //purpose  :
268 //=======================================================================
269 Standard_Integer BOPTools_AlgoTools3D::SenseFlag (const gp_Dir& aDNF1,
270                                                   const gp_Dir& aDNF2)
271 {
272   Standard_Boolean bIsDirsCoinside;
273   //
274   bIsDirsCoinside=IntTools_Tools::IsDirsCoinside(aDNF1, aDNF2);
275   if (!bIsDirsCoinside) {
276     return 0;
277   }
278   
279   Standard_Real aScPr;
280   
281   aScPr=aDNF1*aDNF2;
282   if (aScPr<0.) {
283     return -1;
284   }
285   else if (aScPr>0.) {
286     return 1;
287   }
288   return -1;
289 }
290 //=======================================================================
291 //function : GetNormalToSurface
292 //purpose  :
293 //=======================================================================
294 Standard_Boolean BOPTools_AlgoTools3D::GetNormalToSurface
295   (const Handle(Geom_Surface)& aS,
296    const Standard_Real U,
297    const Standard_Real V,
298    gp_Dir& aDNS)
299 {
300   Standard_Boolean bFlag;
301   
302   gp_Pnt aP;
303   gp_Vec aD1U, aD1V;
304
305   aS->D1(U, V, aP, aD1U, aD1V);
306   
307   gp_Dir aDD1U(aD1U); 
308   gp_Dir aDD1V(aD1V); 
309   
310   bFlag=IntTools_Tools::IsDirsCoinside(aDD1U, aDD1U);
311   if (!bFlag) {
312     return bFlag;
313   }
314   
315   aDNS=aDD1U^aDD1V;
316   return bFlag;
317 }
318 //=======================================================================
319 //function : GetApproxNormalToFaceOnEdge
320 //purpose  : 
321 //=======================================================================
322 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge
323   (const TopoDS_Edge& aE,
324    const TopoDS_Face& aF,
325    const Standard_Real aT,
326    gp_Pnt& aPNear,
327    gp_Dir& aDNF,
328    Standard_Real aDt2D)
329 {
330   Standard_Real aFirst, aLast;
331   Handle(Geom2d_Curve) aC2D= 
332     BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
333   
334   if (aC2D.IsNull()) {
335     return;
336   }
337   gp_Pnt2d aPx2DNear;
338   PointNearEdge (aE, aF, aT, aDt2D, aPx2DNear, aPNear);
339   Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
340   
341   BOPTools_AlgoTools3D::GetNormalToSurface 
342     (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
343   
344   if (aF.Orientation()==TopAbs_REVERSED){
345     aDNF.Reverse();
346   }
347 }
348 //=======================================================================
349 //function : GetApproxNormalToFaceOnEdge
350 //purpose  : 
351 //=======================================================================
352 void BOPTools_AlgoTools3D::GetApproxNormalToFaceOnEdge 
353   (const TopoDS_Edge& aE,
354    const TopoDS_Face& aF,
355    const Standard_Real aT,
356    gp_Pnt& aPNear,
357    gp_Dir& aDNF,
358    Handle(IntTools_Context)& theContext)
359 {
360   Standard_Real aFirst, aLast;
361   Handle(Geom2d_Curve) aC2D= 
362     BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
363   
364   if (aC2D.IsNull()) {
365     return;
366   }
367   //gp_Pnt aPNear;
368   gp_Pnt2d aPx2DNear;
369   BOPTools_AlgoTools3D::PointNearEdge 
370     (aE, aF, aT, aPx2DNear, aPNear, theContext);
371   
372   Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
373   
374   BOPTools_AlgoTools3D::GetNormalToSurface 
375     (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
376   
377   if (aF.Orientation()==TopAbs_REVERSED){
378     aDNF.Reverse();
379   }
380 }
381 //=======================================================================
382 //function : PointNearEdge
383 //purpose  : 
384 //=======================================================================
385 void BOPTools_AlgoTools3D::PointNearEdge (const TopoDS_Edge& aE,
386                                           const TopoDS_Face& aF,
387                                           const Standard_Real aT, 
388                                           const Standard_Real aDt2D, 
389                                           gp_Pnt2d& aPx2DNear,
390                                           gp_Pnt& aPxNear)
391 {
392   Standard_Real aFirst, aLast, aETol, aFTol, transVal;
393   GeomAbs_SurfaceType aTS;
394   Handle(Geom2d_Curve) aC2D;
395   Handle(Geom_Surface) aS;
396   //
397   aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
398   if (aC2D.IsNull()) {
399     aPx2DNear.SetCoord (99., 99);
400     return;
401   }
402   //
403   aS=BRep_Tool::Surface(aF);
404   //
405   gp_Pnt2d aPx2D;
406   gp_Vec2d aVx2D;
407   aC2D->D1 (aT, aPx2D, aVx2D);
408   gp_Dir2d aDx2D(aVx2D);
409   
410   gp_Dir2d aDP;
411   aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
412   
413   if (aE.Orientation()==TopAbs_REVERSED){
414     aDP.Reverse();
415   }
416
417   if (aF.Orientation()==TopAbs_REVERSED) {
418     aDP.Reverse();
419   }
420   //
421   aETol = BRep_Tool::Tolerance(aE);
422   aFTol = BRep_Tool::Tolerance(aF);
423   // NPAL19220
424   GeomAdaptor_Surface aGAS(aS);
425   aTS=aGAS.GetType();
426   if (aTS==GeomAbs_BSplineSurface) {
427     if (aETol > 1.e-5) {
428       aFTol=aETol;
429     }
430   }
431   if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
432   //if( aETol > 1.e-5 && aFTol > 1.e-5 ) {
433     //pkv/103/D7
434     if(aTS!=GeomAbs_Sphere) {
435       gp_Vec2d transVec( aDP );
436       transVal = aDt2D + aETol + aFTol;
437       if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
438         Standard_Real aR, dT;
439         //
440         gp_Cylinder aCyl=aGAS.Cylinder();
441         aR=aCyl.Radius();
442         dT=1.-transVal/aR;
443         if (dT>=-1 && dT<=1) {
444           dT=acos(dT);
445           transVal=dT;
446         }
447       }
448       //
449       transVec.Multiply(transVal);
450       aPx2DNear = aPx2D.Translated( transVec );
451     }
452     else {
453       aPx2DNear.SetCoord 
454         (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
455     }
456   }
457   else {
458     aPx2DNear.SetCoord 
459       (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
460   }
461   //
462   aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
463 }
464 //=======================================================================
465 //function : PointNearEdge
466 //purpose  : 
467 //=======================================================================
468 void BOPTools_AlgoTools3D::PointNearEdge 
469   (const TopoDS_Edge& aE,
470    const TopoDS_Face& aF,
471    const Standard_Real aT, 
472    gp_Pnt2d& aPx2DNear,
473    gp_Pnt& aPxNear,
474    Handle(IntTools_Context)& theContext)
475 {
476   Standard_Real aTolE, aTolF, dTx, dT2D;
477   Handle(Geom_Surface) aS;
478   GeomAdaptor_Surface aGAS;
479   //
480   dT2D=10.*BOPTools_AlgoTools3D::MinStepIn2d();//~1.e-5;
481   //
482   aS = BRep_Tool::Surface(aF);
483   aGAS.Load(aS);
484   if (aGAS.GetType()==GeomAbs_Cylinder ||
485       aGAS.GetType()==GeomAbs_Sphere) {
486     dT2D=10.*dT2D;
487   } 
488   //
489   aTolE = BRep_Tool::Tolerance(aE);
490   aTolF = BRep_Tool::Tolerance(aF);
491   dTx = 2.*(aTolE + aTolF);
492   if (dTx > dT2D) {
493     dT2D=dTx;
494   }
495   //
496   BOPTools_AlgoTools3D::PointNearEdge 
497     (aE, aF, aT, dT2D, aPx2DNear, aPxNear);
498   if (!theContext->IsPointInOnFace(aF, aPx2DNear)) {
499     Standard_Integer iErr;
500     Standard_Real aU1, aU2, aV1, aV2, dV, dU, dTresh;
501     gp_Pnt aP;
502     gp_Pnt2d aP2d;
503     //
504     BRepTools::UVBounds(aF, aU1, aU2, aV1, aV2);
505     // 
506     dU=aU2-aU1;
507     dV=aV2-aV1;
508     //
509     dTresh=1.e-4;
510     if (dT2D > dTresh) {
511       dTresh=dT2D;
512     }
513     //
514     if (dU < dTresh || dV < dTresh) {
515       iErr = BOPTools_AlgoTools3D::PointInFace
516         (aF, aP, aP2d, theContext);
517       if (!iErr) {
518         aPxNear = aP;
519         aPx2DNear = aP2d;
520       }
521     }
522   }
523 }
524 //=======================================================================
525 // function: PointNearEdge
526 // purpose: 
527 //=======================================================================
528 void  BOPTools_AlgoTools3D::PointNearEdge 
529   (const TopoDS_Edge& aE,
530    const TopoDS_Face& aF, 
531    gp_Pnt2d& aPInFace2D, 
532    gp_Pnt& aPInFace,
533    Handle(IntTools_Context)& theContext)
534 {
535   Standard_Real aT, aT1, aT2;
536   //
537   // 1. 
538   BRep_Tool::Range(aE, aT1, aT2);
539   aT=BOPTools_AlgoTools2D::IntermediatePoint(aT1, aT2);
540   //
541   // 2. a Point inside Face near aPOnEdge aPInFace;
542   TopoDS_Face aFF=aF;
543   TopoDS_Edge aERight;
544   aFF.Orientation(TopAbs_FORWARD);
545   BOPTools_AlgoTools3D::OrientEdgeOnFace (aE, aFF, aERight);
546   
547   BOPTools_AlgoTools3D::PointNearEdge 
548     (aERight, aFF, aT, aPInFace2D, aPInFace, theContext);
549 }
550 //=======================================================================
551 //function : MinStepIn2d
552 //purpose  : 
553 //=======================================================================
554 Standard_Real BOPTools_AlgoTools3D::MinStepIn2d()
555 {
556   Standard_Real dt=1.e-5;
557   return dt;
558
559 //=======================================================================
560 //function : IsEmptyShape
561 //purpose  : 
562 //=======================================================================
563 Standard_Boolean BOPTools_AlgoTools3D::IsEmptyShape
564   (const TopoDS_Shape& aS)
565 {
566   Standard_Boolean bHasGeometry=Standard_False;
567   //
568   BOPCol_IndexedMapOfShape myShapes;
569   //
570   Add(aS, myShapes, bHasGeometry);
571
572   return !bHasGeometry;
573 }
574 //=======================================================================
575 //function : Add
576 //purpose  : 
577 //=======================================================================
578 void Add(const TopoDS_Shape& aS,
579          BOPCol_IndexedMapOfShape& myShapes, 
580          Standard_Boolean& bHasGeometry)
581 {
582   Standard_Integer anIndex; 
583   //
584   if (bHasGeometry) {
585     return;
586   }
587   //
588   if (aS.IsNull()) {
589     return;
590   }
591   //
592   TopoDS_Shape aSx = aS;
593   //
594   anIndex=myShapes.FindIndex(aSx);
595   if (!anIndex) {
596     bHasGeometry=HasGeometry (aSx);
597     if (bHasGeometry) {
598       return;
599     }
600     //
601     TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
602     for(; anIt.More(); anIt.Next()) {
603       const TopoDS_Shape& aSy=anIt.Value();
604       Add(aSy, myShapes, bHasGeometry);
605       //
606       if (bHasGeometry) {
607         return;
608       }
609       //
610       myShapes.Add(aSx);
611     }
612   }
613 }
614 //=======================================================================
615 //function : HasGeometry
616 //purpose  : 
617 //=======================================================================
618 Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
619 {
620   Standard_Boolean bHasGeometry=Standard_True;
621   TopAbs_ShapeEnum aType= aS.ShapeType();
622
623   if (aType == TopAbs_VERTEX) {
624     return bHasGeometry;
625   }
626   //
627   else if (aType == TopAbs_EDGE) {
628     Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
629     BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
630
631     while (itrc.More()) {
632       const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
633       if (CR->IsCurve3D()) {
634         if (!CR->Curve3D().IsNull()) {
635           return bHasGeometry;
636         }
637       }
638       else if (CR->IsCurveOnSurface()) {
639         return bHasGeometry;
640       }
641       else if (CR->IsRegularity()) {
642         return bHasGeometry;
643       }
644       else if (!CR->Polygon3D().IsNull()) {
645         return bHasGeometry;
646       }
647       else if (CR->IsPolygonOnTriangulation()) {
648         return bHasGeometry;
649       }
650       else if (CR->IsPolygonOnSurface()) {
651         return bHasGeometry;
652       }
653       itrc.Next();
654     }
655   }
656   //
657   else if (aType == TopAbs_FACE) {
658     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
659     if (!TF->Surface().IsNull())  {
660       return bHasGeometry;
661     }
662     Handle(Poly_Triangulation) Tr = TF->Triangulation();
663     if (!Tr.IsNull()) {
664       return bHasGeometry;
665     }
666   }
667   
668   return !bHasGeometry;
669 }
670 //=======================================================================
671 //function : OrientEdgeOnFace
672 //purpose  : 
673 //=======================================================================
674 void BOPTools_AlgoTools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
675                                              const TopoDS_Face& aF,
676                                              TopoDS_Edge& aERight)
677 {
678   if (BRep_Tool::IsClosed(aE, aF)) {
679     aERight=aE;
680     aERight.Orientation(aE.Orientation());
681
682     Standard_Integer iFoundCount = 0;
683     TopoDS_Edge anEdge = aE;
684     TopExp_Explorer anExp(aF, TopAbs_EDGE);
685
686     for (; anExp.More(); anExp.Next()) {
687       const TopoDS_Shape& aSS=anExp.Current();
688       
689       if (aSS.IsSame(aE)) {
690         anEdge = TopoDS::Edge(aSS);
691         iFoundCount++;
692       }
693     }
694     
695     if(iFoundCount == 1) {
696       aERight = anEdge;
697     }
698     return;
699   }
700   
701   TopExp_Explorer anExp(aF, TopAbs_EDGE);
702   for (; anExp.More(); anExp.Next()) {
703     const TopoDS_Shape& aSS=anExp.Current();
704     if (aSS.IsSame(aE)) {
705       aERight=aE;
706       aERight.Orientation(aSS.Orientation());
707       return;
708     }
709   }
710   aERight=aE;
711   aERight.Orientation(aE.Orientation());
712 }
713 //=======================================================================
714 //function : PointInFace
715 //purpose  :
716 //=======================================================================
717 Standard_Integer BOPTools_AlgoTools3D::PointInFace
718   (const TopoDS_Face& aF,
719    gp_Pnt& theP,
720    gp_Pnt2d& theP2D,
721    Handle(IntTools_Context)& theContext)
722 {
723   Standard_Boolean bIsDone, bHasFirstPoint, bHasSecondPoint;
724   Standard_Integer iErr, aIx, aNbDomains;
725   Standard_Real aUMin, aUMax, aVMin, aVMax;
726   Standard_Real aVx = 0., aUx, aV1, aV2;
727   gp_Dir2d aD2D (0., 1.);
728   gp_Pnt2d aP2D;
729   gp_Pnt aPx;
730   Handle(Geom2d_Curve) aC2D;
731   Handle(Geom2d_Line) aL2D;
732   Handle(Geom_Surface) aS;
733   TopoDS_Face aFF;
734   //
735   Geom2dHatch_Hatcher& aHatcher = theContext->Hatcher(aF);
736   //
737   iErr=0;
738   //
739   aFF=aF;
740   aFF.Orientation (TopAbs_FORWARD);
741   //
742   aS=BRep_Tool::Surface(aFF);
743   BRepTools::UVBounds(aFF, aUMin, aUMax, aVMin, aVMax);
744   //
745   aUx=IntTools_Tools::IntermediatePoint(aUMin, aUMax);
746   aP2D.SetCoord(aUx, 0.);
747   aL2D=new Geom2d_Line (aP2D, aD2D);
748   Geom2dAdaptor_Curve aHCur(aL2D);
749   //
750   aIx=aHatcher.AddHatching(aHCur) ;
751   //
752   aHatcher.Trim();
753   bIsDone=aHatcher.TrimDone(aIx);
754   if (!bIsDone) {
755     iErr=1;
756     return iErr;
757   }
758   //
759   aHatcher.ComputeDomains(aIx);
760   bIsDone=aHatcher.IsDone(aIx);
761   if (!bIsDone) {
762     iErr=2;
763     return iErr;
764   }
765   //
766   aNbDomains=aHatcher.NbDomains(aIx);
767   if (aNbDomains > 0) {
768     const HatchGen_Domain& aDomain=aHatcher.Domain (aIx, 1);
769     bHasFirstPoint=aDomain.HasFirstPoint();
770     if (!bHasFirstPoint) {
771       iErr=3;
772       return iErr;
773     }
774     //
775     aV1=aDomain.FirstPoint().Parameter();
776     //
777     bHasSecondPoint=aDomain.HasSecondPoint();
778     if (!bHasSecondPoint) {
779       iErr=4;
780       return iErr;
781     }
782     //
783     aV2=aDomain.SecondPoint().Parameter();
784     //
785     aVx=IntTools_Tools::IntermediatePoint(aV1, aV2);
786     //
787   }
788   else {
789     iErr=2;
790     return iErr;
791   }
792   //
793   aS->D0(aUx, aVx, aPx);
794   //
795   theP2D.SetCoord(aUx, aVx);
796   theP=aPx;
797   //
798   return iErr;
799 }