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
7 // under the terms of the GNU Lesser General Public 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
19 #include <BOPAlgo_ShellSplitter.ixx>
21 #include <TopoDS_Shape.hxx>
22 #include <TopoDS_Shell.hxx>
23 #include <TopoDS_Edge.hxx>
25 #include <BRep_Builder.hxx>
26 #include <TopExp_Explorer.hxx>
28 #include <BOPCol_TBB.hxx>
29 #include <BOPCol_IndexedMapOfShape.hxx>
30 #include <BOPCol_MapOfShape.hxx>
31 #include <BOPCol_MapOfOrientedShape.hxx>
32 #include <BOPCol_NCVector.hxx>
33 #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
35 #include <BOPInt_Context.hxx>
37 #include <BOPTools.hxx>
38 #include <BOPTools_AlgoTools.hxx>
39 #include <BOPTools_CoupleOfShape.hxx>
41 typedef BOPCol_NCVector<BOPTools_ConnexityBlock> \
42 BOPAlgo_ShellSplitter_VectorOfConnexityBlock;
45 Standard_Boolean IsClosedShell(const TopoDS_Shell& );
47 void MakeShell(const BOPCol_ListOfShape& ,
50 //=======================================================================
53 //=======================================================================
54 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
57 myStartShapes(myAllocator),
58 myShells(myAllocator),
62 //=======================================================================
65 //=======================================================================
66 BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
67 (const Handle(NCollection_BaseAllocator)& theAllocator)
69 BOPAlgo_Algo(theAllocator),
70 myStartShapes(theAllocator),
71 myShells(theAllocator),
75 //=======================================================================
78 //=======================================================================
79 BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
82 //=======================================================================
83 //function : AddStartElement
85 //=======================================================================
86 void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
88 myStartShapes.Append(aE);
90 //=======================================================================
91 //function : StartElements
93 //=======================================================================
94 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
98 //=======================================================================
101 //=======================================================================
102 const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
106 //=======================================================================
109 //=======================================================================
110 void BOPAlgo_ShellSplitter::Perform()
114 MakeConnexityBlocks();
121 //=======================================================================
122 //function : MakeConnexityBlocks
124 //=======================================================================
125 void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
127 Standard_Boolean bRegular;
128 Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
130 TopExp_Explorer aExpF;
131 BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
132 BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
133 BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
134 BOPCol_MapOfShape aMER(100, myAllocator);
135 BOPCol_MapOfShape aMFP(100, myAllocator);
136 BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
137 BOPCol_MapOfShape aMES(100, myAllocator);
138 BOPCol_ListIteratorOfListOfShape aIt;
144 const BOPCol_ListOfShape& aLSE=myStartShapes;
145 aIt.Initialize(aLSE);
146 for (i=1; aIt.More(); aIt.Next(), ++i) {
147 const TopoDS_Shape& aSE=aIt.Value();
148 if (!aMEP.Contains(aSE)) {
150 BOPTools::MapShapesAndAncestors(aSE,
151 TopAbs_EDGE, TopAbs_FACE,
161 for (i=1; i<=aNbE; ++i) {
167 const TopoDS_Shape& aE=aMEF.FindKey(i);
172 // aMES - globally processed edges
174 //------------------------------------- goal: aMEC
175 aMFC.Clear(); // aMEC - edges of CB
176 aMEP.Clear(); // aMVP - edges to process right now
177 aMEAdd.Clear(); // aMVAdd edges to process on next step of for(;;) {
183 for (k=1; k<=aNbEP; ++k) {
184 const TopoDS_Shape& aEP=aMEP(k);
185 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
187 for (; aIt.More(); aIt.Next()) {
188 const TopoDS_Shape& aF=aIt.Value();
190 aExpF.Init(aF, TopAbs_EDGE);
191 for (; aExpF.More(); aExpF.Next()) {
192 const TopoDS_Shape& aEF=aExpF.Current();
201 aNbEP=aMEAdd.Extent();
203 break; // from for(;;) {
208 for (k=1; k<=aNbEP; ++k) {
209 const TopoDS_Shape& aEF=aMEAdd(k);
215 //-------------------------------------
216 BOPTools_ConnexityBlock aCB(myAllocator);
218 BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
219 BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
221 bRegular=Standard_True;
222 aNbCB = aMFC.Extent();
223 for (j=1; j<=aNbCB; ++j) {
226 if (aMER.Contains(aFR)) {
227 aFR.Orientation(TopAbs_FORWARD);
229 aFR.Orientation(TopAbs_REVERSED);
231 bRegular=Standard_False;
238 BOPTools::MapShapesAndAncestors(aFR,
239 TopAbs_EDGE, TopAbs_FACE,
245 Standard_Integer aNbER, aNbFR;
247 aNbER=aMEFR.Extent();
248 for (k=1; k<=aNbER; ++k) {
249 const BOPCol_ListOfShape& aLFR=aMEFR(k);
258 aCB.SetRegular(bRegular);
262 //=======================================================================
263 //function : SplitBlock
265 //=======================================================================
266 void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
268 Standard_Integer aNbLF, aNbOff, aNbFP;
270 TopAbs_Orientation anOr;
273 TopoDS_Iterator aItS;
274 TopExp_Explorer aExp;
275 BOPCol_ListIteratorOfListOfShape aItF;
276 BOPTools_CoupleOfShape aCSOff;
277 BOPCol_MapOfOrientedShape AddedFacesMap;
278 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
280 Handle (BOPInt_Context) aContext=new BOPInt_Context;
282 const BOPCol_ListOfShape& myShapes=aCB.Shapes();
284 BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
288 aItF.Initialize (myShapes);
289 for (; aItF.More(); aItF.Next()) {
290 const TopoDS_Shape& aFF = aItF.Value();
291 BOPTools::MapShapesAndAncestors
292 (aFF, TopAbs_EDGE, TopAbs_FACE, aEFMap);
295 aItF.Initialize (myShapes);
296 for (i=1; aItF.More(); aItF.Next(), ++i) {
297 const TopoDS_Shape& aFF = aItF.Value();
298 if (!AddedFacesMap.Add(aFF)) {
304 aBB.MakeShell(aShell);
305 aBB.Add(aShell, aFF);
308 BOPTools::MapShapesAndAncestors(aFF,
309 TopAbs_EDGE, TopAbs_FACE,
312 // loop on faces added to Shell;
313 // add their neighbor faces to Shell and so on
314 aItS.Initialize (aShell);
315 for (; aItS.More(); aItS.Next()) {
316 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
318 // loop on edges of aF; find a good neighbor face of aF by aE
319 aExp.Init(aF, TopAbs_EDGE);
320 for (; aExp.More(); aExp.Next()) {
321 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
324 if (aMEFP.Contains(aE)) {
325 const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
332 anOr=aE.Orientation();
333 if (anOr==TopAbs_INTERNAL) {
337 if (BRep_Tool::Degenerated(aE)) {
341 // candidate faces list
342 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
348 // try to select one of neighbors
349 // check if a face already added to Shell shares E
350 Standard_Boolean bFound;
351 BOPCol_ListIteratorOfListOfShape aItLF;
352 BOPTools_ListOfCoupleOfShape aLCSOff;
354 aItLF.Initialize(aLF);
355 for (; aItLF.More(); aItLF.Next()) {
356 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
357 if (aF.IsSame(aFL)) {
360 if (AddedFacesMap.Contains(aFL)){
364 bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
369 aCSOff.SetShape1(aEL);
370 aCSOff.SetShape2(aFL);
371 aLCSOff.Append(aCSOff);
372 }//for (; aItLF.More(); aItLF.Next()) {
374 aNbOff=aLCSOff.Extent();
381 aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
384 BOPTools_AlgoTools::GetFaceOff(aE, aF,
385 aLCSOff, aSelF, aContext);
388 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
389 aBB.Add(aShell, aSelF);
390 BOPTools::MapShapesAndAncestors(aSelF,
391 TopAbs_EDGE, TopAbs_FACE,
394 } // for (; aEdgeExp.More(); aEdgeExp.Next()) {
395 } //for (; aItAddedF.More(); aItAddedF.Next()) {
397 if (IsClosedShell(aShell)) {
398 myLoops.Append(aShell);
400 } // for (; aItF.More(); aItF.Next()) {
402 //=======================================================================
403 //class : ShellSplitterFunctor
404 //purpose : Auxiliary class
405 //=======================================================================
406 class BOPAlgo_ShellSplitterFunctor {
409 BOPAlgo_ShellSplitter_VectorOfConnexityBlock* myPVCB;
412 BOPAlgo_ShellSplitterFunctor
413 (BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB)
417 void operator()( const flexible_range<Standard_Size>& aBR ) const{
418 Standard_Size i, iBeg, iEnd;
420 BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB=*myPVCB;
424 for(i=iBeg; i!=iEnd; ++i) {
425 BOPTools_ConnexityBlock& aCB=aVCB((Standard_Integer)i);
427 BOPAlgo_ShellSplitter::SplitBlock(aCB);
431 //=======================================================================
432 //class : BOPAlgo_ShellSplitterCnt
433 //purpose : Auxiliary class
434 //=======================================================================
435 class BOPAlgo_ShellSplitterCnt {
437 //-------------------------------
441 (const Standard_Boolean bRunParallel,
442 BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB) {
444 BOPAlgo_ShellSplitterFunctor aSSF(aVCB);
445 Standard_Size aNbVCB=aVCB.Extent();
448 flexible_for(flexible_range<Standard_Size>(0,aNbVCB), aSSF);
451 aSSF.operator()(flexible_range<Standard_Size>(0,aNbVCB));
455 //=======================================================================
456 //function : MMakeShells
458 //=======================================================================
459 void BOPAlgo_ShellSplitter::MakeShells()
461 Standard_Boolean bIsRegular;
462 Standard_Integer aNbVCB, k;
463 BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
464 BOPCol_ListIteratorOfListOfShape aIt;
465 BOPAlgo_ShellSplitter_VectorOfConnexityBlock aVCB;
470 aItCB.Initialize(myLCB);
471 for (; aItCB.More(); aItCB.Next()) {
472 BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
473 bIsRegular=aCB.IsRegular();
477 const BOPCol_ListOfShape& aLF=aCB.Shapes();
478 MakeShell(aLF, aShell);
479 myShells.Append(aShell);
486 aNbVCB=aVCB.Extent();
487 //===================================================
488 BOPAlgo_ShellSplitterCnt::Perform(myRunParallel, aVCB);
489 //===================================================
490 for (k=0; k<aNbVCB; ++k) {
491 const BOPTools_ConnexityBlock& aCB=aVCB(k);
492 const BOPCol_ListOfShape& aLS=aCB.Loops();
494 for (; aIt.More(); aIt.Next()) {
495 const TopoDS_Shape& aShell=aIt.Value();
496 myShells.Append(aShell);
500 //=======================================================================
501 //function : IsClosedShell
503 //=======================================================================
504 Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
506 Standard_Integer aNbE;
507 Standard_Boolean bRet;
509 TopExp_Explorer aExp;
510 BOPCol_MapOfShape aM;
513 aIt.Initialize(theShell);
514 for(; aIt.More(); aIt.Next()) {
515 const TopoDS_Face& aF=(*(TopoDS_Face*)(&aIt.Value()));
516 aExp.Init(aF, TopAbs_EDGE);
517 for (; aExp.More(); aExp.Next()) {
518 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
519 if (BRep_Tool::Degenerated(aE)) {
523 if (aE.Orientation()==TopAbs_INTERNAL) {
538 //=======================================================================
539 //function : MakeShell
541 //=======================================================================
542 void MakeShell(const BOPCol_ListOfShape& aLS,
543 TopoDS_Shell& aShell)
546 BOPCol_ListIteratorOfListOfShape aIt;
548 aBB.MakeShell(aShell);
551 for (; aIt.More(); aIt.Next()) {
552 const TopoDS_Shape& aF=aIt.Value();