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