0022967: Boolean operations between two cylinders with orthogonal axis generate a...
[occt.git] / src / BOPTools / BOPTools_Tools3D_1.cxx
1 // File:        BOPTools_Tools3D_1.cxx
2 // Created:     Mon Jun 18 09:51:53 2001
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6 #include <BOPTools_Tools3D.ixx>
7 #include <math.h>
8
9 #include <gp.hxx>
10 #include <gp_Cylinder.hxx>
11 #include <gp_Pnt2d.hxx>
12 #include <gp_Vec2d.hxx>
13 #include <gp_Dir2d.hxx>
14
15 #include <gp_Dir.hxx>
16 #include <gp_Vec.hxx>
17
18 #include <Geom2d_Curve.hxx>
19 #include <Geom_Curve.hxx>
20 #include <Geom_Surface.hxx>
21
22 #include <GeomAdaptor_Surface.hxx>
23 #include <GeomAPI_ProjectPointOnSurf.hxx>
24
25 #include <BRepTools.hxx>
26 #include <BRepClass3d_SolidClassifier.hxx>
27
28 #include <BRep_Tool.hxx>
29 #include <BRepAdaptor_Surface.hxx>
30
31 #include <TopTools_ListIteratorOfListOfShape.hxx>
32 #include <TopExp_Explorer.hxx>
33 #include <TopoDS.hxx>
34 #include <TopTools_ListOfShape.hxx>
35
36 #include <BOPTools_Tools2D.hxx>
37
38
39 //=======================================================================
40 //function : GetApproxNormalToFaceOnEdge
41 //purpose  : 
42 //=======================================================================
43   void BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aE,
44                                                       const TopoDS_Face& aF,
45                                                       const Standard_Real aT,
46                                                       gp_Pnt& aPNear,
47                                                       gp_Dir& aDNF)
48 {
49   Standard_Real aFirst, aLast;
50   Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
51   
52   if (aC2D.IsNull()) {
53     return;
54   }
55   //gp_Pnt aPNear;
56   gp_Pnt2d aPx2DNear;
57   BOPTools_Tools3D::PointNearEdge (aE, aF, aT, aPx2DNear, aPNear);
58   
59   Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
60   
61   BOPTools_Tools3D::GetNormalToSurface (aS, aPx2DNear.X(), aPx2DNear.Y(), aDNF);
62   
63   if (aF.Orientation()==TopAbs_REVERSED){
64     aDNF.Reverse();
65   }
66 }
67 //=======================================================================
68 //function : PointNearEdge
69 //purpose  : 
70 //=======================================================================
71   void BOPTools_Tools3D::PointNearEdge (const TopoDS_Edge& aE,
72                                         const TopoDS_Face& aF,
73                                         const Standard_Real aT, 
74                                         const Standard_Real aDt2D, 
75                                         gp_Pnt2d& aPx2DNear,
76                                         gp_Pnt& aPxNear)
77 {
78   Standard_Real aFirst, aLast, aETol, aFTol, transVal;
79   GeomAbs_SurfaceType aTS;
80   Handle(Geom2d_Curve) aC2D;
81   Handle(Geom_Surface) aS;
82   //
83   aC2D= BRep_Tool::CurveOnSurface (aE, aF, aFirst, aLast);
84   if (aC2D.IsNull()) {
85     aPx2DNear.SetCoord (99., 99);
86     return;
87   }
88   //
89   aS=BRep_Tool::Surface(aF);
90   //
91   gp_Pnt2d aPx2D;
92   gp_Vec2d aVx2D;
93   aC2D->D1 (aT, aPx2D, aVx2D);
94   gp_Dir2d aDx2D(aVx2D);
95   
96   gp_Dir2d aDP;
97   aDP.SetCoord (-aDx2D.Y(), aDx2D.X());
98   
99   if (aE.Orientation()==TopAbs_REVERSED){
100     aDP.Reverse();
101   }
102
103   if (aF.Orientation()==TopAbs_REVERSED) {
104     aDP.Reverse();
105   }
106   //
107   aETol = BRep_Tool::Tolerance(aE);
108   aFTol = BRep_Tool::Tolerance(aF);
109   // pkv NPAL19220
110   GeomAdaptor_Surface aGAS(aS);
111   aTS=aGAS.GetType();
112   if (aTS==GeomAbs_BSplineSurface) {
113     if (aETol > 1.e-5) {
114       aFTol=aETol;
115     }
116   }
117   //modified by NIZNHY-PKV Thu Mar 19 14:15:15 2009f
118   if( aETol > 1.e-5 || aFTol > 1.e-5 ) {
119   //if( aETol > 1.e-5 && aFTol > 1.e-5 ) {
120     //modified by NIZNHY-PKV Thu Mar 19 14:15:24 2009t
121     //pkv/103/D7
122     if(aTS!=GeomAbs_Sphere) {
123       gp_Vec2d transVec( aDP );
124       transVal = aDt2D + aETol + aFTol;
125       if (aTS==GeomAbs_Cylinder) {// pkv/909/F8
126         Standard_Real aR, dT;
127         //
128         gp_Cylinder aCyl=aGAS.Cylinder();
129         aR=aCyl.Radius();
130         dT=1.-transVal/aR;
131         dT=acos(dT);
132         transVal=dT;
133       }
134       //
135       transVec.Multiply(transVal);
136       //
137       aPx2DNear = aPx2D.Translated( transVec );
138     }
139     else {
140       aPx2DNear.SetCoord (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
141     }
142   }
143   else {
144     aPx2DNear.SetCoord (aPx2D.X()+aDt2D*aDP.X(), aPx2D.Y()+aDt2D*aDP.Y());
145   }
146   //
147   aS->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
148 }
149
150 //=======================================================================
151 //function : PointNearEdge
152 //purpose  : 
153 //=======================================================================
154   void BOPTools_Tools3D::PointNearEdge (const TopoDS_Edge& aE,
155                                         const TopoDS_Face& aF,
156                                         const Standard_Real aT, 
157                                         gp_Pnt2d& aPx2DNear,
158                                         gp_Pnt& aPxNear)
159 {
160   Standard_Real dt2D=BOPTools_Tools3D::MinStepIn2d();//~1.e-5;
161   //
162   BOPTools_Tools3D::PointNearEdge (aE, aF, aT, dt2D, aPx2DNear, aPxNear);
163 }
164
165 //=======================================================================
166 // function: PointNearEdge
167 // purpose: 
168 //=======================================================================
169   void  BOPTools_Tools3D::PointNearEdge (const TopoDS_Edge& aE,
170                                          const TopoDS_Face& aF, 
171                                          gp_Pnt2d& aPInFace2D, 
172                                          gp_Pnt& aPInFace)
173                                   
174 {
175   Standard_Real aT, aT1, aT2;
176   //
177   // 1. 
178   BRep_Tool::Range(aE, aT1, aT2);
179   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
180   //
181   // 2. a Point inside Face near aPOnEdge aPInFace;
182   TopoDS_Face aFF=aF;
183   TopoDS_Edge aERight;
184   aFF.Orientation(TopAbs_FORWARD);
185   BOPTools_Tools3D::OrientEdgeOnFace (aE, aFF, aERight);
186   
187   BOPTools_Tools3D::PointNearEdge (aERight, aFF, aT, aPInFace2D, aPInFace);
188 }
189
190
191 //=======================================================================
192 //function : PointToCompare
193 //purpose  : 
194 //=======================================================================
195   void BOPTools_Tools3D::PointToCompare (const gp_Pnt& aP1,
196                                          const gp_Pnt& aP2,
197                                          const TopoDS_Face& aF,
198                                          gp_Pnt& aPF,
199                                          const Handle(IntTools_Context)& aContext)
200 {
201   Standard_Boolean bFlag;
202   Standard_Real aD, aTolF,  U, V;
203
204   Handle(Geom_Surface) aS=BRep_Tool::Surface(aF);
205
206   aTolF=BRep_Tool::Tolerance(aF);
207   //
208   GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF);
209   //
210   aProjector.Perform(aP1);
211   //
212   bFlag=aProjector.IsDone();
213   
214   if (bFlag) {
215     aD=aProjector.LowerDistance();
216     if (aD<aTolF) {
217       aProjector.LowerDistanceParameters (U, V);
218       aS->D0(U, V, aPF);
219       return;
220     }
221   }
222   //
223   aProjector.Perform(aP2);
224   //
225   bFlag=aProjector.IsDone();
226
227   if (bFlag) {
228     aD=aProjector.LowerDistance();
229     if (aD<aTolF) {
230       aProjector.LowerDistanceParameters (U, V);
231       aS->D0(U, V, aPF);
232       return;
233     }
234   }
235
236   aPF=aP1;
237 }
238
239 //=======================================================================
240 //function : GetPlane
241 //purpose  : 
242 //=======================================================================
243   void BOPTools_Tools3D::GetPlane (const TopoDS_Edge& aSpEF1,
244                                    const TopoDS_Edge& aEF1,
245                                    const TopoDS_Face& aF1,
246                                    const TopoDS_Face& aF2,
247                                    TopAbs_State& aStPF,
248                                    const Handle(IntTools_Context)& aContext)
249 {
250   Standard_Real aT1, aT2, aT, aTolF2, aDt2D;
251   gp_Pnt2d aPx2DNear;
252   gp_Pnt aPxNear, aPxF2;
253   gp_Dir aDNF2;
254
255   Handle(Geom_Curve)aC3D =BRep_Tool::Curve(aSpEF1, aT1, aT2);
256   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
257
258   Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aEF1, aF1, aT1, aT2);
259
260   aStPF=TopAbs_OUT;
261   //
262   aDt2D=BOPTools_Tools3D::MinStepIn2d();//~1.e-5;
263   aTolF2=BRep_Tool::Tolerance(aF2);
264   //
265   {
266     GeomAbs_SurfaceType aType1;
267     
268     Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
269     GeomAdaptor_Surface aGASF1(aS1);
270     aType1=aGASF1.GetType();
271     
272     if (aType1==GeomAbs_Cylinder) {
273       Standard_Real aCT, aDt2Dx, aPC=0.99;
274       
275       aCT=1.-aGASF1.UResolution(aTolF2);
276       aDt2Dx=aPC*acos(aCT);
277       if (aDt2Dx>aDt2D) {
278         aDt2D=aDt2Dx;
279       }
280     }
281   }
282   //
283   BOPTools_Tools3D::PointNearEdge (aEF1, aF1, aT, aDt2D, aPx2DNear, aPxNear);
284   //
285
286   //-- EJG
287   Standard_Boolean isIn = aContext->IsPointInFace(aF1,aPx2DNear);
288   if( !isIn ) {
289     Standard_Real aEF1Tol = BRep_Tool::Tolerance(aEF1);
290     Standard_Real aF1Tol = BRep_Tool::Tolerance(aF1);
291     if( aEF1Tol > 1.e-5 || ( aF1Tol > 1.e-5 || aTolF2 > 1.e-5 ) ) {
292       gp_Pnt2d aP2DOnC; 
293       aC2D->D0(aT, aP2DOnC);
294       gp_Vec2d aP2Dir( aPx2DNear, aP2DOnC );
295       Standard_Real transVal = aP2Dir.Magnitude();
296       gp_Vec2d aP2DirN = aP2Dir.Normalized();
297       if( aF1Tol > 1.e-5 && aTolF2 > 1.e-5 ) {
298         transVal = 2.*transVal +aEF1Tol + aF1Tol + aTolF2;
299       }
300       else {
301         transVal *= 2.;
302       }
303       aPx2DNear.Translate( (transVal*aP2DirN) );
304       Handle(Geom_Surface) aS1 = BRep_Tool::Surface(aF1);
305       aS1->D0(aPx2DNear.X(), aPx2DNear.Y(), aPxNear);
306
307     }
308   }
309   //-- EJG
310
311   Standard_Boolean bFlag;
312   Standard_Real aD, U, V;
313   //
314   GeomAPI_ProjectPointOnSurf& aProjector=aContext->ProjPS(aF2);
315   //
316   Handle(Geom_Surface) aS2=BRep_Tool::Surface(aF2);
317   //
318   aProjector.Perform(aPxNear);
319   //
320   bFlag=aProjector.IsDone();
321   
322   if (!bFlag) {
323     return;
324   }
325   //
326   aD=aProjector.LowerDistance();
327   if (aD<aTolF2) {
328     // aPxF2, aDNF2, aPlnF2
329     aProjector.LowerDistanceParameters (U, V);
330     aS2->D0(U, V, aPxF2);
331     
332     BOPTools_Tools3D::GetNormalToSurface (aS2, U, V, aDNF2);
333   
334     if (aF2.Orientation()==TopAbs_REVERSED){
335       aDNF2.Reverse();
336     }
337
338     gp_Pln aPlnF2(aPxF2, aDNF2);
339     //
340     aD=BOPTools_Tools3D::SignDistance(aPxNear, aPlnF2);
341     
342     if (aD<=0.) {
343       aStPF=TopAbs_IN;
344     }
345   }
346 }
347
348 //=======================================================================
349 //function : GetPointState
350 //purpose  : 
351 //=======================================================================
352   void BOPTools_Tools3D::GetPointState (const TopoDS_Edge& aSpEF2,
353                                         const TopoDS_Edge& aEF2,
354                                         const TopoDS_Face& aF2adj,
355                                         const TopoDS_Face& aF1,
356                                         TopAbs_State& aStPF)
357 {
358   Standard_Real aT1, aT2, aT, aTolEF2;
359   gp_Dir aDNF1;
360   gp_Pnt2d aPxOnF1, aPxOnF2;
361   //
362   TopoDS_Face aF2adjF=aF2adj;
363   aF2adjF.Orientation(TopAbs_FORWARD);
364   //
365   aTolEF2=BRep_Tool::Tolerance(aEF2);
366   //
367   aStPF=TopAbs_OUT;
368   //
369   Handle(Geom_Curve)aC3D =BRep_Tool::Curve(aSpEF2, aT1, aT2);
370   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
371   //
372   // 2D-curves of aSpEF2 for aF1, aF2adj
373   Handle(Geom2d_Curve) aC2DF1= BRep_Tool::CurveOnSurface (aSpEF2, aF1, aT1, aT2);
374   aC2DF1->D0(aT, aPxOnF1);
375
376   Handle(Geom2d_Curve) aC2DF2= BRep_Tool::CurveOnSurface (aSpEF2, aF2adjF, aT1, aT2);
377   aC2DF2->D0(aT, aPxOnF2);
378   //
379   // Surfaces
380   Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
381   Handle(Geom_Surface) aS2=BRep_Tool::Surface(aF2adjF);
382   
383   //
384   // Step aDt2D 
385   Standard_Real aDt2D, aDt2dMin, aURes, aVRes;
386   //
387   GeomAdaptor_Surface aGASF2adjF(aS2);
388   //
389   aURes=aGASF2adjF.UResolution(aTolEF2);
390   aVRes=aGASF2adjF.VResolution(aTolEF2);
391   aDt2D=(aURes>aVRes) ? aURes : aVRes;
392   //
393   aDt2dMin=BOPTools_Tools3D::MinStepIn2d();
394   //
395   if (aDt2D < aDt2dMin) {
396     aDt2D=aDt2dMin;
397   }
398   //
399   // Point aPxNear on aF2adjF that is Near Edge aEF2Right at parameter aT
400   gp_Pnt2d aPx2DNear;
401   gp_Pnt aPxNear;
402   TopoDS_Edge aEF2Right;
403   //
404   BOPTools_Tools3D::OrientEdgeOnFace (aEF2, aF2adjF, aEF2Right);
405   //
406   BOPTools_Tools3D::PointNearEdge (aEF2Right, aF2adjF, aT, aDt2D, aPx2DNear, aPxNear);
407   //
408   // Normal to the face aF1 at the point aPxOnF1
409   BOPTools_Tools3D::GetNormalToSurface (aS1, aPxOnF1.X(), aPxOnF1.Y(), aDNF1);
410   if (aF1.Orientation()==TopAbs_REVERSED){
411     aDNF1.Reverse();
412   }
413   //
414   // Plane to compare aPlnF1
415   gp_Pnt aPxF1, aPxF2;
416   //
417   aS1->D0(aPxOnF1.X(), aPxOnF1.Y(), aPxF1);
418   //
419   gp_Pln aPlnF1(aPxF1, aDNF1);
420   //
421   // Correction on shifting vector aVx
422   {
423     Standard_Real aX, aY, aZ;
424     //
425     aS2->D0(aPxOnF2.X(), aPxOnF2.Y(), aPxF2);
426     gp_Vec aVx(aPxF2, aPxF1);
427     //
428     aX=aPxNear.X()+aVx.X();
429     aY=aPxNear.Y()+aVx.Y();
430     aZ=aPxNear.Z()+aVx.Z();
431     //
432     aPxNear.SetCoord(aX, aY, aZ);
433   }
434   //
435   // Signed Distance between aPxNear, aPlnF1
436   Standard_Real aD;
437   aD=BOPTools_Tools3D::SignDistance(aPxNear, aPlnF1);
438   if (aD<=0.) {
439     aStPF=TopAbs_IN;
440   }
441 }
442
443 //=======================================================================
444 //function : OrientEdgeOnFace
445 //purpose  : 
446 //=======================================================================
447   void BOPTools_Tools3D::OrientEdgeOnFace (const TopoDS_Edge& aE,
448                                            const TopoDS_Face& aF,
449                                            TopoDS_Edge& aERight)
450 {
451   if (BRep_Tool::IsClosed(aE, aF)) {
452     aERight=aE;
453     aERight.Orientation(aE.Orientation());
454
455     Standard_Integer iFoundCount = 0;
456     TopoDS_Edge anEdge = aE;
457     TopExp_Explorer anExp(aF, TopAbs_EDGE);
458
459     for (; anExp.More(); anExp.Next()) {
460       const TopoDS_Shape& aSS=anExp.Current();
461       
462       if (aSS.IsSame(aE)) {
463         anEdge = TopoDS::Edge(aSS);
464         iFoundCount++;
465       }
466     }
467     
468     if(iFoundCount == 1) {
469       aERight = anEdge;
470     }
471     return;
472   }
473   
474   TopExp_Explorer anExp(aF, TopAbs_EDGE);
475   for (; anExp.More(); anExp.Next()) {
476     const TopoDS_Shape& aSS=anExp.Current();
477     if (aSS.IsSame(aE)) {
478       aERight=aE;
479       aERight.Orientation(aSS.Orientation());
480       return;
481     }
482   }
483   aERight=aE;
484   aERight.Orientation(aE.Orientation());
485 }
486 //=======================================================================
487 //function : OrientTouchEdgeOnF1
488 //purpose  : 
489 //=======================================================================
490   TopAbs_Orientation BOPTools_Tools3D::OrientTouchEdgeOnF1 (const TopoDS_Edge& aSpEF2,
491                                                             const TopoDS_Edge& aEF2,
492                                                             const TopoDS_Face& aF2adj,
493                                                             const TopoDS_Face& aF1)
494 {
495   Standard_Real aT1, aT2, aT;
496   //
497   Handle(Geom_Curve)aC3D =BRep_Tool::Curve(aSpEF2, aT1, aT2);
498   //
499   // point on edge aEF2 inside range of aSpEF2:
500   gp_Pnt aPx;
501   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
502   aC3D->D0(aT, aPx);
503   //
504   // Normal to aF1
505   gp_Dir aDNF1;
506   Handle(Geom2d_Curve) aC2DF1= BRep_Tool::CurveOnSurface (aSpEF2, aF1, aT1, aT2);
507   gp_Pnt2d aPxOnF1;
508   aC2DF1->D0(aT, aPxOnF1);
509
510   Handle(Geom_Surface) aS1=BRep_Tool::Surface(aF1);
511   BOPTools_Tools3D::GetNormalToSurface (aS1, aPxOnF1.X(), aPxOnF1.Y(), aDNF1);
512   
513   if (aF1.Orientation()==TopAbs_REVERSED){
514     aDNF1.Reverse();
515   }
516   //
517   // Point  aPxNear that is ON F2adj and near Px
518   gp_Pnt2d aPx2DNear;
519   gp_Pnt aPxNear;
520   
521   Handle(Geom2d_Curve) aC2D= BRep_Tool::CurveOnSurface (aEF2, aF2adj, aT1, aT2);
522   
523   TopoDS_Face aF2adjF=aF2adj;
524   aF2adjF.Orientation(TopAbs_FORWARD);
525   TopoDS_Edge aEF2Right;
526   BOPTools_Tools3D::OrientEdgeOnFace (aEF2, aF2adjF, aEF2Right);
527   BOPTools_Tools3D::PointNearEdge (aEF2Right, aF2adjF, aT, aPx2DNear, aPxNear);
528   //
529   // Normal to aF2adj
530   gp_Dir aDNF2;
531   Handle(Geom_Surface) aS2=BRep_Tool::Surface(aF2adj);
532   BOPTools_Tools3D::GetNormalToSurface (aS2, aPx2DNear.X(), aPx2DNear.Y(), aDNF2);
533   
534   if (aF2adj.Orientation()==TopAbs_REVERSED){
535     aDNF2.Reverse();
536   }
537   //
538   // vector product
539   gp_Dir aDTN=aDNF1^aDNF2;
540   // Tangent for split
541   gp_Vec aTE;
542   BOPTools_Tools2D::TangentOnEdge(aT, aSpEF2, aTE);
543   gp_Dir aDTE(aTE); 
544   
545   Standard_Real aScPr;
546   aScPr=aDTN*aDTE;
547   
548   TopAbs_Orientation anOr;
549   anOr=TopAbs_FORWARD;
550   if (aScPr<0.) {
551     anOr=TopAbs_REVERSED;
552   }
553   return anOr;
554 }
555
556 //=======================================================================
557 // function: GetSeams
558 // purpose: 
559 //=======================================================================
560   void BOPTools_Tools3D::GetSeams (const TopoDS_Face& aF,
561                                    TopoDS_Edge& aSim1,
562                                    TopoDS_Edge& aSim2)
563 {
564   TopTools_ListOfShape aLS;
565   TopExp_Explorer anExpEdges (aF, TopAbs_EDGE);
566   for (; anExpEdges.More(); anExpEdges.Next()) {
567     const TopoDS_Edge& aE= TopoDS::Edge(anExpEdges.Current());
568     if (BRep_Tool::IsClosed(aE, aF)) {
569       aLS.Append(aE);
570     }
571   }
572   aSim1=TopoDS::Edge(aLS.First());
573   aSim2=TopoDS::Edge(aLS.Last ());
574 }
575
576 //=======================================================================
577 // function: GetSeam
578 // purpose: 
579 //=======================================================================
580   void BOPTools_Tools3D::GetSeam (const TopoDS_Face& aF,
581                                   const TopoDS_Edge& aSim1,
582                                   TopoDS_Edge& aSim2)
583 {
584   TopExp_Explorer anExpEdges (aF, TopAbs_EDGE);
585   for (; anExpEdges.More(); anExpEdges.Next()) {
586     const TopoDS_Edge& aE= TopoDS::Edge(anExpEdges.Current());
587     if (BRep_Tool::IsClosed(aE, aF)) {
588       if (aE.IsSame(aSim1)) {
589         if (aE!=aSim1) {
590           aSim2=aE;
591           return;
592         }
593       }
594     }
595   }
596 }
597
598 //=======================================================================
599 //function : MinStepIn2d
600 //purpose  : 
601 //=======================================================================
602   Standard_Real BOPTools_Tools3D::MinStepIn2d()
603 {
604   Standard_Real dt=1.e-5;
605   return dt;
606
607
608
609 #include <TopTools_IndexedMapOfShape.hxx>
610 #include <TopoDS_Iterator.hxx>
611 #include <BRep_TVertex.hxx>
612 #include <BRep_ListIteratorOfListOfPointRepresentation.hxx>
613 #include <BRep_PointRepresentation.hxx>
614 #include <BRep_TEdge.hxx>
615 #include <BRep_ListIteratorOfListOfCurveRepresentation.hxx>
616 #include <BRep_CurveRepresentation.hxx>
617 #include <BRep_TFace.hxx>
618 #include <Poly_Triangulation.hxx>
619 #include <BRep_Builder.hxx>
620
621 static 
622   Standard_Boolean HasGeometry(const TopoDS_Shape& aS);
623
624 static
625   void Add(const TopoDS_Shape& aS,
626            TopTools_IndexedMapOfShape& myShapes, 
627            Standard_Boolean& bHasGeometry);
628
629 //=======================================================================
630 //function : IsEmptyShape
631 //purpose  : 
632 //=======================================================================
633   Standard_Boolean BOPTools_Tools3D::IsEmptyShape(const TopoDS_Shape& aS)
634 {
635   Standard_Boolean bHasGeometry=Standard_False;
636   //
637   TopTools_IndexedMapOfShape myShapes;
638   //
639   Add(aS, myShapes, bHasGeometry);
640
641   return !bHasGeometry;
642 }
643 //=======================================================================
644 //function : Add
645 //purpose  : 
646 //=======================================================================
647 void Add(const TopoDS_Shape& aS,
648          TopTools_IndexedMapOfShape& myShapes, 
649          Standard_Boolean& bHasGeometry)
650 {
651   Standard_Integer anIndex; 
652   //
653   if (bHasGeometry) {
654     return;
655   }
656   //
657   if (aS.IsNull()) {
658     return;
659   }
660   //
661   TopoDS_Shape aSx = aS;
662   //
663   anIndex=myShapes.FindIndex(aSx);
664   if (!anIndex) {
665     bHasGeometry=HasGeometry (aSx);
666     if (bHasGeometry) {
667       return;
668     }
669     //
670     TopoDS_Iterator anIt(aSx, Standard_False, Standard_False);
671     for(; anIt.More(); anIt.Next()) {
672       const TopoDS_Shape& aSy=anIt.Value();
673       Add(aSy, myShapes, bHasGeometry);
674       //
675       if (bHasGeometry) {
676         return;
677       }
678       //
679       myShapes.Add(aSx);
680     }
681   }
682 }
683 //=======================================================================
684 //function : HasGeometry
685 //purpose  : 
686 //=======================================================================
687   Standard_Boolean HasGeometry(const TopoDS_Shape& aS)
688 {
689   Standard_Boolean bHasGeometry=Standard_True;
690   TopAbs_ShapeEnum aType= aS.ShapeType();
691
692   if (aType == TopAbs_VERTEX) {
693     
694     Handle(BRep_TVertex) TV = Handle(BRep_TVertex)::DownCast(aS.TShape());
695     BRep_ListIteratorOfListOfPointRepresentation itrp(TV->Points());
696     
697     while (itrp.More()) {
698       const Handle(BRep_PointRepresentation)& PR = itrp.Value();
699
700       if (PR->IsPointOnCurve()) {
701         return bHasGeometry;
702       }
703
704       else if (PR->IsPointOnCurveOnSurface()) {
705         return bHasGeometry;
706       }
707
708       else if (PR->IsPointOnSurface()) {
709         return bHasGeometry;
710       }
711       itrp.Next();
712     }
713   }
714
715   //
716   else if (aType == TopAbs_EDGE) {
717     Handle(BRep_TEdge) TE = Handle(BRep_TEdge)::DownCast(aS.TShape());
718     BRep_ListIteratorOfListOfCurveRepresentation itrc(TE->Curves());
719
720     while (itrc.More()) {
721       const Handle(BRep_CurveRepresentation)& CR = itrc.Value();
722       if (CR->IsCurve3D()) {
723         if (!CR->Curve3D().IsNull()) {
724           return bHasGeometry;
725         }
726       }
727       else if (CR->IsCurveOnSurface()) {
728         return bHasGeometry;
729       }
730       else if (CR->IsRegularity()) {
731         return bHasGeometry;
732       }
733       else if (!CR->Polygon3D().IsNull()) {
734         return bHasGeometry;
735       }
736       else if (CR->IsPolygonOnTriangulation()) {
737         return bHasGeometry;
738       }
739       else if (CR->IsPolygonOnSurface()) {
740         return bHasGeometry;
741       }
742       itrc.Next();
743     }
744   }
745   //
746   else if (aType == TopAbs_FACE) {
747     Handle(BRep_TFace) TF = Handle(BRep_TFace)::DownCast(aS.TShape());
748     if (!TF->Surface().IsNull())  {
749       return bHasGeometry;
750     }
751     Handle(Poly_Triangulation) Tr = TF->Triangulation();
752     if (!Tr.IsNull()) {
753       return bHasGeometry;
754     }
755   }
756   
757   return !bHasGeometry;
758 }
759
760 //=======================================================================
761 // function: InvertShape
762 // purpose: 
763 //=======================================================================
764   void BOPTools_Tools3D::InvertShape(const TopoDS_Shape& aS,
765                                      TopoDS_Shape& aSInvert)
766 {
767   BRep_Builder aBB;
768   
769   aSInvert=aS.EmptyCopied();
770   
771   TopoDS_Iterator anIt(aS);
772
773   while (anIt.More()) {
774     aBB.Add(aSInvert, anIt.Value().Reversed());
775     anIt.Next();
776   }
777 }
778
779 //=======================================================================
780 // function: GetStatePartIN2D
781 // purpose: 
782 //=======================================================================
783   TopAbs_State  BOPTools_Tools3D::GetStatePartIN2D(const TopoDS_Edge& aSp,
784                                                    const TopoDS_Edge& aEF1,
785                                                    const TopoDS_Face& aF1,
786                                                    const TopoDS_Face& aF2,
787                                                    const Handle(IntTools_Context)& aContext)
788 {
789   gp_Dir aDBF1, aDNF2;
790   TopAbs_State aStPF;
791
792   BOPTools_Tools3D::GetBiNormal (aSp, aF1, aDBF1);
793   BOPTools_Tools3D::GetNormalToFaceOnEdge (aSp, aF2, aDNF2);
794
795   Standard_Real aTolScPr, aScPr;
796
797   aTolScPr=1.e-7;
798   aScPr=aDBF1*aDNF2;
799
800   //XX 909/G2
801   BRepAdaptor_Surface aBAS1, aBAS2;
802   GeomAbs_SurfaceType aType1, aType2;
803
804   aBAS1.Initialize (aF1, Standard_False);
805   aBAS2.Initialize (aF2, Standard_False);
806   aType1=aBAS1.GetType();
807   aType2=aBAS2.GetType();
808   
809   if (aType1==GeomAbs_BSplineSurface
810       ||
811       aType2==GeomAbs_BSplineSurface) {
812     //aTolScPr=1.e-5;
813     aTolScPr=5.5e-5;
814   }
815   //XX
816
817   if (fabs(aScPr) < aTolScPr) {
818     
819     
820     BOPTools_Tools3D::GetPlane(aSp, aEF1, aF1, aF2, aStPF, aContext);
821     aScPr=1.; // >0.
822     if (aStPF==TopAbs_IN) {
823       aScPr=-1.; // <0.
824     }
825   }
826
827   aStPF=TopAbs_OUT;
828   if (aScPr<0.) {
829     aStPF=TopAbs_IN;
830   }
831   return aStPF;
832 }
833 // ===========================================================================================
834 // function: ComputeFaceState
835 // purpose: 
836 // ===========================================================================================
837 Standard_Boolean BOPTools_Tools3D::ComputeFaceState(const TopoDS_Face&  theFace,
838                                                     const TopoDS_Solid& theRef,
839                                                     const Handle(IntTools_Context)& theContext,
840                                                     TopAbs_State&       theState) 
841 {
842   TopAbs_State aState = TopAbs_ON;
843
844   Standard_Real umin = 0., umax = 0., vmin = 0., vmax = 0.;
845   BRepTools::UVBounds(theFace, umin, umax, vmin, vmax);
846   Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace);
847   Standard_Real aTolerance = BRep_Tool::Tolerance(theFace);
848
849   Standard_Integer nbpoints = 5;
850   Standard_Real adeltau = (umax - umin) / (nbpoints + 1);
851   Standard_Real adeltav = (vmax - vmin) / (nbpoints + 1);
852   Standard_Real U = umin + adeltau;
853   Standard_Boolean bFoundValidPoint = Standard_False;
854   Standard_Boolean bFoundInFacePoint = Standard_False;
855   BRepClass3d_SolidClassifier& aSolidClassifier = theContext->SolidClassifier(theRef);
856   Standard_Integer i = 0, j = 0;
857
858   for(i = 1; !bFoundValidPoint && (i <= nbpoints); i++, U+=adeltau) {
859     Standard_Real V = vmin + adeltav;
860
861     for(j = 1; !bFoundValidPoint && (j <= nbpoints); j++, V+=adeltav) {
862       gp_Pnt2d aPoint(U,V);
863
864       if(theContext->IsPointInFace(theFace, aPoint)) {
865         bFoundInFacePoint = Standard_True;
866         gp_Pnt aP3d = aSurface->Value(U, V);
867
868         aSolidClassifier.Perform(aP3d, aTolerance);
869         aState = aSolidClassifier.State();
870
871         if(aState != TopAbs_ON) {
872           
873           if(!aSolidClassifier.Rejected()) {
874             TopoDS_Face aFace2 = aSolidClassifier.Face();
875
876             if(!aFace2.IsNull()) {
877               if(BOPTools_Tools3D::CheckSameDomainFaceInside(theFace, aFace2, theContext))
878                 aState = TopAbs_ON;
879               else {
880                 break;
881               }
882             }
883           }
884         }
885       }
886     }
887   }
888
889   if(!bFoundInFacePoint) {
890     U = (umin + umax) * 0.5;
891     nbpoints /= 2;
892
893     for(i = 1; !bFoundValidPoint && (i <= nbpoints); i++, U+=adeltau) {
894       Standard_Real V = (vmin + vmax) * 0.5;
895
896       for(j = 1; !bFoundValidPoint && (j <= nbpoints); j++, V+=adeltav) {
897         gp_Pnt2d aPoint(U,V);
898
899         if(theContext->IsPointInOnFace(theFace, aPoint)) {
900           bFoundInFacePoint = Standard_True;
901           gp_Pnt aP3d = aSurface->Value(U, V);
902     
903           aSolidClassifier.Perform(aP3d, aTolerance);
904           aState = aSolidClassifier.State();
905
906           if(aState != TopAbs_ON) {
907
908             if(!aSolidClassifier.Rejected()) {
909               TopoDS_Face aFace2 = aSolidClassifier.Face();
910
911               if(!aFace2.IsNull()) {
912                 GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(aFace2);
913                 aProjector.Perform(aP3d);
914
915                 if(aProjector.IsDone()) {
916                   Standard_Real U2 = 0., V2 = 0.;
917                   aProjector.LowerDistanceParameters(U2, V2);
918                   gp_Pnt2d aPoint2(U2, V2);
919
920                   if(aProjector.LowerDistance() < aTolerance) {
921                     if(theContext->IsPointInFace(aFace2, aPoint2)) 
922                       aState = TopAbs_ON;
923                   }
924                 }
925                 bFoundValidPoint = Standard_True;
926                 break;
927               }
928             }
929             else {
930               bFoundInFacePoint = Standard_False;
931             }
932           }
933         }
934       }
935     }
936   }
937
938   if(!bFoundInFacePoint)
939     return Standard_False;
940
941   theState = aState;
942
943   return Standard_True;
944 }
945 //modified by NIZNHY-PKV Thu Sep 22 10:55:14 2011f
946 // ===========================================================================================
947 // function: CheckSameDomainFaceInside
948 // purpose: Check if distance between several points of theFace1 and
949 //          theFace2 
950 // ===========================================================================================
951 Standard_Boolean BOPTools_Tools3D::CheckSameDomainFaceInside(const TopoDS_Face& theFace1,
952                                                              const TopoDS_Face& theFace2,
953                                                              const Handle(IntTools_Context)& theContext) 
954 {
955   Standard_Boolean bFoundON, bPointInFace; 
956   Standard_Integer nbpoints, i, j;
957   Standard_Real umin, umax, vmin, vmax, aTol, adeltau, adeltav, U, V, U2, V2, aD, aTolE;
958   gp_Pnt2d aP2D;
959   gp_Pnt aP3D; 
960   TopExp_Explorer aExp;
961   //
962   BRepTools::UVBounds(theFace1, umin, umax, vmin, vmax);
963   Handle(Geom_Surface) aS1=BRep_Tool::Surface(theFace1);
964   //
965   aTol=BRep_Tool::Tolerance(theFace1);
966   aExp.Init(theFace1, TopAbs_EDGE);
967   for(; aExp.More(); aExp.Next()) {
968     const TopoDS_Edge& aE = TopoDS::Edge(aExp.Current());
969     aTolE = BRep_Tool::Tolerance(aE);
970     aTol=(aTol < aTolE) ? aTolE : aTol;
971   }
972   aTol=aTol+BRep_Tool::Tolerance(theFace2);
973   //
974   nbpoints=5;
975   adeltau=(umax - umin) / (nbpoints + 1);
976   adeltav=(vmax - vmin) / (nbpoints + 1);
977   bFoundON = Standard_False;
978   //
979   GeomAPI_ProjectPointOnSurf& aProjector = theContext->ProjPS(theFace2);
980   //
981   for(i=1; i<=nbpoints; ++i){
982     U=umin+i*adeltau;
983     for(j=1; j<=nbpoints; ++j) {
984       V=vmin+j*adeltav;
985       aP2D.SetCoord(U,V);
986       bPointInFace=theContext->IsPointInFace(theFace1, aP2D);
987       if(bPointInFace) {
988         aP3D=aS1->Value(U, V);
989         aProjector.Perform(aP3D);
990         if(aProjector.IsDone()) {
991           aProjector.LowerDistanceParameters(U2, V2);
992           aP2D.SetCoord(U2, V2);
993           //
994           aD=aProjector.LowerDistance();
995           if(aD > aTol) {
996             return Standard_False;
997           }
998           //
999           bPointInFace=theContext->IsPointInFace(theFace2, aP2D);
1000           if (bPointInFace) {
1001             bFoundON = Standard_True;
1002           }
1003         }
1004       }
1005     }
1006   }
1007   return bFoundON;
1008 }
1009 //modified by NIZNHY-PKV Thu Sep 22 10:55:19 2011t