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