Salome HOME
Merge from BR_Dev_For_4_0 branch (from tag mergeto_BR_QT4_Dev_17Jan08)
[modules/geom.git] / src / GEOMAlgo / GEOMAlgo_Tools3D.cxx
1 // Copyright (C) 2005  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
3 // 
4 // This library is free software; you can redistribute it and/or
5 // modify it under the terms of the GNU Lesser General Public
6 // License as published by the Free Software Foundation; either 
7 // version 2.1 of the License.
8 // 
9 // This library is distributed in the hope that it will be useful 
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU 
12 // Lesser General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public  
15 // License along with this library; if not, write to the Free Software 
16 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
17 //
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
19 //
20 // File:        GEOMAlgo_Tools3D.cxx
21 // Created:     
22 // Author:      Peter KURNEV
23
24 #include <GEOMAlgo_Tools3D.ixx>
25
26 #include <Precision.hxx>
27
28 #include <gp_Vec.hxx>
29 #include <gp_Pnt.hxx>
30 #include <gp_Dir.hxx>
31 #include <gp_Pnt2d.hxx>
32 #include <gp_Pln.hxx>
33 #include <gp_XYZ.hxx>
34
35 #include <Geom_Curve.hxx>
36 #include <Geom_Surface.hxx>
37 #include <Geom2d_Curve.hxx>
38 #include <GeomAPI_ProjectPointOnSurf.hxx>
39
40 #include <TopAbs_ShapeEnum.hxx>
41 #include <TopAbs_State.hxx>
42
43 #include <TopLoc_Location.hxx>
44
45 #include <TopoDS.hxx>
46 #include <TopoDS_Edge.hxx>
47 #include <TopoDS_CompSolid.hxx>
48 #include <TopoDS_Wire.hxx>
49 #include <TopoDS_Compound.hxx>
50 #include <TopoDS_Face.hxx>
51 #include <TopoDS_Vertex.hxx>
52 #include <TopoDS_Solid.hxx>
53 #include <TopoDS_Shell.hxx>
54 #include <TopoDS_Iterator.hxx>
55
56 #include <TopExp.hxx>
57 #include <TopExp_Explorer.hxx>
58
59 #include <BRep_Builder.hxx>
60 #include <BRep_Tool.hxx>
61 //
62 #include <TopTools_ListOfShape.hxx>
63 #include <TopTools_IndexedMapOfShape.hxx>
64 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
65 #include <TopTools_IndexedMapOfShape.hxx>
66 #include <TopTools_ListIteratorOfListOfShape.hxx>
67 #include <TopTools_MapOfShape.hxx>
68
69 #include <BRepClass3d_SolidClassifier.hxx>
70
71 #include <IntTools_Context.hxx>
72 #include <IntTools_Tools.hxx>
73
74 #include <BOPTools_Tools3D.hxx>
75 #include <BOPTools_Tools2D.hxx>
76 #include <BOPTools_Tools.hxx>
77
78 #include <NMTTools_ListOfCoupleOfShape.hxx>
79 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
80 #include <NMTTools_CoupleOfShape.hxx>
81 #include <TopTools_DataMapOfShapeListOfShape.hxx>
82 #include <TopTools_DataMapOfShapeListOfShape.hxx>
83 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
84 #include <TopTools_MapOfShape.hxx>
85 #include <TopTools_MapIteratorOfMapOfShape.hxx>
86 //
87
88 static
89   Standard_Boolean FindFacePairs (const TopoDS_Edge& ,
90                                   const TopTools_ListOfShape& ,
91                                   NMTTools_ListOfCoupleOfShape& );
92
93
94 static
95   Standard_Real AngleWithRef(const gp_Dir& ,
96                              const gp_Dir& ,
97                              const gp_Dir& );
98
99 //=======================================================================
100 //function : IsInternalFace
101 //purpose  : 
102 //=======================================================================
103   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
104                                                    const TopoDS_Solid& theSolid,
105                                                    const TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
106                                                    const Standard_Real theTol,
107                                                    IntTools_Context& theContext)
108 {
109   Standard_Boolean bRet;
110   Standard_Integer aNbF;
111   TopoDS_Edge aEL;
112   TopExp_Explorer aExp;
113   TopTools_ListIteratorOfListOfShape aItF;
114   //
115   bRet=Standard_False;
116   //
117   // 1 Try to find an edge from theFace in theMEF
118   aExp.Init(theFace, TopAbs_EDGE);
119   for(; aExp.More(); aExp.Next()) {
120     const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
121     if (!theMEF.Contains(aE)) {
122       continue;
123     }
124     // 
125     const TopTools_ListOfShape& aLF=theMEF.FindFromKey(aE);
126     aNbF=aLF.Extent();
127     if (!aNbF) {
128       return bRet; // it can not be so
129     }
130     else if (aNbF==1) {
131       // aE is internal edge on aLF.First()
132       const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
133       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF1);
134       return bRet;
135     }
136     else if (aNbF==2) {
137       const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
138       const TopoDS_Face& aF2=TopoDS::Face(aLF.Last());
139       //
140       if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
141         // treat as it was for 1 face
142         bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF2);
143         return bRet;
144       }
145     }
146     if (aNbF%2) {
147       return bRet; // it can not be so
148     }
149     else { // aNbF=2,4,6,8,...
150       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aLF);
151       return bRet;
152     }
153   }//for(; aExp.More(); aExp.Next()) {
154   //
155   //========================================
156   // 2. Classify face using classifier
157   //
158   TopAbs_State aState;
159   TopTools_IndexedMapOfShape aBounds;
160   //
161   aState=GEOMAlgo_Tools3D::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
162   bRet=(aState==TopAbs_IN);
163   //
164   return bRet;
165 }
166 //=======================================================================
167 //function : IsInternalFace
168 //purpose  : 
169 //=======================================================================
170   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
171                                                     const TopoDS_Edge& theEdge,
172                                                     const TopTools_ListOfShape& theLF)
173 {
174   Standard_Boolean bRet;
175   Standard_Boolean aNbF;
176   //
177   bRet=Standard_False;
178   //
179   aNbF=theLF.Extent();
180   if (aNbF==2) {
181     const TopoDS_Face& aF1=TopoDS::Face(theLF.First());
182     const TopoDS_Face& aF2=TopoDS::Face(theLF.Last());
183     bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, theEdge, aF1, aF2);
184     return bRet;
185   }
186   //
187   else {
188     NMTTools_ListOfCoupleOfShape aLCFF;
189     NMTTools_ListIteratorOfListOfCoupleOfShape aIt;
190     //
191     FindFacePairs(theEdge, theLF, aLCFF);
192     //
193     aIt.Initialize(aLCFF);
194     for (; aIt.More(); aIt.Next()) {
195       const NMTTools_CoupleOfShape& aCSFF=aIt.Value();
196       //
197       const TopoDS_Face& aF1=TopoDS::Face(aCSFF.Shape1());
198       const TopoDS_Face& aF2=TopoDS::Face(aCSFF.Shape2());
199       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, theEdge, aF1, aF2);
200       if (bRet) {
201         return bRet;
202       }
203     }
204   }
205   return bRet;
206 }
207 //=======================================================================
208 //function : IsInternalFace
209 //purpose  : 
210 //=======================================================================
211   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
212                                                    const TopoDS_Edge& theEdge,
213                                                    const TopoDS_Face& theFace1,
214                                                    const TopoDS_Face& theFace2)
215 {
216   Standard_Boolean bRet;
217   Standard_Real aT1, aT2, aT, aDt2D, aDt2Dx;//aD1, aD2,
218   gp_Pnt aPx, aPF, aPF1, aPF2;
219   gp_Pnt2d aP2D, aPF2D;
220   gp_Dir aDNF1, aDNF2;
221   TopoDS_Edge aE1, aE2;
222   Handle(Geom_Curve)aC3D;
223   //
224   aC3D =BRep_Tool::Curve(theEdge, aT1, aT2);
225   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
226   aC3D->D0(aT, aPx);
227   //
228   // 1. PF
229   aDt2D=BOPTools_Tools3D::MinStepIn2d();
230   aDt2Dx=10.*aDt2D;
231   BOPTools_Tools3D::PointNearEdge (theEdge, theFace, aT, aDt2Dx, aPF2D, aPF);
232   // 
233   // 2. E1, E2
234   GEOMAlgo_Tools3D::GetEdgeOnFace(theEdge, theFace1, aE1);
235   if (aE1.Orientation()==TopAbs_INTERNAL) {
236     aE2=aE1;
237     aE1.Orientation(TopAbs_FORWARD);
238     aE2.Orientation(TopAbs_REVERSED);
239   }
240   else if (theFace1==theFace2) {
241     aE2=aE1;
242     aE1.Orientation(TopAbs_FORWARD);
243     aE2.Orientation(TopAbs_REVERSED);
244   }
245   else {
246     GEOMAlgo_Tools3D::GetEdgeOnFace(theEdge, theFace2, aE2);
247   }
248   //
249   // 3
250   bRet=Standard_False;
251   //
252   //modified by NIZNHY-PKV Mon Nov 13 12:12:53 2006f
253   //
254   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aE1, theFace1, aT, aPF1, aDNF1);
255   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aE2, theFace2, aT, aPF2, aDNF2);
256   //
257   {
258     Standard_Real aA12, aA1x, aTwoPI;
259     //
260     aTwoPI=2.*PI;
261     gp_Vec aVBF (aPx, aPF );
262     gp_Vec aVBF1(aPx, aPF1);
263     gp_Vec aVBF2(aPx, aPF2);
264     //
265     gp_Dir aDTF1;
266     gp_Dir aDBF (aVBF);
267     gp_Dir aDBF1(aVBF1);
268     gp_Dir aDBF2(aVBF2);
269     //
270     aDTF1=aDNF1^aDBF1;
271     //aA12=aDBF1.AngleWithRef(aDBF2, aDTF1);
272     aA12=AngleWithRef(aDBF1, aDBF2, aDTF1);
273     if (aA12<0.) {
274       aA12=aA12+aTwoPI;
275     }
276     //aA1x=aDBF1.AngleWithRef(aDBF , aDTF1);
277     aA1x=AngleWithRef(aDBF1, aDBF , aDTF1);
278     if (aA1x<0.) {
279       aA1x=aA1x+aTwoPI;
280     }
281     //
282     if (aA1x<aA12) {
283       bRet=!bRet; //TopAbs_IN;
284     }
285   }
286   //
287   /*
288   {
289     Standard_Real aD1, aD2;
290     //
291     //BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aE1, theFace1, aT, aPF1, aDNF1);
292     gp_Pln aPlnF1(aPx, aDNF1);
293     //
294     aD1=BOPTools_Tools3D::SignDistance(aPF, aPlnF1);
295     if (aD1<=0.) {
296       //BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aE2, theFace2, aT, aPF2, aDNF2);
297       gp_Pln aPlnF2(aPx, aDNF2);
298       //
299       aD2=BOPTools_Tools3D::SignDistance(aPF, aPlnF2);
300       if (aD2<=0.) {
301         bRet=!bRet; //TopAbs_IN;
302       }
303     }
304   }
305   */
306   //modified by NIZNHY-PKV Mon Nov 13 12:12:55 2006t
307   //
308   return bRet;
309   
310 }
311 //=======================================================================
312 //function : GetFaceOff
313 //purpose  : 
314 //=======================================================================
315   void GEOMAlgo_Tools3D::GetFaceOff(const TopoDS_Edge& theE1,
316                                    const TopoDS_Face& theF1,
317                                    const NMTTools_ListOfCoupleOfShape& theLCSOff,
318                                    TopoDS_Face& theFOff)
319 {
320   Standard_Real aT, aT1, aT2, aAngle, aTwoPI, aAngleMin;
321   gp_Pnt aPn1, aPn2;
322   gp_Vec aVTgt;
323   gp_Dir aDN1, aDN2;
324   NMTTools_ListIteratorOfListOfCoupleOfShape aIt;
325   //
326   aAngleMin=100.;
327   aTwoPI=PI+PI;
328   BRep_Tool::Range(theE1, aT1, aT2);
329   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
330   // Ref
331   BOPTools_Tools2D::EdgeTangent(theE1, aT, aVTgt);
332   gp_Dir aDTtgt(aVTgt);
333   aDTtgt.Reverse();
334   // N1
335   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge(theE1, theF1, aT, aPn1, aDN1);
336   //
337   aIt.Initialize(theLCSOff);
338   for (; aIt.More(); aIt.Next()) {
339     const NMTTools_CoupleOfShape& aCS=aIt.Value();
340     const TopoDS_Edge& aE2=TopoDS::Edge(aCS.Shape1());
341     const TopoDS_Face& aF2=TopoDS::Face(aCS.Shape2());
342     //
343     if (aF2==theF1) {
344       aAngle=PI;
345     }
346     else if (aF2.IsSame(theF1)) {
347       aAngle=aTwoPI;
348     }
349     else {
350       BOPTools_Tools3D::GetApproxNormalToFaceOnEdge (aE2, aF2, aT, aPn2, aDN2);
351       aDN2.Reverse();
352       // Angle
353       //
354       //aAngle=aDN1.AngleWithRef(aDN2, aDTtgt);
355       aAngle=AngleWithRef(aDN1, aDN2, aDTtgt);
356       //
357       if(aAngle<0.) {
358         aAngle=aTwoPI+aAngle;
359       }
360     }
361
362     if (aAngle<aAngleMin){
363       aAngleMin=aAngle;
364       theFOff=aF2;
365     }
366   }
367 }
368 //=======================================================================
369 //function : GetEdgeOnFace
370 //purpose  : 
371 //=======================================================================
372   Standard_Boolean GEOMAlgo_Tools3D::GetEdgeOnFace(const TopoDS_Edge& theE1,
373                                                   const TopoDS_Face& theF2,
374                                                   TopoDS_Edge& theE2)
375 {
376   Standard_Boolean bFound;
377   TopoDS_Iterator aItF, aItW;
378   //
379   bFound=Standard_False;
380   //
381   aItF.Initialize(theF2);
382   for (; aItF.More(); aItF.Next()) {
383     const TopoDS_Shape& aW=aItF.Value();
384     aItW.Initialize(aW);
385     for (; aItW.More(); aItW.Next()) {
386       const TopoDS_Shape& aE=aItW.Value();
387       if (aE.IsSame(theE1)) {
388         theE2=TopoDS::Edge(aE);
389         bFound=!bFound;
390         return bFound;
391       }
392     }
393   }
394   return bFound;
395 }
396 //=======================================================================
397 //function : GetEdgeOff
398 //purpose  : 
399 //=======================================================================
400   Standard_Boolean GEOMAlgo_Tools3D::GetEdgeOff(const TopoDS_Edge& theE1,
401                                                const TopoDS_Face& theF2,
402                                                TopoDS_Edge& theE2)
403      
404 {
405   Standard_Boolean bFound;
406   TopAbs_Orientation aOr1, aOr1C, aOr2;
407   TopExp_Explorer anExp;
408   //
409   bFound=Standard_False;
410   aOr1=theE1.Orientation();
411   aOr1C=TopAbs::Reverse(aOr1);
412   //
413   anExp.Init(theF2, TopAbs_EDGE);
414   for (; anExp.More(); anExp.Next()) {
415     const TopoDS_Edge& aEF2=TopoDS::Edge(anExp.Current());
416     if (aEF2.IsSame(theE1)) {
417       aOr2=aEF2.Orientation();
418       if (aOr2==aOr1C) {
419         theE2=aEF2;
420         bFound=!bFound;
421         return bFound;
422       }
423     }
424   }
425   return bFound;
426 }
427 //=======================================================================
428 // function:  ComputeState
429 // purpose: 
430 //=======================================================================
431   TopAbs_State GEOMAlgo_Tools3D::ComputeState(const TopoDS_Face& theF,
432                                              const TopoDS_Solid& theRef,
433                                              const Standard_Real theTol,
434                                              const TopTools_IndexedMapOfShape& theBounds,
435                                              IntTools_Context& theCtx)
436 {
437   TopAbs_State aState;
438   TopExp_Explorer aExp; 
439   TopoDS_Edge aE1;
440   gp_Pnt2d aP2D;
441   gp_Pnt aP3D; 
442   //
443   aState=TopAbs_UNKNOWN;
444   //
445   aExp.Init(theF, TopAbs_EDGE);
446   for (; aExp.More(); aExp.Next()) {
447     const TopoDS_Edge& aSE=TopoDS::Edge(aExp.Current());
448     if (BRep_Tool::Degenerated(aSE)) {
449       continue;
450     }
451     //
452     if (!theBounds.Contains(aSE)) {
453       const TopoDS_Edge& aE=TopoDS::Edge(aSE);
454       aState= GEOMAlgo_Tools3D::ComputeState(aE, theRef, theTol, theCtx);
455       return aState;
456     }
457     if (aE1.IsNull()) {
458       aE1=TopoDS::Edge(aSE);
459     }
460   }
461   // !!<- process edges that are all on theRef
462   if (!aE1.IsNull()) {
463     BOPTools_Tools3D::PointNearEdge(aE1, theF, aP2D, aP3D);
464     aState=GEOMAlgo_Tools3D::ComputeState(aP3D, theRef, theTol, theCtx);
465   }
466   //
467   return aState;
468 }
469 //=======================================================================
470 // function:  ComputeStateByOnePoint
471 // purpose: 
472 //=======================================================================
473   TopAbs_State GEOMAlgo_Tools3D::ComputeStateByOnePoint(const TopoDS_Shape& theS,
474                                                        const TopoDS_Solid& theRef,
475                                                        const Standard_Real theTol,
476                                                        IntTools_Context& theCtx)
477 {
478   TopAbs_State aState;
479   TopAbs_ShapeEnum aType;
480   //
481   aState=TopAbs_UNKNOWN;
482   aType=theS.ShapeType();
483   if (aType==TopAbs_VERTEX) {
484     const TopoDS_Vertex& aV=TopoDS::Vertex(theS);
485     aState=GEOMAlgo_Tools3D::ComputeState(aV, theRef, theTol, theCtx);
486   }
487   else if (aType==TopAbs_EDGE) {
488     const TopoDS_Edge& aE=TopoDS::Edge(theS);
489     aState=GEOMAlgo_Tools3D::ComputeState(aE, theRef, theTol, theCtx);
490   }
491   return aState;
492 }
493 //=======================================================================
494 // function:  ComputeState
495 // purpose: 
496 //=======================================================================
497   TopAbs_State GEOMAlgo_Tools3D::ComputeState(const TopoDS_Vertex& theV,
498                                              const TopoDS_Solid& theRef,
499                                              const Standard_Real theTol,
500                                              IntTools_Context& theCtx)
501 {
502   TopAbs_State aState;
503   gp_Pnt aP3D; 
504   //
505   aP3D=BRep_Tool::Pnt(theV);
506   aState=GEOMAlgo_Tools3D::ComputeState(aP3D, theRef, theTol, theCtx);
507   return aState;
508 }
509 //=======================================================================
510 // function:  ComputeState
511 // purpose: 
512 //=======================================================================
513   TopAbs_State GEOMAlgo_Tools3D::ComputeState(const TopoDS_Edge& theE,
514                                              const TopoDS_Solid& theRef,
515                                              const Standard_Real theTol,
516                                              IntTools_Context& theCtx)
517 {
518   Standard_Real aT1, aT2, aT = 0.;
519   TopAbs_State aState;
520   Handle(Geom_Curve) aC3D;
521   gp_Pnt aP3D; 
522   //
523   aC3D = BRep_Tool::Curve(theE, aT1, aT2);
524   //
525   if(aC3D.IsNull()) {
526     //it means that we are in degenerated edge
527     const TopoDS_Vertex& aV = TopExp::FirstVertex(theE);
528     if(aV.IsNull()){
529       return TopAbs_UNKNOWN;
530     }
531     aP3D=BRep_Tool::Pnt(aV);
532   }
533   else {//usual case
534     Standard_Boolean bF2Inf, bL2Inf;
535     Standard_Real dT=10.;
536     //
537     bF2Inf = Precision::IsNegativeInfinite(aT1);
538     bL2Inf = Precision::IsPositiveInfinite(aT2);
539     //
540     if (bF2Inf && !bL2Inf) {
541       aT=aT2-dT;
542     }
543     else if (!bF2Inf && bL2Inf) {
544       aT=aT1+dT;
545     }
546     else if (bF2Inf && bL2Inf) {
547       aT=0.;
548     }
549     else {
550       aT=IntTools_Tools::IntermediatePoint(aT1, aT2);
551     }
552     aC3D->D0(aT, aP3D);
553   }
554   //
555   aState=GEOMAlgo_Tools3D::ComputeState(aP3D, theRef, theTol, theCtx);
556   //
557   return aState;
558 }
559 //=======================================================================
560 // function:  ComputeState
561 // purpose: 
562 //=======================================================================
563   TopAbs_State GEOMAlgo_Tools3D::ComputeState(const gp_Pnt& theP,
564                                              const TopoDS_Solid& theRef,
565                                              const Standard_Real theTol,
566                                              IntTools_Context& theCtx)
567 {
568   TopAbs_State aState;
569   //
570   BRepClass3d_SolidClassifier& aSC=theCtx.SolidClassifier(theRef);
571   aSC.Perform(theP, theTol);
572   //
573   aState=aSC.State();
574   //
575   return aState;
576 }
577 //=======================================================================
578 // function: IsSplitToReverse
579 // purpose: 
580 //=======================================================================
581   Standard_Boolean GEOMAlgo_Tools3D::IsSplitToReverse(const TopoDS_Shape& theSp,
582                                                      const TopoDS_Shape& theSr,
583                                                      IntTools_Context& theCtx)
584 {
585   Standard_Boolean bRet;
586   TopAbs_ShapeEnum aType;
587   //
588   bRet=Standard_False;
589   //
590   aType=theSp.ShapeType();
591   switch (aType) {
592     case TopAbs_EDGE: {
593       const TopoDS_Edge& aESp=TopoDS::Edge(theSp);
594       const TopoDS_Edge& aESr=TopoDS::Edge(theSr);
595       bRet=GEOMAlgo_Tools3D::IsSplitToReverse(aESp, aESr, theCtx);
596     }
597       break;
598       //
599     case TopAbs_FACE: {
600       const TopoDS_Face& aFSp=TopoDS::Face(theSp);
601       const TopoDS_Face& aFSr=TopoDS::Face(theSr);
602       bRet=GEOMAlgo_Tools3D::IsSplitToReverse(aFSp, aFSr, theCtx);
603     }
604       break;
605       //
606     default:
607       break;
608   }
609   return bRet;
610 }
611 //=======================================================================
612 //function :IsSplitToReverse
613 //purpose  : 
614 //=======================================================================
615   Standard_Boolean GEOMAlgo_Tools3D::IsSplitToReverse(const TopoDS_Face& theFSp,
616                                                      const TopoDS_Face& theFSr,
617                                                      IntTools_Context& theContext)
618 {
619   Standard_Boolean bRet, bFound, bInFace;
620   Standard_Real aT1, aT2, aT, aU, aV, aScPr;
621   gp_Pnt aPFSp, aPFSr;
622   gp_Dir aDNFSp;
623   gp_Vec aD1U, aD1V;
624   Handle(Geom_Surface) aSr, aSp;
625   TopAbs_Orientation aOrSr, aOrSp;
626   TopExp_Explorer anExp;
627   TopoDS_Edge aESp;
628   //
629   bRet=Standard_False;
630   //
631   aSr=BRep_Tool::Surface(theFSr);
632   aSp=BRep_Tool::Surface(theFSp);
633   if (aSr==aSp) {
634     aOrSr=theFSr.Orientation();
635     aOrSp=theFSp.Orientation();
636     bRet=(aOrSr!=aOrSp);
637     return bRet;
638   }
639   //
640   bFound=Standard_False;
641   anExp.Init(theFSp, TopAbs_EDGE);
642   for (; anExp.More(); anExp.Next()) {
643     aESp=TopoDS::Edge(anExp.Current());
644     if (!BRep_Tool::Degenerated(aESp)) {
645       if (!BRep_Tool::IsClosed(aESp, theFSp)) {
646         bFound=!bFound;
647         break;
648       }
649     }
650   }
651   if (!bFound) {
652     return bRet;
653   }
654   //
655   BRep_Tool::Range(aESp, aT1, aT2);
656   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
657   BOPTools_Tools3D::GetApproxNormalToFaceOnEdge(aESp, theFSp, aT, aPFSp, aDNFSp);
658   //
659   // Parts of theContext.ComputeVS(..) 
660   GeomAPI_ProjectPointOnSurf& aProjector=theContext.ProjPS(theFSr);
661   aProjector.Perform(aPFSp);
662   if (!aProjector.IsDone()) {
663     return bRet;
664   }
665   //
666   aProjector.LowerDistanceParameters(aU, aV);
667   gp_Pnt2d aP2D(aU, aV);
668   bInFace=theContext.IsPointInFace (theFSr, aP2D);
669   if (!bInFace) {
670     return bRet;
671   }
672   //
673   aSr->D1(aU, aV, aPFSr, aD1U, aD1V);
674   gp_Dir aDD1U(aD1U); 
675   gp_Dir aDD1V(aD1V);
676   gp_Dir aDNFSr=aDD1U^aDD1V; 
677   if (theFSr.Orientation()==TopAbs_REVERSED){
678     aDNFSr.Reverse();
679   }
680   //
681   aScPr=aDNFSp*aDNFSr;
682   bRet=(aScPr<0.);
683   //
684   return bRet;
685 }
686 //=======================================================================
687 //function :IsSplitToReverse
688 //purpose  : 
689 //=======================================================================
690   Standard_Boolean GEOMAlgo_Tools3D::IsSplitToReverse(const TopoDS_Edge& theSplit,
691                                                      const TopoDS_Edge& theEdge,
692                                                      IntTools_Context& theContext)
693 {
694   Standard_Boolean bRet, aFlag, bIsDegenerated;
695   Standard_Real aTE, aTS, aScPr, aTa, aTb, aT1, aT2;
696   TopAbs_Orientation aOrSr, aOrSp;
697   Handle(Geom_Curve) aCEdge, aCSplit;
698   gp_Vec aVE, aVS;
699   gp_Pnt aP;
700   //
701   bRet=Standard_False;
702   //
703   bIsDegenerated=(BRep_Tool::Degenerated(theSplit) || 
704                   BRep_Tool::Degenerated(theEdge));
705   if (bIsDegenerated) {
706     return bRet;
707   }
708   //
709   aCEdge =BRep_Tool::Curve(theEdge , aT1, aT2);
710   aCSplit=BRep_Tool::Curve(theSplit, aTa, aTb);
711   //
712   if (aCEdge==aCSplit) {
713     aOrSr=theEdge.Orientation();
714     aOrSp=theSplit.Orientation();
715     bRet=(aOrSr!=aOrSp);
716     return bRet;
717   }
718   //
719   aTS=BOPTools_Tools2D::IntermediatePoint(aTa, aTb);
720   aCSplit->D0(aTS, aP);
721   aFlag=BOPTools_Tools2D::EdgeTangent(theSplit, aTS, aVS);
722   gp_Dir aDTS(aVS);
723   //
724   aFlag=theContext.ProjectPointOnEdge(aP, theEdge, aTE);
725   aFlag=BOPTools_Tools2D::EdgeTangent(theEdge, aTE, aVE);
726   gp_Dir aDTE(aVE);
727   //
728   aScPr=aDTS*aDTE;
729   bRet=(aScPr<0.);
730   //
731   return bRet;
732 }
733
734 //=======================================================================
735 // function: Sense
736 // purpose: 
737 //=======================================================================
738   Standard_Integer GEOMAlgo_Tools3D::Sense (const TopoDS_Face& theF1,
739                                            const TopoDS_Face& theF2)
740 {
741   Standard_Integer iSense=0;
742   gp_Dir aDNF1, aDNF2;
743   TopoDS_Edge aE1, aE2;
744   TopExp_Explorer anExp;
745   //
746   anExp.Init(theF1, TopAbs_EDGE);
747   for (; anExp.More(); anExp.Next()) {
748     aE1=TopoDS::Edge(anExp.Current());
749     if (!BRep_Tool::Degenerated(aE1)) {
750       if (!BRep_Tool::IsClosed(aE1, theF1)) {
751         break;
752       }
753     }
754   }
755   //
756   anExp.Init(theF2, TopAbs_EDGE);
757   for (; anExp.More(); anExp.Next()) {
758     aE2=TopoDS::Edge(anExp.Current());
759     if (!BRep_Tool::Degenerated(aE2)) {
760       if (!BRep_Tool::IsClosed(aE2, theF2)) {
761         if (aE2.IsSame(aE1)) {
762           iSense=1;
763           break;
764         }
765       }
766     }
767   }
768   //
769   if (!iSense) {
770     return iSense;
771   }
772   //
773   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, theF1, aDNF1);
774   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, theF2, aDNF2);
775   //
776   iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
777   //
778   return iSense;
779 }
780 //=======================================================================
781 // function: CopyFace
782 // purpose: 
783 //=======================================================================
784   void GEOMAlgo_Tools3D::CopyFace (const TopoDS_Face& theF1,
785                                   TopoDS_Face& theF2)
786 {
787   Standard_Real aTol;
788   TopLoc_Location aLoc;
789   TopAbs_Orientation aOr;
790   TopoDS_Iterator aIt;
791   BRep_Builder aBB;
792   //
793   Handle(Geom_Surface) aSurface=BRep_Tool::Surface(theF1, aLoc);
794   aTol=BRep_Tool::Tolerance(theF1);
795   aOr=theF1.Orientation();
796   //
797   aBB.MakeFace (theF2, aSurface, aLoc, aTol);
798   theF2.Orientation(aOr);
799   //
800   aIt.Initialize(theF1);
801   for (; aIt.More(); aIt.Next()) {
802     const TopoDS_Shape& aW=aIt.Value();
803     aBB.Add(theF2, aW);
804   }
805 }
806 //=======================================================================
807 // function: MakeContainer
808 // purpose: 
809 //=======================================================================
810   void GEOMAlgo_Tools3D::MakeContainer(const TopAbs_ShapeEnum theType,
811                                       TopoDS_Shape& theC)
812 {
813   BRep_Builder aBB;
814   //
815   switch(theType) {
816     case TopAbs_COMPOUND:{
817       TopoDS_Compound aC;
818       aBB.MakeCompound(aC);
819       theC=aC;
820     }
821       break;
822       //
823     case TopAbs_COMPSOLID:{
824       TopoDS_CompSolid aCS;
825       aBB.MakeCompSolid(aCS);
826       theC=aCS;
827     }
828       break;
829       //
830     case TopAbs_SOLID:{
831       TopoDS_Solid aSolid;
832       aBB.MakeSolid(aSolid);
833       theC=aSolid;
834     }  
835       break;
836       //
837       //
838     case TopAbs_SHELL:{
839       TopoDS_Shell aShell;
840       aBB.MakeShell(aShell);
841       theC=aShell;
842     }  
843       break;
844       //
845     case TopAbs_WIRE: {
846       TopoDS_Wire aWire;
847       aBB.MakeWire(aWire);
848       theC=aWire;
849     }
850       break;
851       //
852     default:
853       break;
854   }
855 }
856 //=======================================================================
857 // function: MakeConnexityBlock.
858 // purpose: 
859 //=======================================================================
860   void GEOMAlgo_Tools3D::MakeConnexityBlock (const TopTools_ListOfShape& theLFIn,
861                                              const TopTools_IndexedMapOfShape& theMEAvoid,
862                                              TopTools_ListOfShape& theLCB)
863 {
864   Standard_Integer  aNbF, aNbAdd1;
865   TopExp_Explorer aExp;
866   TopTools_IndexedDataMapOfShapeListOfShape aMEF;
867   TopTools_MapIteratorOfMapOfShape aItM, aItM1;
868   TopTools_MapOfShape aMCB, aMAdd, aMAdd1;
869   TopTools_ListIteratorOfListOfShape aIt;
870   //
871   // 1. aMEF
872   aNbF=theLFIn.Extent();
873   aIt.Initialize(theLFIn);
874   for (; aIt.More(); aIt.Next()) {
875     const TopoDS_Shape& aF=aIt.Value();      
876     TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
877   }
878   //
879   // 2. aMCB
880   const TopoDS_Shape& aF1=theLFIn.First();
881   aMAdd.Add(aF1);
882   //
883   while(1) {
884     aMAdd1.Clear();
885     aItM.Initialize(aMAdd);
886     for (; aItM.More(); aItM.Next()) {
887       const TopoDS_Shape& aF=aItM.Key();
888       //
889       //aMAdd1.Clear();
890       aExp.Init(aF, TopAbs_EDGE);
891       for (; aExp.More(); aExp.Next()) {
892         const TopoDS_Shape& aE=aExp.Current();
893         if (theMEAvoid.Contains(aE)){
894           continue;
895         }
896         //
897         const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
898         aIt.Initialize(aLF);
899         for (; aIt.More(); aIt.Next()) {
900           const TopoDS_Shape& aFx=aIt.Value();
901           if (aFx.IsSame(aF)) {
902             continue;
903           }
904           if (aMCB.Contains(aFx)) {
905             continue;
906           }
907           aMAdd1.Add(aFx);
908         }
909       }//for (; aExp.More(); aExp.Next()){
910       aMCB.Add(aF);
911     }// for (; aItM.More(); aItM.Next()) {
912     //
913     aNbAdd1=aMAdd1.Extent();
914     if (!aNbAdd1) {
915       break;
916     }
917     //
918     aMAdd.Clear();
919     aItM1.Initialize(aMAdd1);
920     for (; aItM1.More(); aItM1.Next()) {
921       const TopoDS_Shape& aFAdd=aItM1.Key();
922       aMAdd.Add(aFAdd);
923     }
924     //
925   }//while(1) {
926   
927   //
928   aNbF=aMCB.Extent();
929   aItM.Initialize(aMCB);
930   for (; aItM.More(); aItM.Next()) {
931     const TopoDS_Shape& aF=aItM.Key();
932     theLCB.Append(aF);
933   }
934 }
935
936 //=======================================================================
937 //function : FindFacePairs
938 //purpose  : 
939 //=======================================================================
940 Standard_Boolean FindFacePairs (const TopoDS_Edge& theE,
941                                 const TopTools_ListOfShape& thLF,
942                                 NMTTools_ListOfCoupleOfShape& theLCFF)
943 {
944   Standard_Boolean bFound;
945   Standard_Integer i, aNbCEF;
946   TopAbs_Orientation aOr, aOrC;
947   TopTools_MapOfShape aMFP;
948   TopoDS_Face aF1, aF2;
949   TopoDS_Edge aEL, aE1;
950   TopTools_ListIteratorOfListOfShape aItLF;
951   NMTTools_CoupleOfShape aCEF, aCFF;
952   NMTTools_ListOfCoupleOfShape aLCEF, aLCEFx;
953   NMTTools_ListIteratorOfListOfCoupleOfShape aIt;
954   //
955   bFound=Standard_True;
956   //
957   // Preface aLCEF
958   aItLF.Initialize(thLF);
959   for (; aItLF.More(); aItLF.Next()) { 
960     const TopoDS_Face& aFL=TopoDS::Face(aItLF.Value());
961     //
962     bFound=GEOMAlgo_Tools3D::GetEdgeOnFace(theE, aFL, aEL);
963     if (!bFound) {
964       return bFound; // it can not be so
965     }
966     //
967     aCEF.SetShape1(aEL);
968     aCEF.SetShape2(aFL);
969     aLCEF.Append(aCEF);
970   }
971   //
972   aNbCEF=aLCEF.Extent();
973   while(aNbCEF) {
974     //
975     // aLCEFx
976     aLCEFx.Clear();
977     aIt.Initialize(aLCEF);
978     for (i=0; aIt.More(); aIt.Next(), ++i) {
979       const NMTTools_CoupleOfShape& aCSx=aIt.Value();
980       const TopoDS_Shape& aEx=aCSx.Shape1();
981       const TopoDS_Shape& aFx=aCSx.Shape2();
982       //
983       aOr=aEx.Orientation();
984       //
985       if (!i) {
986         aOrC=TopAbs::Reverse(aOr);
987         aE1=TopoDS::Edge(aEx);
988         aF1=TopoDS::Face(aFx);
989         aMFP.Add(aFx);
990         continue;
991       }
992       //
993       if (aOr==aOrC) {
994         aLCEFx.Append(aCSx);
995         aMFP.Add(aFx);
996       }
997     }
998     //
999     // F2
1000     GEOMAlgo_Tools3D::GetFaceOff(aE1, aF1, aLCEFx, aF2);
1001     //
1002     aCFF.SetShape1(aF1);
1003     aCFF.SetShape2(aF2);
1004     theLCFF.Append(aCFF);
1005     //
1006     aMFP.Add(aF1);
1007     aMFP.Add(aF2);
1008     //
1009     // refine aLCEF
1010     aLCEFx.Clear();
1011     aLCEFx=aLCEF;
1012     aLCEF.Clear();
1013     aIt.Initialize(aLCEFx);
1014     for (; aIt.More(); aIt.Next()) {
1015       const NMTTools_CoupleOfShape& aCSx=aIt.Value();
1016       const TopoDS_Shape& aFx=aCSx.Shape2();
1017       if (!aMFP.Contains(aFx)) {
1018         aLCEF.Append(aCSx);
1019       }
1020     }
1021     //
1022     aNbCEF=aLCEF.Extent();
1023   }//while(aNbCEF) {
1024   //
1025   return bFound;
1026 }
1027 //
1028 //=======================================================================
1029 //function : AngleWithRef
1030 //purpose  : 
1031 //=======================================================================
1032 Standard_Real AngleWithRef(const gp_Dir& theD1,
1033                            const gp_Dir& theD2,
1034                            const gp_Dir& theDRef)
1035 {
1036   Standard_Real aCosinus, aSinus, aBeta, aHalfPI, aScPr;
1037   gp_XYZ aXYZ;
1038   //
1039   aHalfPI=0.5*PI;
1040   //
1041   const gp_XYZ& aXYZ1=theD1.XYZ();
1042   const gp_XYZ& aXYZ2=theD2.XYZ();
1043   aXYZ=aXYZ1.Crossed(aXYZ2);
1044   aSinus=aXYZ.Modulus();
1045   aCosinus=theD1*theD2;
1046   //
1047   aBeta=0.;
1048   if (aSinus>=0.) {
1049     aBeta=aHalfPI*(1.-aCosinus);
1050   }
1051   else {
1052     aBeta=2.*PI-aHalfPI*(3.+aCosinus);
1053   }
1054   //
1055   aScPr=aXYZ.Dot(theDRef.XYZ());
1056   if (aScPr<0.) {
1057     aBeta=-aBeta;
1058   }
1059   return aBeta;
1060 }
1061 //
1062 /*
1063 static
1064   void Path(const TopoDS_Shape& ,
1065           const TopoDS_Shape& ,
1066           const TopTools_IndexedDataMapOfShapeListOfShape& ,
1067           const TopTools_IndexedMapOfShape& ,
1068           TopTools_IndexedMapOfShape& );
1069
1070 //=======================================================================
1071 // function: MakeConnexityBlock.
1072 // purpose: 
1073 //=======================================================================
1074   void GEOMAlgo_Tools3D::MakeConnexityBlock (const TopTools_ListOfShape& theLFIn,
1075                                             const TopTools_IndexedMapOfShape& theMEAvoid,
1076                                             TopTools_ListOfShape& theLCB)
1077 {
1078   Standard_Integer  j, aNbF;
1079   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
1080   TopTools_IndexedMapOfShape aMFP, aCBMap;
1081   TopTools_ListIteratorOfListOfShape aIt;
1082   TopExp_Explorer aExp;
1083   TopAbs_ShapeEnum aType;
1084   //
1085   aIt.Initialize(theLFIn);
1086   for (; aIt.More(); aIt.Next()) {
1087     const TopoDS_Shape& aF=aIt.Value();      
1088     aType=aF.ShapeType();
1089     TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
1090   }
1091   //
1092   aCBMap.Clear();
1093   const TopoDS_Shape& aF=theLFIn.First();
1094   //
1095   aCBMap.Add(aF);
1096   //
1097   aExp.Init(aF, TopAbs_EDGE);
1098   for (; aExp.More(); aExp.Next()){
1099     const TopoDS_Shape& aE=aExp.Current();
1100     if (theMEAvoid.Contains(aE)){
1101       continue;
1102     }
1103     //
1104     const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
1105     aIt.Initialize(aLF);
1106     for (; aIt.More(); aIt.Next()) {
1107       const TopoDS_Shape& aF1=aIt.Value();
1108       if (!aF1.IsSame(aF)) {
1109         Path (aE, aF1, aEFMap, theMEAvoid,  aCBMap);
1110       }
1111     }
1112   }
1113   //
1114   aNbF=aCBMap.Extent();
1115   for (j=1; j<=aNbF; ++j) {
1116     const TopoDS_Shape& aFx=aCBMap(j);
1117     theLCB.Append(aFx);
1118   }
1119 }
1120 //=======================================================================
1121 // function: Path
1122 // purpose: 
1123 //=======================================================================
1124 void Path(const TopoDS_Shape& theE1,
1125           const TopoDS_Shape& theF1,
1126           const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap,
1127           const TopTools_IndexedMapOfShape& theMEAvoid,
1128           TopTools_IndexedMapOfShape& theCBMap)
1129 {
1130   TopTools_ListIteratorOfListOfShape aIt;
1131   TopExp_Explorer aExp;
1132   //
1133   if (theCBMap.Contains(theF1)){
1134     return;
1135   }
1136   theCBMap.Add(theF1);
1137   //
1138   aExp.Init(theF1, TopAbs_EDGE);
1139   for (; aExp.More(); aExp.Next()){
1140     const TopoDS_Shape& aE=aExp.Current();
1141     if (!aE.IsSame(theE1)){
1142       if (theMEAvoid.Contains(aE)) {
1143         continue;
1144       }
1145       //
1146       const TopTools_ListOfShape& aLF=theEFMap.FindFromKey(aE);
1147       aIt.Initialize(aLF);
1148       for (; aIt.More(); aIt.Next()) {
1149         const TopoDS_Shape& aF=aIt.Value();
1150           Path (aE, aF, theEFMap, theMEAvoid, theCBMap);
1151       }
1152     }
1153   }
1154 }
1155 */