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