1 // Copyright (C) 2007-2008 CEA/DEN, EDF R&D, OPEN CASCADE
3 // Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
4 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
20 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
22 // File: NMTAlgo_Tools.cxx
23 // Created: Fri Jan 30 16:30:45 2004
24 // Author: Peter KURNEV
27 #include <NMTAlgo_Tools.ixx>
31 #include <TopAbs_Orientation.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>
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>
50 #include <BRep_Builder.hxx>
51 #include <BRep_Tool.hxx>
52 #include <BRepClass3d_SolidClassifier.hxx>
55 #include <TopExp_Explorer.hxx>
57 #include <BOPTools_Tools3D.hxx>
59 #include <NMTAlgo_Loop3d.hxx>
60 #include <TopoDS_Iterator.hxx>
63 //=======================================================================
66 //=======================================================================
67 Standard_Integer NMTAlgo_Tools::Sense (const TopoDS_Face& aF1,
68 const TopoDS_Face& aF2)
70 Standard_Integer iSense=0;
73 TopExp_Explorer anExp;
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)) {
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)) {
102 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
103 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, aF2, aDNF2);
105 iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
110 //=======================================================================
111 // function: OrientFacesOnShell
113 //=======================================================================
114 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Face& aF1,
117 Standard_Integer aNbFSh, iSenseFlag;
119 TopExp_Explorer anExp;
120 TopoDS_Edge aE1, aESh;
121 TopTools_IndexedDataMapOfShapeListOfShape aMEFSh;
123 anExp.Init(aF1, TopAbs_EDGE);
124 for (; anExp.More(); anExp.Next()) {
125 aE1=TopoDS::Edge(anExp.Current());
126 if (!BRep_Tool::Degenerated(aE1)) {
131 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
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();
138 const TopoDS_Face& aFSh=TopoDS::Face(aLFSh.First());
140 BOPTools_Tools3D::OrientEdgeOnFace(aE1, aFSh, aESh);
141 BOPTools_Tools3D::GetNormalToFaceOnEdge(aESh, aFSh, aDNF2);
143 iSenseFlag=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
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;
157 //=======================================================================
158 // function: OrientFacesOnShell
160 //=======================================================================
161 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Shell& aShell,
162 TopoDS_Shell& aShellNew)
164 Standard_Boolean bIsProcessed1, bIsProcessed2;
165 Standard_Integer i, aNbE, aNbF, j;
166 TopAbs_Orientation anOrE1, anOrE2;
168 TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
169 TopTools_IndexedMapOfShape aProcessedFaces;
172 aBB.MakeShell(aShellNew);
174 TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
176 aNbE=aEFMap.Extent();
178 // One seam edge in aEFMap contains 2 equivalent faces.
179 for (i=1; i<=aNbE; i++) {
180 TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
182 if (aLF.Extent()>1) {
183 TopTools_ListOfShape aLFTmp;
184 TopTools_IndexedMapOfShape aFM;
186 TopTools_ListIteratorOfListOfShape anIt(aLF);
187 for (; anIt.More(); anIt.Next()) {
188 const TopoDS_Shape& aF=anIt.Value();
189 if (!aFM.Contains(aF)) {
200 for (i=1; i<=aNbE; i++) {
201 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
203 if (BRep_Tool::Degenerated(aE)) {
207 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
211 TopoDS_Face& aF1=TopoDS::Face(aLF.First());
212 TopoDS_Face& aF2=TopoDS::Face(aLF.Last() );
215 bIsProcessed1=aProcessedFaces.Contains(aF1);
216 bIsProcessed2=aProcessedFaces.Contains(aF2);
218 if (bIsProcessed1 && bIsProcessed2) {
222 if (!bIsProcessed1 && !bIsProcessed2) {
223 aProcessedFaces.Add(aF1);
224 aBB.Add(aShellNew, aF1);
226 bIsProcessed1=!bIsProcessed1;
230 TopoDS_Face aF1x, aF2x;
234 j=aProcessedFaces.FindIndex(aF1);
235 aF1x=TopoDS::Face(aProcessedFaces.FindKey(j));
240 j=aProcessedFaces.FindIndex(aF2);
241 aF2x=TopoDS::Face(aProcessedFaces.FindKey(j));
245 anOrE1=NMTAlgo_Tools::Orientation(aE, aF1x);
246 anOrE2=NMTAlgo_Tools::Orientation(aE, aF2x);
248 if (bIsProcessed1 && !bIsProcessed2) {
250 if (anOrE1==anOrE2) {
251 if (!BRep_Tool::IsClosed(aE, aF1) &&
252 !BRep_Tool::IsClosed(aE, aF2)) {
256 aProcessedFaces.Add(aF2);
257 aBB.Add(aShellNew, aF2);
260 else if (!bIsProcessed1 && bIsProcessed2) {
261 if (anOrE1==anOrE2) {
262 if (!BRep_Tool::IsClosed(aE, aF1) &&
263 !BRep_Tool::IsClosed(aE, aF2)) {
267 aProcessedFaces.Add(aF1);
268 aBB.Add(aShellNew, aF1);
274 for (i=1; i<=aNbE; i++) {
275 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
277 if (BRep_Tool::Degenerated(aE)) {
281 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
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);
295 //=======================================================================
296 //function : Orientation
298 //=======================================================================
299 TopAbs_Orientation NMTAlgo_Tools::Orientation(const TopoDS_Edge& anE,
300 const TopoDS_Face& aF)
302 TopAbs_Orientation anOr=TopAbs_INTERNAL;
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();
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)
323 BRepClass3d_SolidClassifier aClassifier( theS2 );
325 TopExp_Explorer expl(theS1, TopAbs_VERTEX);
328 aClassifier.PerformInfinitePoint( ::RealSmall());
331 const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
332 aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
333 BRep_Tool::Tolerance( aVertex ));
336 return ( aClassifier.State() == TopAbs_IN );
338 //=======================================================================
339 //function : MakeShells
341 //=======================================================================
342 void NMTAlgo_Tools::MakeShells (const TopoDS_Shape& aFC,
343 TopTools_ListOfShape& aLNS)
345 NMTAlgo_Loop3d aShellMaker;
346 TopTools_MapOfOrientedShape aMTmp;
348 aShellMaker.AddConstFaces(aFC);
349 aLNS=aShellMaker.MakeShells(aMTmp);
351 //=======================================================================
352 //function : MakeSolids
354 //=======================================================================
355 void NMTAlgo_Tools::MakeSolids(const TopoDS_Shape& aFC,
356 TopTools_ListOfShape& theShellList)
358 NMTAlgo_Tools::MakeShells(aFC, theShellList);
359 NMTAlgo_Tools::MakeSolids(theShellList);
361 //=======================================================================
362 //function : MakeSolids
364 //=======================================================================
365 void NMTAlgo_Tools::MakeSolids(TopTools_ListOfShape& theShellList)
367 TopTools_ListOfShape aHoleShells, aNewSolids;
368 TopoDS_Shape anInfinitePointShape;
369 TopTools_DataMapOfShapeShape aInOutMap;
370 TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
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);
381 // make a solid from a shell
383 aBB.MakeSolid( Solid );
384 aBB.Add (Solid, aShell);
385 aNewSolids.Append (Solid);
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();
394 aSolisIt.Initialize(aNewSolids);
395 for ( ; aSolisIt.More(); aSolisIt.Next()) {
396 const TopoDS_Shape & aSolid = aSolisIt.Value();
398 if (! NMTAlgo_Tools::IsInside(aHole, aSolid)){
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 );
410 aInOutMap.Bind (aHole, aSolid);
414 // add aHole to a solid
415 if (aInOutMap.IsBound( aHole )){
416 TopoDS_Shape & aSolid=aInOutMap(aHole);
417 aBB.Add (aSolid, aHole);
420 theShellList.Clear();
421 theShellList.Append( aNewSolids );
423 //=======================================================================
424 //function : BreakWebs
426 //=======================================================================
427 void NMTAlgo_Tools::BreakWebs(const TopoDS_Shape& aCS,
430 Standard_Integer i, aNbF, aNbS;
431 TopTools_IndexedDataMapOfShapeListOfShape aMFS;
432 TopTools_MapOfShape aMF;
434 TopoDS_Compound aFC, aCR;
437 aBB.MakeCompound(aFC);
438 TopExp::MapShapesAndAncestors(aCS, TopAbs_FACE, TopAbs_SOLID, aMFS);
441 for (i=1; i<=aNbF; ++i) {
442 const TopoDS_Shape& aF=aMFS.FindKey(i);
443 const TopTools_ListOfShape& aLS=aMFS(i);
458 TopTools_ListOfShape aLNS;
459 TopTools_ListIteratorOfListOfShape aItS;
461 NMTAlgo_Tools::MakeShells(aFC, aLNS);
462 NMTAlgo_Tools::MakeSolids(aLNS);
464 aBB.MakeCompound(aCR);
465 aItS.Initialize(aLNS);
466 for ( ;aItS.More(); aItS.Next()) {
467 const TopoDS_Shape& aS=aItS.Value();
472 //=======================================================================
473 //function : FindImageSolid
475 //=======================================================================
476 Standard_Boolean NMTAlgo_Tools::FindImageSolid(const TopoDS_Shape& aFC,
477 const TopTools_IndexedMapOfShape& aMSo,
480 Standard_Boolean bFound=Standard_False;
481 Standard_Integer i, j, aNbSo, aNbF, aNbFSo;
483 TopTools_IndexedMapOfShape aMFC, aMFSo;
486 for (; aIt.More(); aIt.Next()) {
487 const TopoDS_Shape& aF=aIt.Value();
493 for (i=1; i<=aNbSo; ++i) {
494 const TopoDS_Shape& aSo=aMSo(i);
496 bFound=Standard_True;
498 TopExp::MapShapes(aSo, TopAbs_FACE, aMFSo);
500 aNbFSo=aMFSo.Extent();
502 bFound=Standard_False;
506 for (j=1; j<=aNbFSo; ++j) {
507 const TopoDS_Shape& aFSo=aMFSo(j);
508 if (!aMFC.Contains(aFSo)) {
509 bFound=Standard_False;