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