1 // File: NMTAlgo_Tools.cxx
2 // Created: Fri Jan 30 16:30:45 2004
3 // Author: Peter KURNEV
7 #include <NMTAlgo_Tools.ixx>
11 #include <TopAbs_Orientation.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>
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>
30 #include <BRep_Builder.hxx>
31 #include <BRep_Tool.hxx>
32 #include <BRepClass3d_SolidClassifier.hxx>
35 #include <TopExp_Explorer.hxx>
37 #include <BOPTools_Tools3D.hxx>
39 #include <NMTAlgo_Loop3d.hxx>
40 #include <TopoDS_Iterator.hxx>
43 //=======================================================================
46 //=======================================================================
47 Standard_Integer NMTAlgo_Tools::Sense (const TopoDS_Face& aF1,
48 const TopoDS_Face& aF2)
50 Standard_Integer iSense=0;
53 TopExp_Explorer anExp;
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)) {
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)) {
82 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
83 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, aF2, aDNF2);
85 iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
90 //=======================================================================
91 // function: OrientFacesOnShell
93 //=======================================================================
94 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Face& aF1,
97 Standard_Integer aNbFSh, iSenseFlag;
99 TopExp_Explorer anExp;
100 TopoDS_Edge aE1, aESh;
101 TopTools_IndexedDataMapOfShapeListOfShape aMEFSh;
103 anExp.Init(aF1, TopAbs_EDGE);
104 for (; anExp.More(); anExp.Next()) {
105 aE1=TopoDS::Edge(anExp.Current());
106 if (!BRep_Tool::Degenerated(aE1)) {
111 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
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();
118 const TopoDS_Face& aFSh=TopoDS::Face(aLFSh.First());
120 BOPTools_Tools3D::OrientEdgeOnFace(aE1, aFSh, aESh);
121 BOPTools_Tools3D::GetNormalToFaceOnEdge(aESh, aFSh, aDNF2);
123 iSenseFlag=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
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;
137 //=======================================================================
138 // function: OrientFacesOnShell
140 //=======================================================================
141 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Shell& aShell,
142 TopoDS_Shell& aShellNew)
144 Standard_Boolean bIsProcessed1, bIsProcessed2;
145 Standard_Integer i, aNbE, aNbF, j;
146 TopAbs_Orientation anOrE1, anOrE2;
148 TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
149 TopTools_IndexedMapOfShape aProcessedFaces;
152 aBB.MakeShell(aShellNew);
154 TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
156 aNbE=aEFMap.Extent();
158 // One seam edge in aEFMap contains 2 equivalent faces.
159 for (i=1; i<=aNbE; i++) {
160 TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
162 if (aLF.Extent()>1) {
163 TopTools_ListOfShape aLFTmp;
164 TopTools_IndexedMapOfShape aFM;
166 TopTools_ListIteratorOfListOfShape anIt(aLF);
167 for (; anIt.More(); anIt.Next()) {
168 const TopoDS_Shape& aF=anIt.Value();
169 if (!aFM.Contains(aF)) {
180 for (i=1; i<=aNbE; i++) {
181 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
183 if (BRep_Tool::Degenerated(aE)) {
187 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
191 TopoDS_Face& aF1=TopoDS::Face(aLF.First());
192 TopoDS_Face& aF2=TopoDS::Face(aLF.Last() );
195 bIsProcessed1=aProcessedFaces.Contains(aF1);
196 bIsProcessed2=aProcessedFaces.Contains(aF2);
198 if (bIsProcessed1 && bIsProcessed2) {
202 if (!bIsProcessed1 && !bIsProcessed2) {
203 aProcessedFaces.Add(aF1);
204 aBB.Add(aShellNew, aF1);
206 bIsProcessed1=!bIsProcessed1;
210 TopoDS_Face aF1x, aF2x;
214 j=aProcessedFaces.FindIndex(aF1);
215 aF1x=TopoDS::Face(aProcessedFaces.FindKey(j));
220 j=aProcessedFaces.FindIndex(aF2);
221 aF2x=TopoDS::Face(aProcessedFaces.FindKey(j));
225 anOrE1=NMTAlgo_Tools::Orientation(aE, aF1x);
226 anOrE2=NMTAlgo_Tools::Orientation(aE, aF2x);
228 if (bIsProcessed1 && !bIsProcessed2) {
230 if (anOrE1==anOrE2) {
231 if (!BRep_Tool::IsClosed(aE, aF1) &&
232 !BRep_Tool::IsClosed(aE, aF2)) {
236 aProcessedFaces.Add(aF2);
237 aBB.Add(aShellNew, aF2);
240 else if (!bIsProcessed1 && bIsProcessed2) {
241 if (anOrE1==anOrE2) {
242 if (!BRep_Tool::IsClosed(aE, aF1) &&
243 !BRep_Tool::IsClosed(aE, aF2)) {
247 aProcessedFaces.Add(aF1);
248 aBB.Add(aShellNew, aF1);
254 for (i=1; i<=aNbE; i++) {
255 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
257 if (BRep_Tool::Degenerated(aE)) {
261 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
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);
275 //=======================================================================
276 //function : Orientation
278 //=======================================================================
279 TopAbs_Orientation NMTAlgo_Tools::Orientation(const TopoDS_Edge& anE,
280 const TopoDS_Face& aF)
282 TopAbs_Orientation anOr=TopAbs_INTERNAL;
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();
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)
303 BRepClass3d_SolidClassifier aClassifier( theS2 );
305 TopExp_Explorer expl(theS1, TopAbs_VERTEX);
308 aClassifier.PerformInfinitePoint( ::RealSmall());
311 const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
312 aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
313 BRep_Tool::Tolerance( aVertex ));
316 return ( aClassifier.State() == TopAbs_IN );
318 //=======================================================================
319 //function : MakeShells
321 //=======================================================================
322 void NMTAlgo_Tools::MakeShells (const TopoDS_Shape& aFC,
323 TopTools_ListOfShape& aLNS)
325 NMTAlgo_Loop3d aShellMaker;
326 TopTools_MapOfOrientedShape aMTmp;
328 aShellMaker.AddConstFaces(aFC);
329 aLNS=aShellMaker.MakeShells(aMTmp);
331 //=======================================================================
332 //function : MakeSolids
334 //=======================================================================
335 void NMTAlgo_Tools::MakeSolids(const TopoDS_Shape& aFC,
336 TopTools_ListOfShape& theShellList)
338 NMTAlgo_Tools::MakeShells(aFC, theShellList);
339 NMTAlgo_Tools::MakeSolids(theShellList);
341 //=======================================================================
342 //function : MakeSolids
344 //=======================================================================
345 void NMTAlgo_Tools::MakeSolids(TopTools_ListOfShape& theShellList)
347 TopTools_ListOfShape aHoleShells, aNewSolids;
348 TopoDS_Shape anInfinitePointShape;
349 TopTools_DataMapOfShapeShape aInOutMap;
350 TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
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);
361 // make a solid from a shell
363 aBB.MakeSolid( Solid );
364 aBB.Add (Solid, aShell);
365 aNewSolids.Append (Solid);
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();
374 aSolisIt.Initialize(aNewSolids);
375 for ( ; aSolisIt.More(); aSolisIt.Next()) {
376 const TopoDS_Shape & aSolid = aSolisIt.Value();
378 if (! NMTAlgo_Tools::IsInside(aHole, aSolid)){
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 );
390 aInOutMap.Bind (aHole, aSolid);
394 // add aHole to a solid
395 if (aInOutMap.IsBound( aHole )){
396 TopoDS_Shape & aSolid=aInOutMap(aHole);
397 aBB.Add (aSolid, aHole);
400 theShellList.Clear();
401 theShellList.Append( aNewSolids );
403 //=======================================================================
404 //function : BreakWebs
406 //=======================================================================
407 void NMTAlgo_Tools::BreakWebs(const TopoDS_Shape& aCS,
410 Standard_Integer i, aNbF, aNbS;
411 TopTools_IndexedDataMapOfShapeListOfShape aMFS;
412 TopTools_MapOfShape aMF;
414 TopoDS_Compound aFC, aCR;
417 aBB.MakeCompound(aFC);
418 TopExp::MapShapesAndAncestors(aCS, TopAbs_FACE, TopAbs_SOLID, aMFS);
421 for (i=1; i<=aNbF; ++i) {
422 const TopoDS_Shape& aF=aMFS.FindKey(i);
423 const TopTools_ListOfShape& aLS=aMFS(i);
438 TopTools_ListOfShape aLNS;
439 TopTools_ListIteratorOfListOfShape aItS;
441 NMTAlgo_Tools::MakeShells(aFC, aLNS);
442 NMTAlgo_Tools::MakeSolids(aLNS);
444 aBB.MakeCompound(aCR);
445 aItS.Initialize(aLNS);
446 for ( ;aItS.More(); aItS.Next()) {
447 const TopoDS_Shape& aS=aItS.Value();
452 //=======================================================================
453 //function : FindImageSolid
455 //=======================================================================
456 Standard_Boolean NMTAlgo_Tools::FindImageSolid(const TopoDS_Shape& aFC,
457 const TopTools_IndexedMapOfShape& aMSo,
460 Standard_Boolean bFound=Standard_False;
461 Standard_Integer i, j, aNbSo, aNbF, aNbFSo;
463 TopTools_IndexedMapOfShape aMFC, aMFSo;
466 for (; aIt.More(); aIt.Next()) {
467 const TopoDS_Shape& aF=aIt.Value();
473 for (i=1; i<=aNbSo; ++i) {
474 const TopoDS_Shape& aSo=aMSo(i);
476 bFound=Standard_True;
478 TopExp::MapShapes(aSo, TopAbs_FACE, aMFSo);
480 aNbFSo=aMFSo.Extent();
485 for (j=1; j<=aNbFSo; ++j) {
486 const TopoDS_Shape& aFSo=aMFSo(j);
487 if (!aMFC.Contains(aFSo)) {
488 bFound=Standard_False;