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