Salome HOME
Preparation of intermediate revision
[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 //modified by NIZNHY-PKV Tue Jul 14 07:24:10 2009f
102 static
103   void GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aE, 
104                                     const TopoDS_Face& aF, 
105                                     Standard_Real aT, 
106                                     gp_Pnt& aPF, 
107                                     gp_Dir& aDNF,
108                                     IntTools_Context& aCtx);
109 //modified by NIZNHY-PKV Tue Jul 14 07:24:15 2009t
110
111 //=======================================================================
112 //function : IsInternalFace
113 //purpose  : 
114 //=======================================================================
115   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
116                                                    const TopoDS_Solid& theSolid,
117                                                    const TopTools_IndexedDataMapOfShapeListOfShape& theMEF,
118                                                    const Standard_Real theTol,
119                                                    IntTools_Context& theContext)
120 {
121   Standard_Boolean bRet;
122   Standard_Integer aNbF;
123   TopoDS_Edge aEL;
124   TopExp_Explorer aExp;
125   TopTools_ListIteratorOfListOfShape aItF;
126   //
127   bRet=Standard_False;
128   //
129   // 1 Try to find an edge from theFace in theMEF
130   aExp.Init(theFace, TopAbs_EDGE);
131   for(; aExp.More(); aExp.Next()) {
132     const TopoDS_Edge& aE=TopoDS::Edge(aExp.Current());
133     if (!theMEF.Contains(aE)) {
134       continue;
135     }
136     // 
137     const TopTools_ListOfShape& aLF=theMEF.FindFromKey(aE);
138     aNbF=aLF.Extent();
139     if (!aNbF) {
140       return bRet; // it can not be so
141     }
142     else if (aNbF==1) {
143       // aE is internal edge on aLF.First()
144       const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
145       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF1, theContext);
146       return bRet;
147     }
148     else if (aNbF==2) {
149       const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
150       const TopoDS_Face& aF2=TopoDS::Face(aLF.Last());
151       //
152       if (aF2.IsSame(aF1) && BRep_Tool::IsClosed(aE, aF1)) {
153         // treat as it was for 1 face
154         bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aF1, aF2, theContext);
155         return bRet;
156       }
157     }
158     if (aNbF%2) {
159       return bRet; // it can not be so
160     }
161     else { // aNbF=2,4,6,8,...
162       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, aE, aLF, theContext);
163       return bRet;
164     }
165   }//for(; aExp.More(); aExp.Next()) {
166   //
167   //========================================
168   // 2. Classify face using classifier
169   //
170   TopAbs_State aState;
171   TopTools_IndexedMapOfShape aBounds;
172   //
173   aState=GEOMAlgo_Tools3D::ComputeState(theFace, theSolid, theTol, aBounds, theContext);
174   bRet=(aState==TopAbs_IN);
175   //
176   return bRet;
177 }
178 //=======================================================================
179 //function : IsInternalFace
180 //purpose  : 
181 //=======================================================================
182   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
183                                                     const TopoDS_Edge& theEdge,
184                                                     const TopTools_ListOfShape& theLF,
185                                                     IntTools_Context& theContext)
186 {
187   Standard_Boolean bRet;
188   Standard_Boolean aNbF;
189   //
190   bRet=Standard_False;
191   //
192   aNbF=theLF.Extent();
193   if (aNbF==2) {
194     const TopoDS_Face& aF1=TopoDS::Face(theLF.First());
195     const TopoDS_Face& aF2=TopoDS::Face(theLF.Last());
196     bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
197     return bRet;
198   }
199   //
200   else {
201     NMTTools_ListOfCoupleOfShape aLCFF;
202     NMTTools_ListIteratorOfListOfCoupleOfShape aIt;
203     //
204     FindFacePairs(theEdge, theLF, aLCFF);
205     //
206     aIt.Initialize(aLCFF);
207     for (; aIt.More(); aIt.Next()) {
208       const NMTTools_CoupleOfShape& aCSFF=aIt.Value();
209       //
210       const TopoDS_Face& aF1=TopoDS::Face(aCSFF.Shape1());
211       const TopoDS_Face& aF2=TopoDS::Face(aCSFF.Shape2());
212       bRet=GEOMAlgo_Tools3D::IsInternalFace(theFace, theEdge, aF1, aF2, theContext);
213       if (bRet) {
214         return bRet;
215       }
216     }
217   }
218   return bRet;
219 }
220 //=======================================================================
221 //function : IsInternalFace
222 //purpose  : 
223 //=======================================================================
224   Standard_Boolean GEOMAlgo_Tools3D::IsInternalFace(const TopoDS_Face& theFace,
225                                                     const TopoDS_Edge& theEdge,
226                                                     const TopoDS_Face& theFace1,
227                                                     const TopoDS_Face& theFace2,
228                                                     IntTools_Context& theContext)
229 {
230   Standard_Boolean bRet;
231   Standard_Real aT1, aT2, aT, aDt2D, aDt2Dx;
232   Standard_Real aA12, aA1x, aTwoPI;
233   gp_Pnt aPx, aPF, aPF1, aPF2;
234   gp_Pnt2d aP2D, aPF2D;
235   gp_Dir aDNF1, aDNF2;
236   TopoDS_Edge aE1, aE2;
237   Handle(Geom_Curve)aC3D;
238   //
239   aC3D =BRep_Tool::Curve(theEdge, aT1, aT2);
240   aT=BOPTools_Tools2D::IntermediatePoint(aT1, aT2);
241   aC3D->D0(aT, aPx);
242   //
243   // 1. PF
244   aDt2D=BOPTools_Tools3D::MinStepIn2d();
245   aDt2Dx=10.*aDt2D;
246   BOPTools_Tools3D::PointNearEdge (theEdge, theFace, aT, aDt2Dx, aPF2D, aPF);
247   // 
248   // 2. E1, E2
249   GEOMAlgo_Tools3D::GetEdgeOnFace(theEdge, theFace1, aE1);
250   if (aE1.Orientation()==TopAbs_INTERNAL) {
251     aE2=aE1;
252     aE1.Orientation(TopAbs_FORWARD);
253     aE2.Orientation(TopAbs_REVERSED);
254   }
255   else if (theFace1==theFace2) {
256     aE2=aE1;
257     aE1.Orientation(TopAbs_FORWARD);
258     aE2.Orientation(TopAbs_REVERSED);
259   }
260   else {
261     GEOMAlgo_Tools3D::GetEdgeOnFace(theEdge, theFace2, aE2);
262   }
263   //
264   // 3
265   bRet=Standard_False;
266   //
267   //modified by NIZNHY-PKV Tue Jul 14 07:22:38 2009f
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   //modified by NIZNHY-PKV Tue Jul 14 07:22:42 2009t
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 //modified by NIZNHY-PKV Tue Jul 14 07:49:55 2009f
1049 //=======================================================================
1050 //function : GetApproxNormalToFaceOnEdge
1051 //purpose  : 
1052 //=======================================================================
1053 void GetApproxNormalToFaceOnEdge (const TopoDS_Edge& aEx, 
1054                                   const TopoDS_Face& aFx, 
1055                                   Standard_Real aT, 
1056                                   gp_Pnt& aPF, 
1057                                   gp_Dir& aDNF,
1058                                   IntTools_Context& aCtx)
1059 {
1060   Standard_Boolean bReverse;
1061   Standard_Real aT1, aT2, dT, aU, aV;
1062   gp_Dir aDTT, aDNFT, aDBT;
1063   gp_Pnt aPFT, aPFx;
1064   Handle(Geom_Curve) aC3D;
1065   TopoDS_Face aF;
1066   TopoDS_Edge aE;
1067   //
1068   bReverse=Standard_False;
1069   aF=aFx;
1070   aE=aEx;
1071   if (aF.Orientation()==TopAbs_REVERSED){
1072     bReverse=!bReverse;
1073     aE.Reverse();
1074     //
1075     aF.Orientation(TopAbs_FORWARD);
1076     //GEOMAlgo_Tools3D::GetEdgeOnFace(aEx, aF, aE);
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   aPFx.SetXYZ(aPFT.XYZ()+dT*aDBT.XYZ());
1094   //
1095   aPF=aPFx;
1096   aDNF=aDNFT;
1097   if (bReverse) {
1098     aDNF.Reverse();
1099   }
1100   //
1101   GeomAPI_ProjectPointOnSurf& aProjector=aCtx.ProjPS(aF);
1102   aProjector.Perform(aPFx);
1103   if(aProjector.IsDone()) {
1104     Handle(Geom_Surface) aS;
1105     //
1106     aProjector.LowerDistanceParameters (aU, aV);
1107     aS=BRep_Tool::Surface(aF);
1108     aS->D0(aU, aV, aPF);
1109     BOPTools_Tools3D::GetNormalToSurface (aS, aU, aV, aDNF);
1110     if (bReverse){
1111       aDNF.Reverse();
1112     }
1113   }
1114 }
1115 //modified by NIZNHY-PKV Tue Jul 14 07:49:58 2009t