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