Salome HOME
Merge with version on tag OCC-V2_1_0d
[modules/geom.git] / src / NMTAlgo / NMTAlgo_Tools.cxx
1 // File:        NMTAlgo_Tools.cxx
2 // Created:     Fri Jan 30 16:30:45 2004
3 // Author:      Peter KURNEV
4 //              <pkv@irinox>
5
6
7 #include <NMTAlgo_Tools.ixx>
8
9 #include <gp_Dir.hxx>
10
11 #include <TopAbs_Orientation.hxx>
12
13 #include <TopoDS.hxx>
14 #include <TopoDS_Shape.hxx>
15 #include <TopoDS_Edge.hxx>
16 #include <TopoDS_Solid.hxx>
17 #include <TopoDS_Face.hxx>
18 #include <TopoDS_Vertex.hxx>
19 #include <TopoDS_Compound.hxx>
20
21 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
22 #include <TopTools_IndexedMapOfShape.hxx>
23 #include <TopTools_ListOfShape.hxx>
24 #include <TopTools_IndexedMapOfShape.hxx>
25 #include <TopTools_ListIteratorOfListOfShape.hxx>
26 #include <TopTools_DataMapOfShapeShape.hxx>
27 #include <TopTools_MapOfShape.hxx>
28 #include <TopTools_MapOfOrientedShape.hxx>
29
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRepClass3d_SolidClassifier.hxx>
33
34 #include <TopExp.hxx>
35 #include <TopExp_Explorer.hxx>
36
37 #include <BOPTools_Tools3D.hxx>
38
39 #include <NMTAlgo_Loop3d.hxx>
40 #include <TopoDS_Iterator.hxx>
41
42
43 //=======================================================================
44 // function: Sense
45 // purpose: 
46 //=======================================================================
47   Standard_Integer NMTAlgo_Tools::Sense (const TopoDS_Face& aF1,
48                                          const TopoDS_Face& aF2)
49 {
50   Standard_Integer iSense=0;
51   gp_Dir aDNF1, aDNF2;
52   TopoDS_Edge aE1, aE2;
53   TopExp_Explorer anExp;
54   //
55   anExp.Init(aF1, TopAbs_EDGE);
56   for (; anExp.More(); anExp.Next()) {
57     aE1=TopoDS::Edge(anExp.Current());
58     if (!BRep_Tool::Degenerated(aE1)) {
59       if (!BRep_Tool::IsClosed(aE1, aF1)) {
60         break;
61       }
62     }
63   }
64   //
65   anExp.Init(aF2, TopAbs_EDGE);
66   for (; anExp.More(); anExp.Next()) {
67     aE2=TopoDS::Edge(anExp.Current());
68     if (!BRep_Tool::Degenerated(aE2)) {
69       if (!BRep_Tool::IsClosed(aE2, aF2)) {
70         if (aE2.IsSame(aE1)) {
71           iSense=1;
72           break;
73         }
74       }
75     }
76   }
77   //
78   if (!iSense) {
79     return iSense;
80   }
81   //
82   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
83   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, aF2, aDNF2);
84   //
85   iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
86   //
87   return iSense;
88 }
89
90 //=======================================================================
91 // function: OrientFacesOnShell
92 // purpose: 
93 //=======================================================================
94   void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Face& aF1, 
95                                           TopoDS_Shell& aSh)
96 {
97   Standard_Integer aNbFSh, iSenseFlag;
98   gp_Dir aDNF1, aDNF2;
99   TopExp_Explorer anExp;
100   TopoDS_Edge aE1, aESh;
101   TopTools_IndexedDataMapOfShapeListOfShape aMEFSh;
102   //
103   anExp.Init(aF1, TopAbs_EDGE);
104   for (; anExp.More(); anExp.Next()) {
105     aE1=TopoDS::Edge(anExp.Current());
106     if (!BRep_Tool::Degenerated(aE1)) {
107       break;
108     }
109   }
110   //
111   BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
112   //
113   TopExp::MapShapesAndAncestors(aSh, TopAbs_EDGE, TopAbs_FACE, aMEFSh);
114   if (aMEFSh.Contains(aE1)) {
115     const TopTools_ListOfShape& aLFSh=aMEFSh.FindFromKey(aE1);
116     aNbFSh=aLFSh.Extent();
117     if (aNbFSh==1) {
118       const TopoDS_Face& aFSh=TopoDS::Face(aLFSh.First());
119       //
120       BOPTools_Tools3D::OrientEdgeOnFace(aE1, aFSh, aESh); 
121       BOPTools_Tools3D::GetNormalToFaceOnEdge(aESh, aFSh, aDNF2);
122       //
123       iSenseFlag=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
124       if (iSenseFlag==1) {
125         return;
126       }
127       //
128       anExp.Init(aSh, TopAbs_FACE);
129       for (; anExp.More(); anExp.Next()) {
130         const TopoDS_Shape& aFx=anExp.Current();
131         TopoDS_Shape *pFx=(TopoDS_Shape *)&aFx;
132         pFx->Reverse();
133       }
134     }
135   }
136 }
137 //=======================================================================
138 // function: OrientFacesOnShell
139 // purpose: 
140 //=======================================================================
141   void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Shell& aShell, 
142                                           TopoDS_Shell& aShellNew)
143 {
144   Standard_Boolean bIsProcessed1, bIsProcessed2;
145   Standard_Integer i, aNbE, aNbF, j;
146   TopAbs_Orientation anOrE1, anOrE2;
147
148   TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
149   TopTools_IndexedMapOfShape aProcessedFaces;
150   BRep_Builder aBB;
151
152   aBB.MakeShell(aShellNew);
153   
154   TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
155   
156   aNbE=aEFMap.Extent();
157   // 
158   // One seam edge  in aEFMap contains  2 equivalent faces.
159   for (i=1; i<=aNbE; i++) {
160     TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
161
162     if (aLF.Extent()>1) {
163       TopTools_ListOfShape aLFTmp;
164       TopTools_IndexedMapOfShape aFM;
165
166       TopTools_ListIteratorOfListOfShape anIt(aLF);
167       for (; anIt.More(); anIt.Next()) {
168         const TopoDS_Shape& aF=anIt.Value();
169         if (!aFM.Contains(aF)) {
170           aFM.Add(aF);
171           aLFTmp.Append(aF);
172         }
173       }
174       aLF.Clear();
175       aLF=aLFTmp;
176     }
177   }
178   //
179   // Do
180   for (i=1; i<=aNbE; i++) {
181     const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
182
183     if (BRep_Tool::Degenerated(aE)) {
184       continue;
185     }
186
187     const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
188     aNbF=aLF.Extent();
189     
190     if (aNbF==2) {
191       TopoDS_Face& aF1=TopoDS::Face(aLF.First());
192       TopoDS_Face& aF2=TopoDS::Face(aLF.Last() );
193       
194       
195       bIsProcessed1=aProcessedFaces.Contains(aF1);
196       bIsProcessed2=aProcessedFaces.Contains(aF2);
197      
198       if (bIsProcessed1 && bIsProcessed2) {
199         continue;
200       }
201
202       if (!bIsProcessed1 && !bIsProcessed2) {
203         aProcessedFaces.Add(aF1);
204         aBB.Add(aShellNew, aF1);
205
206         bIsProcessed1=!bIsProcessed1;
207       }
208
209       //
210       TopoDS_Face aF1x, aF2x;
211       
212       aF1x=aF1;
213       if (bIsProcessed1) {
214         j=aProcessedFaces.FindIndex(aF1);
215         aF1x=TopoDS::Face(aProcessedFaces.FindKey(j));
216       }
217       
218       aF2x=aF2;
219       if (bIsProcessed2) {
220         j=aProcessedFaces.FindIndex(aF2);
221         aF2x=TopoDS::Face(aProcessedFaces.FindKey(j));
222       }
223       //
224
225       anOrE1=NMTAlgo_Tools::Orientation(aE, aF1x); 
226       anOrE2=NMTAlgo_Tools::Orientation(aE, aF2x);
227
228       if (bIsProcessed1 && !bIsProcessed2) {
229         
230         if (anOrE1==anOrE2) {
231           if (!BRep_Tool::IsClosed(aE, aF1) &&
232               !BRep_Tool::IsClosed(aE, aF2)) {
233             aF2.Reverse();
234           }
235         }
236         aProcessedFaces.Add(aF2);
237         aBB.Add(aShellNew, aF2);
238       }
239       
240       else if (!bIsProcessed1 && bIsProcessed2) {
241         if (anOrE1==anOrE2) {
242           if (!BRep_Tool::IsClosed(aE, aF1) &&
243               !BRep_Tool::IsClosed(aE, aF2)) {
244             aF1.Reverse();
245           }
246         }
247         aProcessedFaces.Add(aF1);
248         aBB.Add(aShellNew, aF1);
249       }
250     }
251   }
252   //
253   //
254   for (i=1; i<=aNbE; i++) {
255     const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
256
257     if (BRep_Tool::Degenerated(aE)) {
258       continue;
259     }
260
261     const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
262     aNbF=aLF.Extent();
263     if (aNbF!=2) {
264       TopTools_ListIteratorOfListOfShape anIt(aLF);
265       for(; anIt.More(); anIt.Next()) {
266         const TopoDS_Face& aF=TopoDS::Face(anIt.Value());
267         if (!aProcessedFaces.Contains(aF)) {
268           aProcessedFaces.Add(aF);
269           aBB.Add(aShellNew, aF);
270         }
271       }
272     }
273   }
274 }
275 //=======================================================================
276 //function : Orientation
277 //purpose  :
278 //=======================================================================
279   TopAbs_Orientation NMTAlgo_Tools::Orientation(const TopoDS_Edge& anE,
280                                                 const TopoDS_Face& aF)
281 {
282   TopAbs_Orientation anOr=TopAbs_INTERNAL;
283
284   TopExp_Explorer anExp;
285   anExp.Init(aF, TopAbs_EDGE);
286   for (; anExp.More(); anExp.Next()) {
287     const TopoDS_Edge& anEF1=TopoDS::Edge(anExp.Current());
288     if (anEF1.IsSame(anE)) {
289       anOr=anEF1.Orientation();
290       break;
291     }
292   }
293   return anOr;
294 }
295 //=======================================================================
296 //function : IsInside
297 //purpose  : Return True if the first vertex of S1 inside S2.
298 //           If S1.IsNull(), check infinite point against S2.
299 //=======================================================================
300   Standard_Boolean NMTAlgo_Tools::IsInside (const TopoDS_Shape& theS1,
301                                             const TopoDS_Shape& theS2)
302 {
303   BRepClass3d_SolidClassifier aClassifier( theS2 );
304   //
305   TopExp_Explorer expl(theS1, TopAbs_VERTEX);
306   //
307   if (!expl.More()){
308     aClassifier.PerformInfinitePoint( ::RealSmall());
309   }
310   else  {
311     const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
312     aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
313                          BRep_Tool::Tolerance( aVertex ));
314   }
315   //
316   return ( aClassifier.State() == TopAbs_IN );
317 }
318 //=======================================================================
319 //function : MakeShells
320 //purpose  : 
321 //=======================================================================
322   void NMTAlgo_Tools::MakeShells (const TopoDS_Shape& aFC,
323                                   TopTools_ListOfShape& aLNS)
324 {
325   NMTAlgo_Loop3d aShellMaker;
326   TopTools_MapOfOrientedShape aMTmp;
327   //
328   aShellMaker.AddConstFaces(aFC);
329   aLNS=aShellMaker.MakeShells(aMTmp);
330 }
331 //=======================================================================
332 //function : MakeSolids
333 //purpose  : 
334 //=======================================================================
335   void NMTAlgo_Tools::MakeSolids(const TopoDS_Shape& aFC,
336                                  TopTools_ListOfShape& theShellList)
337 {
338   NMTAlgo_Tools::MakeShells(aFC, theShellList);
339   NMTAlgo_Tools::MakeSolids(theShellList);
340 }
341 //=======================================================================
342 //function : MakeSolids
343 //purpose  : 
344 //=======================================================================
345   void NMTAlgo_Tools::MakeSolids(TopTools_ListOfShape& theShellList)
346 {
347   TopTools_ListOfShape aHoleShells, aNewSolids; 
348   TopoDS_Shape anInfinitePointShape;
349   TopTools_DataMapOfShapeShape aInOutMap;
350   TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
351   BRep_Builder aBB;
352   //
353   aShellIt.Initialize(theShellList);
354   for ( ; aShellIt.More(); aShellIt.Next()) {
355     const TopoDS_Shape & aShell = aShellIt.Value();
356     // check if a shell is a hole of theSolid
357     if (NMTAlgo_Tools::IsInside(anInfinitePointShape, aShell)){
358       aHoleShells.Append(aShell);
359     }
360     else {
361       // make a solid from a shell
362       TopoDS_Solid Solid;
363       aBB.MakeSolid( Solid );
364       aBB.Add (Solid, aShell);
365       aNewSolids.Append (Solid);
366     }
367   }
368   //
369   // find outer a shell most close to each hole shell
370   aShellIt.Initialize(aHoleShells);
371   for (; aShellIt.More(); aShellIt.Next()){
372     const TopoDS_Shape & aHole = aShellIt.Value();
373     //
374     aSolisIt.Initialize(aNewSolids);
375     for ( ; aSolisIt.More(); aSolisIt.Next())    {
376       const TopoDS_Shape & aSolid = aSolisIt.Value();
377       //
378       if (! NMTAlgo_Tools::IsInside(aHole, aSolid)){
379         continue;
380       }
381       //
382       if ( aInOutMap.IsBound (aHole)){
383         const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
384         if ( IsInside( aSolid, aSolid2 )) {
385           aInOutMap.UnBind( aHole );
386           aInOutMap.Bind ( aHole, aSolid );
387         }
388       }
389       else{
390         aInOutMap.Bind (aHole, aSolid);
391       }
392     }
393     //
394     // add aHole to a solid
395     if (aInOutMap.IsBound( aHole )){
396       TopoDS_Shape & aSolid=aInOutMap(aHole);
397       aBB.Add (aSolid, aHole);
398     }
399   }
400   theShellList.Clear();
401   theShellList.Append( aNewSolids );
402 }
403 //=======================================================================
404 //function : BreakWebs
405 //purpose  :
406 //=======================================================================
407   void NMTAlgo_Tools::BreakWebs(const TopoDS_Shape& aCS,
408                                 TopoDS_Shape& aCSR)
409 {
410   Standard_Integer i, aNbF, aNbS;
411   TopTools_IndexedDataMapOfShapeListOfShape aMFS;
412   TopTools_MapOfShape aMF;
413   
414   TopoDS_Compound aFC, aCR;
415   BRep_Builder aBB;
416   //
417   aBB.MakeCompound(aFC);
418   TopExp::MapShapesAndAncestors(aCS, TopAbs_FACE, TopAbs_SOLID, aMFS);
419   //
420   aNbF=aMFS.Extent();
421   for (i=1; i<=aNbF; ++i) {
422     const TopoDS_Shape& aF=aMFS.FindKey(i);
423     const TopTools_ListOfShape& aLS=aMFS(i);
424     aNbS=aLS.Extent();
425     if (aNbS==2) {
426       aMF.Add(aF);
427     }
428     else {
429       aBB.Add(aFC, aF);
430     }
431   }
432   //
433   if (!aMF.Extent()) {
434     aCSR=aCS;
435     return;
436   }
437   //
438   TopTools_ListOfShape aLNS;
439   TopTools_ListIteratorOfListOfShape aItS;
440   //
441   NMTAlgo_Tools::MakeShells(aFC, aLNS);
442   NMTAlgo_Tools::MakeSolids(aLNS);
443   //
444   aBB.MakeCompound(aCR);
445   aItS.Initialize(aLNS);
446   for ( ;aItS.More(); aItS.Next()) {
447     const TopoDS_Shape& aS=aItS.Value();
448     aBB.Add(aCR, aS);
449   }
450   aCSR=aCR;
451 }
452 //=======================================================================
453 //function : FindImageSolid
454 //purpose  :
455 //=======================================================================
456   Standard_Boolean NMTAlgo_Tools::FindImageSolid(const TopoDS_Shape& aFC,
457                                                  const TopTools_IndexedMapOfShape& aMSo,
458                                                  TopoDS_Shape& aSox)
459 {
460   Standard_Boolean bFound=Standard_False;
461   Standard_Integer i, j, aNbSo, aNbF, aNbFSo;
462   TopoDS_Iterator aIt;
463   TopTools_IndexedMapOfShape aMFC, aMFSo;
464   //
465   aIt.Initialize(aFC);
466   for (; aIt.More(); aIt.Next()) {
467     const TopoDS_Shape& aF=aIt.Value();
468     aMFC.Add(aF);
469   }
470   //
471   aNbF=aMFC.Extent();
472   aNbSo=aMSo.Extent();
473   for (i=1; i<=aNbSo; ++i) {
474     const TopoDS_Shape& aSo=aMSo(i);
475     //
476     bFound=Standard_True;
477     aMFSo.Clear();
478     TopExp::MapShapes(aSo, TopAbs_FACE, aMFSo);
479     //
480     aNbFSo=aMFSo.Extent();
481     if (aNbFSo!=aNbF) {
482       continue;
483     }
484     //
485     for (j=1; j<=aNbFSo; ++j) {
486       const TopoDS_Shape& aFSo=aMFSo(j);
487       if (!aMFC.Contains(aFSo)) {
488         bFound=Standard_False;
489         break;
490       }
491     }
492     if (bFound) {
493       aSox=aSo;
494       return bFound;
495     }
496   }
497   return bFound;
498 }