0024861: Extra solid is in the result of General Fuse Operation
[occt.git] / src / BOPAlgo / BOPAlgo_ShellSplitter.cxx
CommitLineData
682c9d06 1// Created by: Peter KURNEV
2// Copyright (c) 1999-2014 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
d5f74e42 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
682c9d06 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.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
df80c6dd 15// File: BOPAlgo_ShellSplitter.cxx
16// Created: Thu Jan 16 08:33:50 2014
17// <pkv@PETREX>
682c9d06 18
19#include <BOPAlgo_ShellSplitter.ixx>
20//
21#include <TopoDS_Shape.hxx>
22#include <TopoDS_Shell.hxx>
23#include <TopoDS_Edge.hxx>
24
25#include <BRep_Builder.hxx>
26#include <TopExp_Explorer.hxx>
27//
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>
34//
35#include <BOPInt_Context.hxx>
36//
37#include <BOPTools.hxx>
38#include <BOPTools_AlgoTools.hxx>
39#include <BOPTools_CoupleOfShape.hxx>
69b558c4 40
682c9d06 41//
42static
43 Standard_Boolean IsClosedShell(const TopoDS_Shell& );
69b558c4 44//
682c9d06 45static
46 void MakeShell(const BOPCol_ListOfShape& ,
df80c6dd 47 TopoDS_Shell& );
69b558c4 48//
49static
50 void RefineShell(TopoDS_Shell& theShell);
682c9d06 51
69b558c4 52//=======================================================================
53//class : BOPAlgo_CBK
54//purpose :
55//=======================================================================
56class BOPAlgo_CBK {
57 public:
58 BOPAlgo_CBK() :
59 myPCB (NULL) {
60 }
61 //
62 ~BOPAlgo_CBK() {
63 }
64 //
65 void SetConnexityBlock (const BOPTools_ConnexityBlock& aCB) {
66 myPCB=(BOPTools_ConnexityBlock*)&aCB;
67 }
68 //
69 BOPTools_ConnexityBlock& ConnexityBlock () {
70 return *myPCB;
71 }
72 //
73 void Perform() {
74 BOPAlgo_ShellSplitter::SplitBlock(*myPCB);
75 }
76 protected:
77 BOPTools_ConnexityBlock *myPCB;
78};
79//=======================================================================
80typedef BOPCol_NCVector
81 <BOPAlgo_CBK> BOPAlgo_VectorOfCBK;
82//
83typedef BOPCol_TBBFunctor
84 <BOPAlgo_CBK,
85 BOPAlgo_VectorOfCBK> BOPAlgo_CBKFunctor;
86//
87typedef BOPCol_TBBCnt
88 <BOPAlgo_CBKFunctor,
89 BOPAlgo_VectorOfCBK> BOPAlgo_CBKCnt;
90//
682c9d06 91//=======================================================================
92//function :
93//purpose :
94//=======================================================================
95BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
96:
97 BOPAlgo_Algo(),
98 myStartShapes(myAllocator),
99 myShells(myAllocator),
100 myLCB(myAllocator)
101{
102}
103//=======================================================================
104//function :
105//purpose :
106//=======================================================================
107BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
108 (const Handle(NCollection_BaseAllocator)& theAllocator)
109:
110 BOPAlgo_Algo(theAllocator),
111 myStartShapes(theAllocator),
112 myShells(theAllocator),
113 myLCB(myAllocator)
114{
115}
116//=======================================================================
117//function : ~
118//purpose :
119//=======================================================================
120BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
121{
122}
123//=======================================================================
124//function : AddStartElement
125//purpose :
126//=======================================================================
127void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
128{
129 myStartShapes.Append(aE);
130}
131//=======================================================================
132//function : StartElements
133//purpose :
134//=======================================================================
135const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
136{
137 return myStartShapes;
138}
139//=======================================================================
140//function : Loops
141//purpose :
142//=======================================================================
143const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
144{
145 return myShells;
146}
147//=======================================================================
148//function : Perform
149//purpose :
150//=======================================================================
151void BOPAlgo_ShellSplitter::Perform()
152{
153 myErrorStatus=0;
154 //
155 MakeConnexityBlocks();
156 if (myErrorStatus) {
157 return;
158 }
159 //
160 MakeShells();
161}
162//=======================================================================
163//function : MakeConnexityBlocks
164//purpose :
165//=======================================================================
166void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
167{
168 Standard_Boolean bRegular;
169 Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
170 TopoDS_Shape aFR;
171 TopExp_Explorer aExpF;
172 BOPCol_IndexedDataMapOfShapeListOfShape aMEF(100, myAllocator);
173 BOPCol_IndexedMapOfShape aMEP(100, myAllocator);
174 BOPCol_IndexedMapOfShape aMFC(100, myAllocator);
175 BOPCol_MapOfShape aMER(100, myAllocator);
176 BOPCol_MapOfShape aMFP(100, myAllocator);
177 BOPCol_IndexedMapOfShape aMEAdd(100, myAllocator);
178 BOPCol_MapOfShape aMES(100, myAllocator);
179 BOPCol_ListIteratorOfListOfShape aIt;
180 //
181 myErrorStatus=0;
182 //
183 myLCB.Clear();
184 //
185 const BOPCol_ListOfShape& aLSE=myStartShapes;
186 aIt.Initialize(aLSE);
187 for (i=1; aIt.More(); aIt.Next(), ++i) {
188 const TopoDS_Shape& aSE=aIt.Value();
189 if (!aMEP.Contains(aSE)) {
190 aMEP.Add(aSE);
191 BOPTools::MapShapesAndAncestors(aSE,
69b558c4 192 TopAbs_EDGE,
193 TopAbs_FACE,
df80c6dd 194 aMEF);
682c9d06 195 }
196 else {
197 aMER.Add(aSE);
198 }
199 }
200 //
201 // 2
202 aNbE=aMEF.Extent();
203 for (i=1; i<=aNbE; ++i) {
204 aNbES=aMES.Extent();
205 if (aNbES==aNbE) {
206 break;
207 }
208 //
209 const TopoDS_Shape& aE=aMEF.FindKey(i);
210 //
211 if (!aMES.Add(aE)) {
212 continue;
213 }
214 // aMES - globally processed edges
215 //
216 //------------------------------------- goal: aMEC
217 aMFC.Clear(); // aMEC - edges of CB
218 aMEP.Clear(); // aMVP - edges to process right now
219 aMEAdd.Clear(); // aMVAdd edges to process on next step of for(;;) {
220 //
221 aMEP.Add(aE);
222 //
223 for(;;) {
224 aNbEP=aMEP.Extent();
225 for (k=1; k<=aNbEP; ++k) {
226 const TopoDS_Shape& aEP=aMEP(k);
227 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
228 aIt.Initialize(aLF);
229 for (; aIt.More(); aIt.Next()) {
230 const TopoDS_Shape& aF=aIt.Value();
231 if (aMFC.Add(aF)) {
df80c6dd 232 aExpF.Init(aF, TopAbs_EDGE);
682c9d06 233 for (; aExpF.More(); aExpF.Next()) {
234 const TopoDS_Shape& aEF=aExpF.Current();
235 if (aMES.Add(aEF)) {
236 aMEAdd.Add(aEF);
237 }
238 }
239 }
240 }
241 }
242 //
243 aNbEP=aMEAdd.Extent();
244 if (!aNbEP) {
245 break; // from for(;;) {
246 }
247 //
248 aMEP.Clear();
249 //
250 for (k=1; k<=aNbEP; ++k) {
251 const TopoDS_Shape& aEF=aMEAdd(k);
252 aMEP.Add(aEF);
253 }
254 aMEAdd.Clear();
255 }// for(;;) {
256 //
257 //-------------------------------------
258 BOPTools_ConnexityBlock aCB(myAllocator);
259 //
260 BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
261 BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
262 //
263 bRegular=Standard_True;
264 aNbCB = aMFC.Extent();
265 for (j=1; j<=aNbCB; ++j) {
266 aFR = aMFC(j);
267 //
268 if (aMER.Contains(aFR)) {
269 aFR.Orientation(TopAbs_FORWARD);
270 aLECB.Append(aFR);
271 aFR.Orientation(TopAbs_REVERSED);
272 aLECB.Append(aFR);
273 bRegular=Standard_False;
274 }
275 else {
276 aLECB.Append(aFR);
277 }
278 //
279 if (bRegular) {
280 BOPTools::MapShapesAndAncestors(aFR,
69b558c4 281 TopAbs_EDGE,
282 TopAbs_FACE,
df80c6dd 283 aMEFR);
682c9d06 284 }
285 }
286 //
287 if (bRegular) {
288 Standard_Integer aNbER, aNbFR;
289 //
290 aNbER=aMEFR.Extent();
291 for (k=1; k<=aNbER; ++k) {
292 const BOPCol_ListOfShape& aLFR=aMEFR(k);
293 aNbFR=aLFR.Extent();
294 if (aNbFR>2) {
295 bRegular=!bRegular;
296 break;
297 }
298 }
299 }
300 //
301 aCB.SetRegular(bRegular);
302 myLCB.Append(aCB);
303 }
304}
305//=======================================================================
306//function : SplitBlock
307//purpose :
308//=======================================================================
309void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
310{
311 Standard_Integer aNbLF, aNbOff, aNbFP;
312 Standard_Integer i;
313 TopAbs_Orientation anOr;
314 TopoDS_Edge aEL;
315 BRep_Builder aBB;
316 TopoDS_Iterator aItS;
317 TopExp_Explorer aExp;
318 BOPCol_ListIteratorOfListOfShape aItF;
319 BOPTools_CoupleOfShape aCSOff;
320 BOPCol_MapOfOrientedShape AddedFacesMap;
321 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP;
322 //
323 Handle (BOPInt_Context) aContext=new BOPInt_Context;
324 //
325 const BOPCol_ListOfShape& myShapes=aCB.Shapes();
326 //
327 BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
328 myLoops.Clear();
329 //
330 // 1. Shells Usual
331 aItF.Initialize (myShapes);
332 for (; aItF.More(); aItF.Next()) {
333 const TopoDS_Shape& aFF = aItF.Value();
69b558c4 334 BOPTools::MapShapesAndAncestors (aFF,
335 TopAbs_EDGE,
336 TopAbs_FACE,
337 aEFMap);
682c9d06 338 }
339 //
340 aItF.Initialize (myShapes);
341 for (i=1; aItF.More(); aItF.Next(), ++i) {
342 const TopoDS_Shape& aFF = aItF.Value();
343 if (!AddedFacesMap.Add(aFF)) {
344 continue;
345 }
346 //
347 // make a new shell
348 TopoDS_Shell aShell;
349 aBB.MakeShell(aShell);
350 aBB.Add(aShell, aFF);
351 //
352 aMEFP.Clear();
353 BOPTools::MapShapesAndAncestors(aFF,
69b558c4 354 TopAbs_EDGE,
355 TopAbs_FACE,
df80c6dd 356 aMEFP);
682c9d06 357 //
358 // loop on faces added to Shell;
359 // add their neighbor faces to Shell and so on
360 aItS.Initialize (aShell);
361 for (; aItS.More(); aItS.Next()) {
362 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
363 //
364 // loop on edges of aF; find a good neighbor face of aF by aE
365 aExp.Init(aF, TopAbs_EDGE);
366 for (; aExp.More(); aExp.Next()) {
367 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
368 //
369 //1
370 if (aMEFP.Contains(aE)) {
371 const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
372 aNbFP=aLFP.Extent();
373 if (aNbFP>1) {
374 continue;
375 }
376 }
377 //2
378 anOr=aE.Orientation();
379 if (anOr==TopAbs_INTERNAL) {
380 continue;
381 }
382 //3
383 if (BRep_Tool::Degenerated(aE)) {
384 continue;
385 }
386 //
387 // candidate faces list
388 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
389 aNbLF=aLF.Extent();
390 if (!aNbLF) {
391 continue;
392 }
393 //
394 // try to select one of neighbors
395 // check if a face already added to Shell shares E
396 Standard_Boolean bFound;
397 BOPCol_ListIteratorOfListOfShape aItLF;
398 BOPTools_ListOfCoupleOfShape aLCSOff;
399 //
400 aItLF.Initialize(aLF);
401 for (; aItLF.More(); aItLF.Next()) {
402 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
403 if (aF.IsSame(aFL)) {
404 continue;
405 }
406 if (AddedFacesMap.Contains(aFL)){
407 continue;
408 }
409 //
410 bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
411 if (!bFound) {
412 continue;
413 }
414 //
415 aCSOff.SetShape1(aEL);
416 aCSOff.SetShape2(aFL);
417 aLCSOff.Append(aCSOff);
418 }//for (; aItLF.More(); aItLF.Next()) {
419 //
420 aNbOff=aLCSOff.Extent();
421 if (!aNbOff){
422 continue;
423 }
424 //
425 TopoDS_Face aSelF;
426 if (aNbOff==1) {
427 aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
428 }
429 else if (aNbOff>1){
69b558c4 430 BOPTools_AlgoTools::GetFaceOff(aE,
431 aF,
432 aLCSOff,
433 aSelF,
434 aContext);
682c9d06 435 }
436 //
437 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
438 aBB.Add(aShell, aSelF);
439 BOPTools::MapShapesAndAncestors(aSelF,
69b558c4 440 TopAbs_EDGE,
441 TopAbs_FACE,
df80c6dd 442 aMEFP);
682c9d06 443 }
69b558c4 444 } // for (; aExp.More(); aExp.Next()) {
445 } // for (; aItS.More(); aItS.Next()) {
682c9d06 446 //
447 if (IsClosedShell(aShell)) {
448 myLoops.Append(aShell);
449 }
69b558c4 450 else {
451 RefineShell(aShell);
452 if (IsClosedShell(aShell)) {
453 myLoops.Append(aShell);
454 }
455 }
682c9d06 456 } // for (; aItF.More(); aItF.Next()) {
457}
458//=======================================================================
69b558c4 459//function : RefineShell
460//purpose :
682c9d06 461//=======================================================================
69b558c4 462void RefineShell(TopoDS_Shell& theShell)
463{
464 TopoDS_Iterator aIt;
682c9d06 465 //
69b558c4 466 aIt.Initialize(theShell);
467 if(!aIt.More()) {
468 return;
682c9d06 469 }
470 //
69b558c4 471 Standard_Integer i, aNbMEF, aNbF;
472 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
473 TopoDS_Builder aBB;
474 TopExp_Explorer aExp;
475 BOPCol_MapOfShape aMEStop, aMFB;
476 BOPCol_MapIteratorOfMapOfShape aItM;
477 BOPCol_ListIteratorOfListOfShape aItLF, aItLFP;
478 BOPCol_ListOfShape aLFP, aLFP1;
479 //
480 // Branch points
481 BOPTools::MapShapesAndAncestors (theShell,
482 TopAbs_EDGE,
483 TopAbs_FACE,
484 aMEF);
485 aNbMEF=aMEF.Extent();
486 for (i=1; i<=aNbMEF; ++i) {
487 const TopoDS_Shape& aE=aMEF.FindKey(i);
488 const BOPCol_ListOfShape& aLF=aMEF.FindFromIndex(i);
489 aNbF=aLF.Extent();
490 if (aNbF>2) {
491 aMEStop.Add(aE);
492 }
493 }
494 //
495 if (aMEStop.IsEmpty()) {
496 return;
497 }
498 //
499 // The first Face
500 const TopoDS_Shape& aF1=aIt.Value();
501 aMFB.Add(aF1);
502 aLFP.Append(aF1);
503 //
504 // Trying to reach the branch point
505 for (;;) {
506 aItLFP.Initialize(aLFP);
507 for (; aItLFP.More(); aItLFP.Next()) {
508 const TopoDS_Shape& aFP=aItLFP.Value();
509 //
510 aExp.Init(aFP, TopAbs_EDGE);
511 for (; aExp.More(); aExp.Next()) {
512 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
513 if (aMEStop.Contains(aE)) {
514 continue;
515 }
516 //
517 if (BRep_Tool::Degenerated(aE)) {
518 continue;
519 }
520 //
521 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
522 //
523 aItLF.Initialize(aLF);
524 for (; aItLF.More(); aItLF.Next()) {
525 const TopoDS_Shape& aFP1=aItLF.Value();
526 if (aFP1.IsSame(aFP)) {
527 continue;
528 }
529 if (aMFB.Contains(aFP1)) {
530 continue;
531 }
532 aMFB.Add(aFP1);
533 aLFP1.Append(aFP1);
534 }// for (; aItLF.More(); aItLF.Next()) {
535 }// for (; aExp.More(); aExp.Next()) {
536 }// for (; aItLFP.More(); aItLFP.Next()) {
682c9d06 537 //
682c9d06 538 //
69b558c4 539 if (aLFP1.IsEmpty()) {
540 break;
541 }
542 //
543 aLFP.Clear();
544 aItLF.Initialize(aLFP1);
545 for (; aItLF.More(); aItLF.Next()) {
546 const TopoDS_Shape& aFP1=aItLF.Value();
547 aLFP.Append(aFP1);
682c9d06 548 }
69b558c4 549 aLFP1.Clear();
550 }// for (;;) {
551 //
552 // Remove all faces before the branch point
553 aItM.Initialize(aMFB);
554 for (; aItM.More(); aItM.Next()) {
555 const TopoDS_Shape& aFB=aItM.Value();
556 aBB.Remove(theShell, aFB);
682c9d06 557 }
69b558c4 558}
682c9d06 559//=======================================================================
69b558c4 560//function : IsClosedShell
561//purpose :
682c9d06 562//=======================================================================
69b558c4 563Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
564{
565 Standard_Integer i, aNbE;
566 Standard_Boolean bRet;
567 TopoDS_Iterator aIt;
568 TopExp_Explorer aExp;
569 BOPCol_MapOfShape aM;
570 //
571 bRet=Standard_False;
572 //
573 aIt.Initialize(theShell);
574 for(i=0; aIt.More(); aIt.Next(), ++i) {
575 const TopoDS_Shape& aF=aIt.Value();
682c9d06 576 //
69b558c4 577 aExp.Init(aF, TopAbs_EDGE);
578 for (; aExp.More(); aExp.Next()) {
579 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aExp.Current()));
580 if (BRep_Tool::Degenerated(aE)) {
581 continue;
582 }
583 //
584 if (aE.Orientation()==TopAbs_INTERNAL) {
585 continue;
586 }
587 if (!aM.Add(aE)) {
588 aM.Remove(aE);
589 }
682c9d06 590 }
69b558c4 591 }
592 //
593 if(i) {
594 aNbE=aM.Extent();
595 if (!aNbE) {
596 bRet=!bRet;
682c9d06 597 }
598 }
69b558c4 599 return bRet;
600}
682c9d06 601//=======================================================================
69b558c4 602//function : MakeShells
682c9d06 603//purpose :
604//=======================================================================
605void BOPAlgo_ShellSplitter::MakeShells()
606{
607 Standard_Boolean bIsRegular;
69b558c4 608 Standard_Integer aNbVCBK, k;
682c9d06 609 BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
610 BOPCol_ListIteratorOfListOfShape aIt;
69b558c4 611 BOPAlgo_VectorOfCBK aVCBK;
682c9d06 612 //
613 myErrorStatus=0;
614 myShells.Clear();
615 //
616 aItCB.Initialize(myLCB);
617 for (; aItCB.More(); aItCB.Next()) {
618 BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
619 bIsRegular=aCB.IsRegular();
620 if (bIsRegular) {
621 TopoDS_Shell aShell;
622 //
623 const BOPCol_ListOfShape& aLF=aCB.Shapes();
624 MakeShell(aLF, aShell);
df80c6dd 625 aShell.TShape()->Closed(Standard_True);
682c9d06 626 myShells.Append(aShell);
627 }
628 else {
69b558c4 629 BOPAlgo_CBK& aCBK=aVCBK.Append1();
630 aCBK.SetConnexityBlock(aCB);
682c9d06 631 }
632 }
633 //
69b558c4 634 aNbVCBK=aVCBK.Extent();
682c9d06 635 //===================================================
69b558c4 636 BOPAlgo_CBKCnt::Perform(myRunParallel, aVCBK);
682c9d06 637 //===================================================
69b558c4 638 for (k=0; k<aNbVCBK; ++k) {
639 BOPAlgo_CBK& aCBK=aVCBK(k);
640 const BOPTools_ConnexityBlock& aCB=aCBK.ConnexityBlock();
682c9d06 641 const BOPCol_ListOfShape& aLS=aCB.Loops();
642 aIt.Initialize(aLS);
643 for (; aIt.More(); aIt.Next()) {
644 const TopoDS_Shape& aShell=aIt.Value();
df80c6dd 645 aShell.TShape()->Closed(Standard_True);
682c9d06 646 myShells.Append(aShell);
647 }
648 }
649}
650//=======================================================================
682c9d06 651//function : MakeShell
652//purpose :
653//=======================================================================
654void MakeShell(const BOPCol_ListOfShape& aLS,
df80c6dd 655 TopoDS_Shell& aShell)
682c9d06 656{
657 BRep_Builder aBB;
658 BOPCol_ListIteratorOfListOfShape aIt;
659 //
660 aBB.MakeShell(aShell);
661 //
662 aIt.Initialize(aLS);
663 for (; aIt.More(); aIt.Next()) {
664 const TopoDS_Shape& aF=aIt.Value();
665 aBB.Add(aShell, aF);
666 }
667}