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: GEOMAlgo_BuilderSolid.cxx
22 // Author: Peter KURNEV
25 #include <GEOMAlgo_BuilderSolid.ixx>
27 #include <gp_Pnt2d.hxx>
33 #include <Geom_Curve.hxx>
34 #include <Geom_Surface.hxx>
35 #include <Geom2d_Curve.hxx>
39 #include <TopoDS_Iterator.hxx>
40 #include <TopoDS_Face.hxx>
42 #include <TopoDS_Shape.hxx>
43 #include <TopoDS_Shell.hxx>
44 #include <TopoDS_Edge.hxx>
45 #include <TopoDS_Solid.hxx>
46 #include <TopoDS_Vertex.hxx>
47 #include <TopoDS_Compound.hxx>
49 #include <BRep_Builder.hxx>
50 #include <BRep_Tool.hxx>
51 #include <BRepTools.hxx>
52 #include <BRepClass3d_SolidClassifier.hxx>
55 #include <TopExp_Explorer.hxx>
57 #include <TopTools_MapOfShape.hxx>
58 #include <TopTools_MapIteratorOfMapOfShape.hxx>
59 #include <TopTools_MapOfOrientedShape.hxx>
60 #include <TopTools_MapIteratorOfMapOfOrientedShape.hxx>
61 #include <TopTools_ListOfShape.hxx>
62 #include <TopTools_ListIteratorOfListOfShape.hxx>
63 #include <TopTools_DataMapOfShapeShape.hxx>
64 #include <TopTools_IndexedMapOfShape.hxx>
65 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
66 #include <TopTools_DataMapOfShapeListOfShape.hxx>
67 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
69 #include <IntTools_Context.hxx>
71 #include <BOPTools_Tools2D.hxx>
72 #include <BOPTools_Tools3D.hxx>
74 #include <NMTTools_ListOfCoupleOfShape.hxx>
75 #include <NMTTools_CoupleOfShape.hxx>
76 #include <NMTTools_ListIteratorOfListOfCoupleOfShape.hxx>
78 #include <GEOMAlgo_Tools3D.hxx>
79 #include <GEOMAlgo_BuilderTools.hxx>
83 Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
84 const TopTools_IndexedMapOfShape& );
86 Standard_Boolean IsHole(const TopoDS_Shape& ,
89 Standard_Boolean IsInside(const TopoDS_Shape& ,
93 void MakeInternalShells(const TopTools_MapOfShape& ,
94 TopTools_ListOfShape& );
98 //=======================================================================
101 //=======================================================================
102 GEOMAlgo_BuilderSolid::GEOMAlgo_BuilderSolid()
104 GEOMAlgo_BuilderArea()
107 //=======================================================================
110 //=======================================================================
111 GEOMAlgo_BuilderSolid::~GEOMAlgo_BuilderSolid()
114 //=======================================================================
117 //=======================================================================
118 void GEOMAlgo_BuilderSolid::Perform()
125 TopTools_ListIteratorOfListOfShape aIt;
127 aBB.MakeCompound(aC);
128 aIt.Initialize(myShapes);
129 for(; aIt.More(); aIt.Next()) {
130 const TopoDS_Shape& aF=aIt.Value();
135 if (myContext==NULL) {
136 myErrorStatus=11;// Null Context
140 PerformShapesToAvoid();
153 PerformInternalShapes();
158 //=======================================================================
159 //function :PerformShapesToAvoid
161 //=======================================================================
162 void GEOMAlgo_BuilderSolid::PerformShapesToAvoid()
164 Standard_Boolean bFound;
165 Standard_Integer i, iCnt, aNbE, aNbF;
166 TopAbs_Orientation aOrE;
167 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
168 TopTools_ListIteratorOfListOfShape aIt;
170 myShapesToAvoid.Clear();
175 bFound=Standard_False;
179 aIt.Initialize (myShapes);
180 for (; aIt.More(); aIt.Next()) {
181 const TopoDS_Shape& aF=aIt.Value();
182 if (!myShapesToAvoid.Contains(aF)) {
183 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
192 for (i=1; i<=aNbE; ++i) {
193 const TopoDS_Edge& aE=TopoDS::Edge(aMEF.FindKey(i));
194 if (BRep_Tool::Degenerated(aE)) {
198 TopTools_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
205 aOrE=aE.Orientation();
207 const TopoDS_Face& aF1=TopoDS::Face(aLF.First());
209 if (aOrE==TopAbs_INTERNAL) {
212 bFound=Standard_True;
213 myShapesToAvoid.Add(aF1);
216 const TopoDS_Face& aF2=TopoDS::Face(aLF.Last());
217 if (aF2.IsSame(aF1)) {
218 if (BRep_Tool::IsClosed(aE, aF1)) {
222 if (aOrE==TopAbs_INTERNAL) {
226 bFound=Standard_True;
227 myShapesToAvoid.Add(aF1);
228 myShapesToAvoid.Add(aF2);
231 }// for (i=1; i<=aNbE; ++i) {
239 //=======================================================================
240 //function : PerformLoops
242 //=======================================================================
243 void GEOMAlgo_BuilderSolid::PerformLoops()
249 Standard_Integer aNbLF, aNbOff, aNbFP;
250 TopAbs_Orientation anOr;
253 NMTTools_CoupleOfShape aCSOff;
254 TopTools_MapOfOrientedShape AddedFacesMap;
255 TopTools_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
256 TopTools_ListIteratorOfListOfShape aItF;
258 //=================================================
262 aItF.Initialize (myShapes);
263 for (; aItF.More(); aItF.Next()) {
264 const TopoDS_Shape& aFF = aItF.Value();
265 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
268 aItF.Initialize (myShapes);
269 for (; aItF.More(); aItF.Next()) {
270 const TopoDS_Shape& aFF = aItF.Value();
271 if (myShapesToAvoid.Contains(aFF)) {
274 if (!AddedFacesMap.Add(aFF)) {
280 aBB.MakeShell(aShell);
281 aBB.Add(aShell, aFF);
284 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
286 // loop on faces added to Shell; add their neighbor faces to Shell and so on
287 TopoDS_Iterator aItAddedF (aShell);
288 for (; aItAddedF.More(); aItAddedF.Next()) {
289 const TopoDS_Face& aF = TopoDS::Face(aItAddedF.Value());
291 // loop on edges of aF; find a good neighbor face of aF by aE
292 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
293 for (; aEdgeExp.More(); aEdgeExp.Next()) {
294 const TopoDS_Edge& aE = TopoDS::Edge(aEdgeExp.Current());
297 if (aMEFP.Contains(aE)) {
298 const TopTools_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
305 anOr=aE.Orientation();
306 if (anOr==TopAbs_INTERNAL) {
310 if (BRep_Tool::Degenerated(aE)) {
314 // candidate faces list
315 const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
321 // try to select one of neighbors
322 // check if a face already added to Shell shares E
323 Standard_Boolean bFound;
324 TopTools_ListIteratorOfListOfShape aItLF;
325 NMTTools_ListOfCoupleOfShape aLCSOff;
327 aItLF.Initialize(aLF);
328 for (; aItLF.More(); aItLF.Next()) {
329 const TopoDS_Face& aFL=TopoDS::Face(aItLF.Value());
330 if (myShapesToAvoid.Contains(aFL)) {
333 if (aF.IsSame(aFL)) {
336 if (AddedFacesMap.Contains(aFL)){
340 bFound=GEOMAlgo_Tools3D::GetEdgeOff(aE, aFL, aEL);
345 aCSOff.SetShape1(aEL);
346 aCSOff.SetShape2(aFL);
347 aLCSOff.Append(aCSOff);
348 }//for (; aItLF.More(); aItLF.Next()) {
350 aNbOff=aLCSOff.Extent();
357 aSelF=TopoDS::Face(aLCSOff.First().Shape2());
360 GEOMAlgo_Tools3D::GetFaceOff(aE, aF, aLCSOff, aSelF);
363 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
364 aBB.Add(aShell, aSelF);
365 TopExp::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP);
367 } // for (; aEdgeExp.More(); aEdgeExp.Next()) {
368 } //for (; aItAddedF.More(); aItAddedF.Next()) {
369 myLoops.Append(aShell);
370 } // for (; aItF.More(); aItF.Next()) {
371 //=================================================
375 myLoopsInternal.Clear();
377 Standard_Integer aNbFA;
378 TopTools_MapIteratorOfMapOfOrientedShape aItM;
381 AddedFacesMap.Clear();
383 aNbFA=myShapesToAvoid.Extent();
385 aItM.Initialize(myShapesToAvoid);
386 for (; aItM.More(); aItM.Next()) {
387 const TopoDS_Shape& aFF=aItM.Key();
388 TopExp::MapShapesAndAncestors(aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
391 aItM.Initialize(myShapesToAvoid);
392 for (; aItM.More(); aItM.Next()) {
393 const TopoDS_Shape& aFF=aItM.Key();
394 if (!AddedFacesMap.Add(aFF)) {
400 aBB.MakeShell(aShell);
401 aBB.Add(aShell, aFF);
403 TopoDS_Iterator aItAddedF (aShell);
404 for (; aItAddedF.More(); aItAddedF.Next()) {
405 const TopoDS_Face& aF = TopoDS::Face(aItAddedF.Value());
407 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
408 for (; aEdgeExp.More(); aEdgeExp.Next()) {
409 const TopoDS_Edge& aE = TopoDS::Edge(aEdgeExp.Current());
410 const TopTools_ListOfShape& aLF=aEFMap.FindFromKey(aE);
411 aItF.Initialize(aLF);
412 for (; aItF.More(); aItF.Next()) {
413 const TopoDS_Face& aFL=TopoDS::Face(aItF.Value());
414 if (AddedFacesMap.Add(aFL)){
415 aBB.Add(aShell, aFL);
420 myLoopsInternal.Append(aShell);
423 //=======================================================================
424 //function : PerformAreas
426 //=======================================================================
427 void GEOMAlgo_BuilderSolid::PerformAreas()
431 Standard_Boolean bIsGrowthShell, bIsHole;
432 TopTools_ListOfShape aNewSolids, aHoleShells;
433 TopoDS_Shape anInfinitePointShape;
434 TopTools_DataMapOfShapeShape aInOutMap;
435 TopTools_DataMapOfShapeListOfShape aMSH;
436 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItMSH;
437 TopTools_ListIteratorOfListOfShape aShellIt, aSolidIt;
438 TopTools_IndexedMapOfShape aMHF;
443 // Draft solids [aNewSolids]
444 aShellIt.Initialize(myLoops);
445 for ( ; aShellIt.More(); aShellIt.Next()) {
446 const TopoDS_Shape& aShell = aShellIt.Value();
448 bIsGrowthShell=IsGrowthShell(aShell, aMHF);
449 if (bIsGrowthShell) {
450 // make a growth solid from a shell
452 aBB.MakeSolid(Solid);
453 aBB.Add (Solid, aShell);
455 aNewSolids.Append (Solid);
458 // check if a shell is a hole
460 bIsHole=IsHole(aShell, myContext);
461 //bIsHole=GEOMAlgo_BuilderTools::IsHole(aShell);
464 aHoleShells.Append(aShell);
465 TopExp::MapShapes(aShell, TopAbs_FACE, aMHF);
468 // make a growth solid from a shell
470 aBB.MakeSolid(Solid);
471 aBB.Add (Solid, aShell);
473 aNewSolids.Append (Solid);
478 // 2. Find outer growth shell that is most close to each hole shell
479 aShellIt.Initialize(aHoleShells);
480 for (; aShellIt.More(); aShellIt.Next()) {
481 const TopoDS_Shape& aHole = aShellIt.Value();
483 aSolidIt.Initialize(aNewSolids);
484 for ( ; aSolidIt.More(); aSolidIt.Next()) {
485 const TopoDS_Shape& aSolid = aSolidIt.Value();
487 if (!IsInside(aHole, aSolid, myContext)){
491 if ( aInOutMap.IsBound (aHole)){
492 const TopoDS_Shape& aSolid2 = aInOutMap(aHole);
493 if (IsInside(aSolid, aSolid2, myContext)) {
494 aInOutMap.UnBind(aHole);
495 aInOutMap.Bind (aHole, aSolid);
499 aInOutMap.Bind (aHole, aSolid);
503 // Add aHole to a map Solid/ListOfHoles [aMSH]
504 if (aInOutMap.IsBound(aHole)){
505 const TopoDS_Shape& aSolid=aInOutMap(aHole);
506 if (aMSH.IsBound(aSolid)) {
507 TopTools_ListOfShape& aLH=aMSH.ChangeFind(aSolid);
511 TopTools_ListOfShape aLH;
513 aMSH.Bind(aSolid, aLH);
515 //aBB.Add (aSolid, aHole);
517 }// for (; aShellIt.More(); aShellIt.Next()) {
519 // 3. Add aHoles to Solids
520 aItMSH.Initialize(aMSH);
521 for (; aItMSH.More(); aItMSH.Next()) {
522 TopoDS_Solid aSolid=TopoDS::Solid(aItMSH.Key());
524 const TopTools_ListOfShape& aLH=aItMSH.Value();
525 aShellIt.Initialize(aLH);
526 for (; aShellIt.More(); aShellIt.Next()) {
527 const TopoDS_Shape& aHole = aShellIt.Value();
528 aBB.Add (aSolid, aHole);
532 BRepClass3d_SolidClassifier& aSC=myContext->SolidClassifier(aSolid);
537 // These aNewSolids are draft solids that
538 // do not contain any internal shapes
540 myAreas.Append(aNewSolids);
542 //=======================================================================
543 //function : PerformInternalShapes
545 //=======================================================================
546 void GEOMAlgo_BuilderSolid::PerformInternalShapes()
550 Standard_Integer aNbFI=myLoopsInternal.Extent();
551 if (!aNbFI) {// nothing to do
556 TopTools_ListIteratorOfListOfShape aShellIt, aSolidIt;
558 TopTools_MapOfShape aMF, aMFP;
559 TopTools_MapIteratorOfMapOfShape aItMF;
560 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
561 TopTools_ListOfShape aLSI;
563 // 1. All internal faces
564 aShellIt.Initialize(myLoopsInternal);
565 for (; aShellIt.More(); aShellIt.Next()) {
566 const TopoDS_Shape& aShell=aShellIt.Value();
567 aIt.Initialize(aShell);
568 for (; aIt.More(); aIt.Next()) {
569 const TopoDS_Shape& aF=aIt.Value();
576 aSolidIt.Initialize(myAreas);
577 for ( ; aSolidIt.More(); aSolidIt.Next()) {
578 TopoDS_Solid& aSolid=TopoDS::Solid(aSolidIt.Value());
581 TopExp::MapShapesAndAncestors(aSolid, TopAbs_EDGE, TopAbs_FACE, aMEF);
583 // 2.1 Separate faces to process aMFP
585 aItMF.Initialize(aMF);
586 for (; aItMF.More(); aItMF.Next()) {
587 const TopoDS_Face& aF=TopoDS::Face(aItMF.Key());
588 if (GEOMAlgo_Tools3D::IsInternalFace(aF, aSolid, aMEF, 1.e-14, *myContext)) {
593 // 2.2 Make Internal Shells
595 MakeInternalShells(aMFP, aLSI);
597 // 2.3 Add them to aSolid
598 aShellIt.Initialize(aLSI);
599 for (; aShellIt.More(); aShellIt.Next()) {
600 const TopoDS_Shape& aSI=aShellIt.Value();
601 aBB.Add (aSolid, aSI);
604 // 2.4 Remove faces aMFP from aMF
605 aItMF.Initialize(aMFP);
606 for (; aItMF.More(); aItMF.Next()) {
607 const TopoDS_Shape& aF=aItMF.Key();
615 } //for ( ; aSolidIt.More(); aSolidIt.Next()) {
618 //=======================================================================
619 //function : MakeInternalShells
621 //=======================================================================
622 void MakeInternalShells(const TopTools_MapOfShape& theMF,
623 TopTools_ListOfShape& theShells)
625 TopTools_MapIteratorOfMapOfShape aItM;
626 TopTools_MapOfShape aAddedFacesMap;
627 TopTools_ListIteratorOfListOfShape aItF;
628 TopTools_IndexedDataMapOfShapeListOfShape aMEF;
631 aItM.Initialize(theMF);
632 for (; aItM.More(); aItM.Next()) {
633 const TopoDS_Shape& aF=aItM.Key();
634 TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF);
637 aItM.Initialize(theMF);
638 for (; aItM.More(); aItM.Next()) {
639 TopoDS_Shape aFF=aItM.Key();
640 if (!aAddedFacesMap.Add(aFF)) {
646 aBB.MakeShell(aShell);
647 aFF.Orientation(TopAbs_INTERNAL);
648 aBB.Add(aShell, aFF);
650 TopoDS_Iterator aItAddedF (aShell);
651 for (; aItAddedF.More(); aItAddedF.Next()) {
652 const TopoDS_Shape& aF =aItAddedF.Value();
654 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
655 for (; aEdgeExp.More(); aEdgeExp.Next()) {
656 const TopoDS_Shape& aE =aEdgeExp.Current();
657 const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE);
658 aItF.Initialize(aLF);
659 for (; aItF.More(); aItF.Next()) {
660 TopoDS_Shape aFL=aItF.Value();
661 if (aAddedFacesMap.Add(aFL)){
662 aFL.Orientation(TopAbs_INTERNAL);
663 aBB.Add(aShell, aFL);
668 theShells.Append(aShell);
671 //=======================================================================
674 //=======================================================================
675 Standard_Boolean IsHole(const TopoDS_Shape& theS2,
676 IntTools_PContext& theContext)
678 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
679 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
681 aClsf.PerformInfinitePoint(::RealSmall());
683 return (aClsf.State()==TopAbs_IN);
685 //=======================================================================
686 //function : IsInside
688 //=======================================================================
689 Standard_Boolean IsInside(const TopoDS_Shape& theS1,
690 const TopoDS_Shape& theS2,
691 IntTools_PContext& theContext)
693 TopExp_Explorer aExp;
696 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
698 aExp.Init(theS1, TopAbs_FACE);
700 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
701 aClsf.PerformInfinitePoint(::RealSmall());
702 aState=aClsf.State();
705 TopTools_IndexedMapOfShape aBounds;
706 const TopoDS_Face& aF = TopoDS::Face(aExp.Current());
707 aState=GEOMAlgo_Tools3D::ComputeState(aF, *pS2, 1.e-14, aBounds, *theContext);
709 return (aState==TopAbs_IN);
711 //=======================================================================
712 //function : IsGrowthShell
714 //=======================================================================
715 Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
716 const TopTools_IndexedMapOfShape& theMHF)
718 Standard_Boolean bRet;
722 if (theMHF.Extent()) {
723 aIt.Initialize(theShell);
724 for(; aIt.More(); aIt.Next()) {
725 const TopoDS_Shape& aF=aIt.Value();
726 if (theMHF.Contains(aF)) {
734 //BRepTools::Write(aFF, "ff");