1 // Created by: Peter KURNEV
2 // Copyright (c) 1999-2014 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
6 // This library is free software; you can redistribute it and/or modify it under
7 // the terms of the GNU Lesser General Public License version 2.1 as published
8 // by the Free Software Foundation, with special exception defined in the file
9 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10 // distribution for complete text of the license and disclaimer of any warranty.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 // File: BOPAlgo_ShellSplitter.cxx
16 // Created: Thu Jan 16 08:33:50 2014
18 #include <BOPAlgo_ShellSplitter.ixx>
20 #include <TopoDS_Shape.hxx>
21 #include <TopoDS_Shell.hxx>
22 #include <TopoDS_Edge.hxx>
24 #include <BRep_Builder.hxx>
25 #include <TopExp_Explorer.hxx>
27 #include <BOPCol_Parallel.hxx>
28 #include <BOPCol_IndexedMapOfShape.hxx>
29 #include <BOPCol_MapOfShape.hxx>
30 #include <BOPCol_MapOfOrientedShape.hxx>
31 #include <BOPCol_NCVector.hxx>
32 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
34 #include <IntTools_Context.hxx>
36 #include <BOPTools.hxx>
37 #include <BOPTools_AlgoTools.hxx>
38 #include <BOPTools_CoupleOfShape.hxx>
42 void MakeShell(const BOPCol_ListOfShape& ,
46 void RefineShell(TopoDS_Shell& theShell);
50 (const TopoDS_Shape& aF,
51 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
52 const Handle(NCollection_BaseAllocator)& theAllocator);
54 //=======================================================================
57 //=======================================================================
67 void SetConnexityBlock (const BOPTools_ConnexityBlock& aCB) {
68 myPCB=(BOPTools_ConnexityBlock*)&aCB;
71 BOPTools_ConnexityBlock& ConnexityBlock () {
76 BOPAlgo_ShellSplitter::SplitBlock(*myPCB);
79 BOPTools_ConnexityBlock *myPCB;
81 //=======================================================================
82 typedef BOPCol_NCVector
83 <BOPAlgo_CBK> BOPAlgo_VectorOfCBK;
85 typedef BOPCol_Functor
87 BOPAlgo_VectorOfCBK> BOPAlgo_CBKFunctor;
91 BOPAlgo_VectorOfCBK> BOPAlgo_CBKCnt;
93 //=======================================================================
96 //=======================================================================
97 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
100 myStartShapes(myAllocator),
101 myShells(myAllocator),
105 //=======================================================================
108 //=======================================================================
109 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
110 (const Handle(NCollection_BaseAllocator)& theAllocator)
112 BOPAlgo_Algo(theAllocator),
113 myStartShapes(theAllocator),
114 myShells(theAllocator),
118 //=======================================================================
121 //=======================================================================
122 BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
125 //=======================================================================
126 //function : AddStartElement
128 //=======================================================================
129 void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
131 myStartShapes.Append(aE);
133 //=======================================================================
134 //function : StartElements
136 //=======================================================================
137 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
139 return myStartShapes;
141 //=======================================================================
144 //=======================================================================
145 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
149 //=======================================================================
152 //=======================================================================
153 void BOPAlgo_ShellSplitter::Perform()
157 MakeConnexityBlocks();
164 //=======================================================================
165 //function : MakeConnexityBlocks
167 //=======================================================================
168 void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
170 Standard_Boolean bRegular;
171 Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
173 TopoDS_Iterator aItF, aItW;
174 BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
175 BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
176 BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
177 BOPCol_MapOfShape aMER(100, myAllocator);
178 BOPCol_MapOfShape aMFP(100, myAllocator);
179 BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
180 BOPCol_MapOfShape aMES(100, myAllocator);
181 BOPCol_ListIteratorOfListOfShape aIt;
187 const BOPCol_ListOfShape& aLSE=myStartShapes;
188 aIt.Initialize(aLSE);
189 for (i=1; aIt.More(); aIt.Next(), ++i) {
190 const TopoDS_Shape& aSE=aIt.Value();
191 if (!aMEP.Contains(aSE)) {
193 MapEdgesAndFaces(aSE, aMEF, myAllocator);
202 for (i=1; i<=aNbE; ++i) {
208 const TopoDS_Shape& aE=aMEF.FindKey(i);
213 // aMES - globally processed edges
215 //------------------------------------- goal: aMEC
216 aMFC.Clear(); // aMEC - edges of CB
217 aMEP.Clear(); // aMVP - edges to process right now
218 aMEAdd.Clear(); // aMVAdd edges to process on next step of for(;;) {
224 for (k=1; k<=aNbEP; ++k) {
225 const TopoDS_Shape& aEP=aMEP(k);
226 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
228 for (; aIt.More(); aIt.Next()) {
229 const TopoDS_Shape& aF=aIt.Value();
232 while (aItF.More()) {
233 const TopoDS_Shape& aW=aItF.Value();
234 if (aW.ShapeType()!=TopAbs_WIRE) {
240 while (aItW.More()) {
241 const TopoDS_Shape& aEF=aItW.Value();
256 aNbEP=aMEAdd.Extent();
258 break; // from for(;;) {
263 for (k=1; k<=aNbEP; ++k) {
264 const TopoDS_Shape& aEF=aMEAdd(k);
270 //-------------------------------------
271 BOPTools_ConnexityBlock aCB(myAllocator);
273 BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
274 BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
276 bRegular=Standard_True;
277 aNbCB = aMFC.Extent();
278 for (j=1; j<=aNbCB; ++j) {
281 if (aMER.Contains(aFR)) {
282 aFR.Orientation(TopAbs_FORWARD);
284 aFR.Orientation(TopAbs_REVERSED);
286 bRegular=Standard_False;
293 MapEdgesAndFaces(aFR, aMEFR, myAllocator);
298 Standard_Integer aNbER, aNbFR;
300 aNbER=aMEFR.Extent();
301 for (k=1; k<=aNbER; ++k) {
302 const BOPCol_ListOfShape& aLFR=aMEFR(k);
311 aCB.SetRegular(bRegular);
315 //=======================================================================
316 //function : SplitBlock
318 //=======================================================================
319 void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
321 Standard_Integer aNbLF, aNbOff, aNbFP;
323 TopAbs_Orientation anOr;
326 TopoDS_Iterator aItS;
327 TopExp_Explorer aExp;
328 BOPCol_ListIteratorOfListOfShape aItF;
329 BOPTools_CoupleOfShape aCSOff;
330 BOPCol_MapOfOrientedShape AddedFacesMap;
331 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
333 Handle (IntTools_Context) aContext=new IntTools_Context;
335 const BOPCol_ListOfShape& myShapes=aCB.Shapes();
337 BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
341 aItF.Initialize (myShapes);
342 for (; aItF.More(); aItF.Next()) {
343 const TopoDS_Shape& aFF = aItF.Value();
344 BOPTools::MapShapesAndAncestors (aFF,
350 aItF.Initialize (myShapes);
351 for (i=1; aItF.More(); aItF.Next(), ++i) {
352 const TopoDS_Shape& aFF = aItF.Value();
353 if (!AddedFacesMap.Add(aFF)) {
359 aBB.MakeShell(aShell);
360 aBB.Add(aShell, aFF);
363 BOPTools::MapShapesAndAncestors(aFF,
368 // loop on faces added to Shell;
369 // add their neighbor faces to Shell and so on
370 aItS.Initialize (aShell);
371 for (; aItS.More(); aItS.Next()) {
372 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
374 // loop on edges of aF; find a good neighbor face of aF by aE
375 aExp.Init(aF, TopAbs_EDGE);
376 for (; aExp.More(); aExp.Next()) {
377 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
380 if (aMEFP.Contains(aE)) {
381 const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
388 anOr=aE.Orientation();
389 if (anOr==TopAbs_INTERNAL) {
393 if (BRep_Tool::Degenerated(aE)) {
397 // candidate faces list
398 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
404 // try to select one of neighbors
405 // check if a face already added to Shell shares E
406 Standard_Boolean bFound;
407 BOPCol_ListIteratorOfListOfShape aItLF;
408 BOPTools_ListOfCoupleOfShape aLCSOff;
410 aItLF.Initialize(aLF);
411 for (; aItLF.More(); aItLF.Next()) {
412 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
413 if (aF.IsSame(aFL)) {
416 if (AddedFacesMap.Contains(aFL)){
420 bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
425 aCSOff.SetShape1(aEL);
426 aCSOff.SetShape2(aFL);
427 aLCSOff.Append(aCSOff);
428 }//for (; aItLF.More(); aItLF.Next()) {
430 aNbOff=aLCSOff.Extent();
437 aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
440 BOPTools_AlgoTools::GetFaceOff(aE,
447 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
448 aBB.Add(aShell, aSelF);
449 BOPTools::MapShapesAndAncestors(aSelF,
454 } // for (; aExp.More(); aExp.Next()) {
455 } // for (; aItS.More(); aItS.Next()) {
457 if (BRep_Tool::IsClosed(aShell)) {
458 aShell.Closed (Standard_True);
459 myLoops.Append(aShell);
463 if (BRep_Tool::IsClosed(aShell)) {
464 aShell.Closed (Standard_True);
465 myLoops.Append(aShell);
468 } // for (; aItF.More(); aItF.Next()) {
470 //=======================================================================
471 //function : RefineShell
473 //=======================================================================
474 void RefineShell(TopoDS_Shell& theShell)
478 aIt.Initialize(theShell);
483 Standard_Integer i, aNbMEF, aNbF;
484 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
486 TopExp_Explorer aExp;
487 BOPCol_MapOfShape aMEStop, aMFB;
488 BOPCol_MapIteratorOfMapOfShape aItM;
489 BOPCol_ListIteratorOfListOfShape aItLF, aItLFP;
490 BOPCol_ListOfShape aLFP, aLFP1;
493 BOPTools::MapShapesAndAncestors (theShell,
497 aNbMEF=aMEF.Extent();
498 for (i=1; i<=aNbMEF; ++i) {
499 const TopoDS_Shape& aE=aMEF.FindKey(i);
500 const BOPCol_ListOfShape& aLF=aMEF.FindFromIndex(i);
507 if (aMEStop.IsEmpty()) {
512 const TopoDS_Shape& aF1=aIt.Value();
516 // Trying to reach the branch point
518 aItLFP.Initialize(aLFP);
519 for (; aItLFP.More(); aItLFP.Next()) {
520 const TopoDS_Shape& aFP=aItLFP.Value();
522 aExp.Init(aFP, TopAbs_EDGE);
523 for (; aExp.More(); aExp.Next()) {
524 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
525 if (aMEStop.Contains(aE)) {
529 if (BRep_Tool::Degenerated(aE)) {
533 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
535 aItLF.Initialize(aLF);
536 for (; aItLF.More(); aItLF.Next()) {
537 const TopoDS_Shape& aFP1=aItLF.Value();
538 if (aFP1.IsSame(aFP)) {
541 if (aMFB.Contains(aFP1)) {
546 }// for (; aItLF.More(); aItLF.Next()) {
547 }// for (; aExp.More(); aExp.Next()) {
548 }// for (; aItLFP.More(); aItLFP.Next()) {
551 if (aLFP1.IsEmpty()) {
556 aItLF.Initialize(aLFP1);
557 for (; aItLF.More(); aItLF.Next()) {
558 const TopoDS_Shape& aFP1=aItLF.Value();
564 // Remove all faces before the branch point
565 aItM.Initialize(aMFB);
566 for (; aItM.More(); aItM.Next()) {
567 const TopoDS_Shape& aFB=aItM.Value();
568 aBB.Remove(theShell, aFB);
571 //=======================================================================
572 //function : MakeShells
574 //=======================================================================
575 void BOPAlgo_ShellSplitter::MakeShells()
577 Standard_Boolean bIsRegular;
578 Standard_Integer aNbVCBK, k;
579 BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
580 BOPCol_ListIteratorOfListOfShape aIt;
581 BOPAlgo_VectorOfCBK aVCBK;
586 aItCB.Initialize(myLCB);
587 for (; aItCB.More(); aItCB.Next()) {
588 BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
589 bIsRegular=aCB.IsRegular();
593 const BOPCol_ListOfShape& aLF=aCB.Shapes();
594 MakeShell(aLF, aShell);
595 aShell.Closed(Standard_True);
596 myShells.Append(aShell);
599 BOPAlgo_CBK& aCBK=aVCBK.Append1();
600 aCBK.SetConnexityBlock(aCB);
604 aNbVCBK=aVCBK.Extent();
605 //===================================================
606 BOPAlgo_CBKCnt::Perform(myRunParallel, aVCBK);
607 //===================================================
608 for (k=0; k<aNbVCBK; ++k) {
609 BOPAlgo_CBK& aCBK=aVCBK(k);
610 const BOPTools_ConnexityBlock& aCB=aCBK.ConnexityBlock();
611 const BOPCol_ListOfShape& aLS=aCB.Loops();
613 for (; aIt.More(); aIt.Next()) {
614 TopoDS_Shape& aShell=aIt.ChangeValue();
615 aShell.Closed(Standard_True);
616 myShells.Append(aShell);
620 //=======================================================================
621 //function : MakeShell
623 //=======================================================================
624 void MakeShell(const BOPCol_ListOfShape& aLS,
625 TopoDS_Shell& aShell)
628 BOPCol_ListIteratorOfListOfShape aIt;
630 aBB.MakeShell(aShell);
633 for (; aIt.More(); aIt.Next()) {
634 const TopoDS_Shape& aF=aIt.Value();
638 //=======================================================================
639 // function: MapEdgesAndFaces
641 //=======================================================================
642 void MapEdgesAndFaces
643 (const TopoDS_Shape& aF,
644 BOPCol_IndexedDataMapOfShapeListOfShape& aMEF,
645 const Handle(NCollection_BaseAllocator)& theAllocator)
647 TopoDS_Iterator aItF, aItW;
650 while (aItF.More()) {
651 const TopoDS_Shape& aW=aItF.Value();
652 if (aW.ShapeType()!=TopAbs_WIRE) {
658 while (aItW.More()) {
659 const TopoDS_Shape& aE=aItW.Value();
661 if (aMEF.Contains(aE)) {
662 BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
666 BOPCol_ListOfShape aLS(theAllocator);