1 // Copyright (C) 2005 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
2 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
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.
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.
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
18 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: NMTAlgo_Tools.cxx
21 // Created: Fri Jan 30 16:30:45 2004
22 // Author: Peter KURNEV
26 #include <NMTAlgo_Tools.ixx>
30 #include <TopAbs_Orientation.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>
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>
49 #include <BRep_Builder.hxx>
50 #include <BRep_Tool.hxx>
51 #include <BRepClass3d_SolidClassifier.hxx>
54 #include <TopExp_Explorer.hxx>
56 #include <BOPTools_Tools3D.hxx>
58 #include <NMTAlgo_Loop3d.hxx>
59 #include <TopoDS_Iterator.hxx>
62 //=======================================================================
65 //=======================================================================
66 Standard_Integer NMTAlgo_Tools::Sense (const TopoDS_Face& aF1,
67 const TopoDS_Face& aF2)
69 Standard_Integer iSense=0;
72 TopExp_Explorer anExp;
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)) {
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)) {
101 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
102 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE2, aF2, aDNF2);
104 iSense=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
109 //=======================================================================
110 // function: OrientFacesOnShell
112 //=======================================================================
113 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Face& aF1,
116 Standard_Integer aNbFSh, iSenseFlag;
118 TopExp_Explorer anExp;
119 TopoDS_Edge aE1, aESh;
120 TopTools_IndexedDataMapOfShapeListOfShape aMEFSh;
122 anExp.Init(aF1, TopAbs_EDGE);
123 for (; anExp.More(); anExp.Next()) {
124 aE1=TopoDS::Edge(anExp.Current());
125 if (!BRep_Tool::Degenerated(aE1)) {
130 BOPTools_Tools3D::GetNormalToFaceOnEdge(aE1, aF1, aDNF1);
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();
137 const TopoDS_Face& aFSh=TopoDS::Face(aLFSh.First());
139 BOPTools_Tools3D::OrientEdgeOnFace(aE1, aFSh, aESh);
140 BOPTools_Tools3D::GetNormalToFaceOnEdge(aESh, aFSh, aDNF2);
142 iSenseFlag=BOPTools_Tools3D::SenseFlag(aDNF1, aDNF2);
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;
156 //=======================================================================
157 // function: OrientFacesOnShell
159 //=======================================================================
160 void NMTAlgo_Tools::OrientFacesOnShell (const TopoDS_Shell& aShell,
161 TopoDS_Shell& aShellNew)
163 Standard_Boolean bIsProcessed1, bIsProcessed2;
164 Standard_Integer i, aNbE, aNbF, j;
165 TopAbs_Orientation anOrE1, anOrE2;
167 TopTools_IndexedDataMapOfShapeListOfShape aEFMap;
168 TopTools_IndexedMapOfShape aProcessedFaces;
171 aBB.MakeShell(aShellNew);
173 TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aEFMap);
175 aNbE=aEFMap.Extent();
177 // One seam edge in aEFMap contains 2 equivalent faces.
178 for (i=1; i<=aNbE; i++) {
179 TopTools_ListOfShape& aLF=aEFMap.ChangeFromIndex(i);
181 if (aLF.Extent()>1) {
182 TopTools_ListOfShape aLFTmp;
183 TopTools_IndexedMapOfShape aFM;
185 TopTools_ListIteratorOfListOfShape anIt(aLF);
186 for (; anIt.More(); anIt.Next()) {
187 const TopoDS_Shape& aF=anIt.Value();
188 if (!aFM.Contains(aF)) {
199 for (i=1; i<=aNbE; i++) {
200 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
202 if (BRep_Tool::Degenerated(aE)) {
206 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
210 TopoDS_Face& aF1=TopoDS::Face(aLF.First());
211 TopoDS_Face& aF2=TopoDS::Face(aLF.Last() );
214 bIsProcessed1=aProcessedFaces.Contains(aF1);
215 bIsProcessed2=aProcessedFaces.Contains(aF2);
217 if (bIsProcessed1 && bIsProcessed2) {
221 if (!bIsProcessed1 && !bIsProcessed2) {
222 aProcessedFaces.Add(aF1);
223 aBB.Add(aShellNew, aF1);
225 bIsProcessed1=!bIsProcessed1;
229 TopoDS_Face aF1x, aF2x;
233 j=aProcessedFaces.FindIndex(aF1);
234 aF1x=TopoDS::Face(aProcessedFaces.FindKey(j));
239 j=aProcessedFaces.FindIndex(aF2);
240 aF2x=TopoDS::Face(aProcessedFaces.FindKey(j));
244 anOrE1=NMTAlgo_Tools::Orientation(aE, aF1x);
245 anOrE2=NMTAlgo_Tools::Orientation(aE, aF2x);
247 if (bIsProcessed1 && !bIsProcessed2) {
249 if (anOrE1==anOrE2) {
250 if (!BRep_Tool::IsClosed(aE, aF1) &&
251 !BRep_Tool::IsClosed(aE, aF2)) {
255 aProcessedFaces.Add(aF2);
256 aBB.Add(aShellNew, aF2);
259 else if (!bIsProcessed1 && bIsProcessed2) {
260 if (anOrE1==anOrE2) {
261 if (!BRep_Tool::IsClosed(aE, aF1) &&
262 !BRep_Tool::IsClosed(aE, aF2)) {
266 aProcessedFaces.Add(aF1);
267 aBB.Add(aShellNew, aF1);
273 for (i=1; i<=aNbE; i++) {
274 const TopoDS_Edge& aE=TopoDS::Edge(aEFMap.FindKey(i));
276 if (BRep_Tool::Degenerated(aE)) {
280 const TopTools_ListOfShape& aLF=aEFMap.FindFromIndex(i);
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);
294 //=======================================================================
295 //function : Orientation
297 //=======================================================================
298 TopAbs_Orientation NMTAlgo_Tools::Orientation(const TopoDS_Edge& anE,
299 const TopoDS_Face& aF)
301 TopAbs_Orientation anOr=TopAbs_INTERNAL;
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();
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)
322 BRepClass3d_SolidClassifier aClassifier( theS2 );
324 TopExp_Explorer expl(theS1, TopAbs_VERTEX);
327 aClassifier.PerformInfinitePoint( ::RealSmall());
330 const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
331 aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
332 BRep_Tool::Tolerance( aVertex ));
335 return ( aClassifier.State() == TopAbs_IN );
337 //=======================================================================
338 //function : MakeShells
340 //=======================================================================
341 void NMTAlgo_Tools::MakeShells (const TopoDS_Shape& aFC,
342 TopTools_ListOfShape& aLNS)
344 NMTAlgo_Loop3d aShellMaker;
345 TopTools_MapOfOrientedShape aMTmp;
347 aShellMaker.AddConstFaces(aFC);
348 aLNS=aShellMaker.MakeShells(aMTmp);
350 //=======================================================================
351 //function : MakeSolids
353 //=======================================================================
354 void NMTAlgo_Tools::MakeSolids(const TopoDS_Shape& aFC,
355 TopTools_ListOfShape& theShellList)
357 NMTAlgo_Tools::MakeShells(aFC, theShellList);
358 NMTAlgo_Tools::MakeSolids(theShellList);
360 //=======================================================================
361 //function : MakeSolids
363 //=======================================================================
364 void NMTAlgo_Tools::MakeSolids(TopTools_ListOfShape& theShellList)
366 TopTools_ListOfShape aHoleShells, aNewSolids;
367 TopoDS_Shape anInfinitePointShape;
368 TopTools_DataMapOfShapeShape aInOutMap;
369 TopTools_ListIteratorOfListOfShape aShellIt, aSolisIt;
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);
380 // make a solid from a shell
382 aBB.MakeSolid( Solid );
383 aBB.Add (Solid, aShell);
384 aNewSolids.Append (Solid);
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();
393 aSolisIt.Initialize(aNewSolids);
394 for ( ; aSolisIt.More(); aSolisIt.Next()) {
395 const TopoDS_Shape & aSolid = aSolisIt.Value();
397 if (! NMTAlgo_Tools::IsInside(aHole, aSolid)){
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 );
409 aInOutMap.Bind (aHole, aSolid);
413 // add aHole to a solid
414 if (aInOutMap.IsBound( aHole )){
415 TopoDS_Shape & aSolid=aInOutMap(aHole);
416 aBB.Add (aSolid, aHole);
419 theShellList.Clear();
420 theShellList.Append( aNewSolids );
422 //=======================================================================
423 //function : BreakWebs
425 //=======================================================================
426 void NMTAlgo_Tools::BreakWebs(const TopoDS_Shape& aCS,
429 Standard_Integer i, aNbF, aNbS;
430 TopTools_IndexedDataMapOfShapeListOfShape aMFS;
431 TopTools_MapOfShape aMF;
433 TopoDS_Compound aFC, aCR;
436 aBB.MakeCompound(aFC);
437 TopExp::MapShapesAndAncestors(aCS, TopAbs_FACE, TopAbs_SOLID, aMFS);
440 for (i=1; i<=aNbF; ++i) {
441 const TopoDS_Shape& aF=aMFS.FindKey(i);
442 const TopTools_ListOfShape& aLS=aMFS(i);
457 TopTools_ListOfShape aLNS;
458 TopTools_ListIteratorOfListOfShape aItS;
460 NMTAlgo_Tools::MakeShells(aFC, aLNS);
461 NMTAlgo_Tools::MakeSolids(aLNS);
463 aBB.MakeCompound(aCR);
464 aItS.Initialize(aLNS);
465 for ( ;aItS.More(); aItS.Next()) {
466 const TopoDS_Shape& aS=aItS.Value();
471 //=======================================================================
472 //function : FindImageSolid
474 //=======================================================================
475 Standard_Boolean NMTAlgo_Tools::FindImageSolid(const TopoDS_Shape& aFC,
476 const TopTools_IndexedMapOfShape& aMSo,
479 Standard_Boolean bFound=Standard_False;
480 Standard_Integer i, j, aNbSo, aNbF, aNbFSo;
482 TopTools_IndexedMapOfShape aMFC, aMFSo;
485 for (; aIt.More(); aIt.Next()) {
486 const TopoDS_Shape& aF=aIt.Value();
492 for (i=1; i<=aNbSo; ++i) {
493 const TopoDS_Shape& aSo=aMSo(i);
495 bFound=Standard_True;
497 TopExp::MapShapes(aSo, TopAbs_FACE, aMFSo);
499 aNbFSo=aMFSo.Extent();
501 bFound=Standard_False;
505 for (j=1; j<=aNbFSo; ++j) {
506 const TopoDS_Shape& aFSo=aMFSo(j);
507 if (!aMFC.Contains(aFSo)) {
508 bFound=Standard_False;