0024624: Lost word in license statement in source files
[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
15// File: BOPAlgo_ShellSplitter.cxx
16// Created: Thu Jan 16 08:33:50 2014
17// <pkv@PETREX>
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>
40//
41typedef BOPCol_NCVector<BOPTools_ConnexityBlock> \
42 BOPAlgo_ShellSplitter_VectorOfConnexityBlock;
43//
44static
45 Standard_Boolean IsClosedShell(const TopoDS_Shell& );
46static
47 void MakeShell(const BOPCol_ListOfShape& ,
48 TopoDS_Shell& );
49
50//=======================================================================
51//function :
52//purpose :
53//=======================================================================
54BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter()
55:
56 BOPAlgo_Algo(),
57 myStartShapes(myAllocator),
58 myShells(myAllocator),
59 myLCB(myAllocator)
60{
61}
62//=======================================================================
63//function :
64//purpose :
65//=======================================================================
66BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter
67 (const Handle(NCollection_BaseAllocator)& theAllocator)
68:
69 BOPAlgo_Algo(theAllocator),
70 myStartShapes(theAllocator),
71 myShells(theAllocator),
72 myLCB(myAllocator)
73{
74}
75//=======================================================================
76//function : ~
77//purpose :
78//=======================================================================
79BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter()
80{
81}
82//=======================================================================
83//function : AddStartElement
84//purpose :
85//=======================================================================
86void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE)
87{
88 myStartShapes.Append(aE);
89}
90//=======================================================================
91//function : StartElements
92//purpose :
93//=======================================================================
94const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const
95{
96 return myStartShapes;
97}
98//=======================================================================
99//function : Loops
100//purpose :
101//=======================================================================
102const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const
103{
104 return myShells;
105}
106//=======================================================================
107//function : Perform
108//purpose :
109//=======================================================================
110void BOPAlgo_ShellSplitter::Perform()
111{
112 myErrorStatus=0;
113 //
114 MakeConnexityBlocks();
115 if (myErrorStatus) {
116 return;
117 }
118 //
119 MakeShells();
120}
121//=======================================================================
122//function : MakeConnexityBlocks
123//purpose :
124//=======================================================================
125void BOPAlgo_ShellSplitter::MakeConnexityBlocks()
126{
127 Standard_Boolean bRegular;
128 Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB;
129 TopoDS_Shape aFR;
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;
139 //
140 myErrorStatus=0;
141 //
142 myLCB.Clear();
143 //
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)) {
149 aMEP.Add(aSE);
150 BOPTools::MapShapesAndAncestors(aSE,
151 TopAbs_EDGE, TopAbs_FACE,
152 aMEF);
153 }
154 else {
155 aMER.Add(aSE);
156 }
157 }
158 //
159 // 2
160 aNbE=aMEF.Extent();
161 for (i=1; i<=aNbE; ++i) {
162 aNbES=aMES.Extent();
163 if (aNbES==aNbE) {
164 break;
165 }
166 //
167 const TopoDS_Shape& aE=aMEF.FindKey(i);
168 //
169 if (!aMES.Add(aE)) {
170 continue;
171 }
172 // aMES - globally processed edges
173 //
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(;;) {
178 //
179 aMEP.Add(aE);
180 //
181 for(;;) {
182 aNbEP=aMEP.Extent();
183 for (k=1; k<=aNbEP; ++k) {
184 const TopoDS_Shape& aEP=aMEP(k);
185 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP);
186 aIt.Initialize(aLF);
187 for (; aIt.More(); aIt.Next()) {
188 const TopoDS_Shape& aF=aIt.Value();
189 if (aMFC.Add(aF)) {
190 aExpF.Init(aF, TopAbs_EDGE);
191 for (; aExpF.More(); aExpF.Next()) {
192 const TopoDS_Shape& aEF=aExpF.Current();
193 if (aMES.Add(aEF)) {
194 aMEAdd.Add(aEF);
195 }
196 }
197 }
198 }
199 }
200 //
201 aNbEP=aMEAdd.Extent();
202 if (!aNbEP) {
203 break; // from for(;;) {
204 }
205 //
206 aMEP.Clear();
207 //
208 for (k=1; k<=aNbEP; ++k) {
209 const TopoDS_Shape& aEF=aMEAdd(k);
210 aMEP.Add(aEF);
211 }
212 aMEAdd.Clear();
213 }// for(;;) {
214 //
215 //-------------------------------------
216 BOPTools_ConnexityBlock aCB(myAllocator);
217 //
218 BOPCol_ListOfShape& aLECB=aCB.ChangeShapes();
219 BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator);
220 //
221 bRegular=Standard_True;
222 aNbCB = aMFC.Extent();
223 for (j=1; j<=aNbCB; ++j) {
224 aFR = aMFC(j);
225 //
226 if (aMER.Contains(aFR)) {
227 aFR.Orientation(TopAbs_FORWARD);
228 aLECB.Append(aFR);
229 aFR.Orientation(TopAbs_REVERSED);
230 aLECB.Append(aFR);
231 bRegular=Standard_False;
232 }
233 else {
234 aLECB.Append(aFR);
235 }
236 //
237 if (bRegular) {
238 BOPTools::MapShapesAndAncestors(aFR,
239 TopAbs_EDGE, TopAbs_FACE,
240 aMEFR);
241 }
242 }
243 //
244 if (bRegular) {
245 Standard_Integer aNbER, aNbFR;
246 //
247 aNbER=aMEFR.Extent();
248 for (k=1; k<=aNbER; ++k) {
249 const BOPCol_ListOfShape& aLFR=aMEFR(k);
250 aNbFR=aLFR.Extent();
251 if (aNbFR>2) {
252 bRegular=!bRegular;
253 break;
254 }
255 }
256 }
257 //
258 aCB.SetRegular(bRegular);
259 myLCB.Append(aCB);
260 }
261}
262//=======================================================================
263//function : SplitBlock
264//purpose :
265//=======================================================================
266void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB)
267{
268 Standard_Integer aNbLF, aNbOff, aNbFP;
269 Standard_Integer i;
270 TopAbs_Orientation anOr;
271 TopoDS_Edge aEL;
272 BRep_Builder aBB;
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;
279 //
280 Handle (BOPInt_Context) aContext=new BOPInt_Context;
281 //
282 const BOPCol_ListOfShape& myShapes=aCB.Shapes();
283 //
284 BOPCol_ListOfShape& myLoops=aCB.ChangeLoops();
285 myLoops.Clear();
286 //
287 // 1. Shells Usual
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);
293 }
294 //
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)) {
299 continue;
300 }
301 //
302 // make a new shell
303 TopoDS_Shell aShell;
304 aBB.MakeShell(aShell);
305 aBB.Add(aShell, aFF);
306 //
307 aMEFP.Clear();
308 BOPTools::MapShapesAndAncestors(aFF,
309 TopAbs_EDGE, TopAbs_FACE,
310 aMEFP);
311 //
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()));
317 //
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()));
322 //
323 //1
324 if (aMEFP.Contains(aE)) {
325 const BOPCol_ListOfShape& aLFP=aMEFP.FindFromKey(aE);
326 aNbFP=aLFP.Extent();
327 if (aNbFP>1) {
328 continue;
329 }
330 }
331 //2
332 anOr=aE.Orientation();
333 if (anOr==TopAbs_INTERNAL) {
334 continue;
335 }
336 //3
337 if (BRep_Tool::Degenerated(aE)) {
338 continue;
339 }
340 //
341 // candidate faces list
342 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
343 aNbLF=aLF.Extent();
344 if (!aNbLF) {
345 continue;
346 }
347 //
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;
353 //
354 aItLF.Initialize(aLF);
355 for (; aItLF.More(); aItLF.Next()) {
356 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aItLF.Value()));
357 if (aF.IsSame(aFL)) {
358 continue;
359 }
360 if (AddedFacesMap.Contains(aFL)){
361 continue;
362 }
363 //
364 bFound=BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL);
365 if (!bFound) {
366 continue;
367 }
368 //
369 aCSOff.SetShape1(aEL);
370 aCSOff.SetShape2(aFL);
371 aLCSOff.Append(aCSOff);
372 }//for (; aItLF.More(); aItLF.Next()) {
373 //
374 aNbOff=aLCSOff.Extent();
375 if (!aNbOff){
376 continue;
377 }
378 //
379 TopoDS_Face aSelF;
380 if (aNbOff==1) {
381 aSelF=(*(TopoDS_Face*)(&aLCSOff.First().Shape2()));
382 }
383 else if (aNbOff>1){
384 BOPTools_AlgoTools::GetFaceOff(aE, aF,
385 aLCSOff, aSelF, aContext);
386 }
387 //
388 if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) {
389 aBB.Add(aShell, aSelF);
390 BOPTools::MapShapesAndAncestors(aSelF,
391 TopAbs_EDGE, TopAbs_FACE,
392 aMEFP);
393 }
394 } // for (; aEdgeExp.More(); aEdgeExp.Next()) {
395 } //for (; aItAddedF.More(); aItAddedF.Next()) {
396 //
397 if (IsClosedShell(aShell)) {
398 myLoops.Append(aShell);
399 }
400 } // for (; aItF.More(); aItF.Next()) {
401}
402//=======================================================================
403//class : ShellSplitterFunctor
404//purpose : Auxiliary class
405//=======================================================================
406class BOPAlgo_ShellSplitterFunctor {
407 protected:
408 TopoDS_Face myFace;
409 BOPAlgo_ShellSplitter_VectorOfConnexityBlock* myPVCB;
410 //
411 public:
412 BOPAlgo_ShellSplitterFunctor
413 (BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB)
414 : myPVCB(&aVCB) {
415 }
416 //
417 void operator()( const flexible_range<Standard_Size>& aBR ) const{
418 Standard_Size i, iBeg, iEnd;
419 //
420 BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB=*myPVCB;
421 //
422 iBeg=aBR.begin();
423 iEnd=aBR.end();
424 for(i=iBeg; i!=iEnd; ++i) {
425 BOPTools_ConnexityBlock& aCB=aVCB((Standard_Integer)i);
426 //
427 BOPAlgo_ShellSplitter::SplitBlock(aCB);
428 }
429 }
430};
431//=======================================================================
432//class : BOPAlgo_ShellSplitterCnt
433//purpose : Auxiliary class
434//=======================================================================
435class BOPAlgo_ShellSplitterCnt {
436 public:
437 //-------------------------------
438 // Perform
439 Standard_EXPORT
440 static void Perform
441 (const Standard_Boolean bRunParallel,
442 BOPAlgo_ShellSplitter_VectorOfConnexityBlock& aVCB) {
443 //
444 BOPAlgo_ShellSplitterFunctor aSSF(aVCB);
445 Standard_Size aNbVCB=aVCB.Extent();
446 //
447 if (bRunParallel) {
448 flexible_for(flexible_range<Standard_Size>(0,aNbVCB), aSSF);
449 }
450 else {
451 aSSF.operator()(flexible_range<Standard_Size>(0,aNbVCB));
452 }
453 }
454};
455//=======================================================================
456//function : MMakeShells
457//purpose :
458//=======================================================================
459void BOPAlgo_ShellSplitter::MakeShells()
460{
461 Standard_Boolean bIsRegular;
462 Standard_Integer aNbVCB, k;
463 BOPTools_ListIteratorOfListOfConnexityBlock aItCB;
464 BOPCol_ListIteratorOfListOfShape aIt;
465 BOPAlgo_ShellSplitter_VectorOfConnexityBlock aVCB;
466 //
467 myErrorStatus=0;
468 myShells.Clear();
469 //
470 aItCB.Initialize(myLCB);
471 for (; aItCB.More(); aItCB.Next()) {
472 BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue();
473 bIsRegular=aCB.IsRegular();
474 if (bIsRegular) {
475 TopoDS_Shell aShell;
476 //
477 const BOPCol_ListOfShape& aLF=aCB.Shapes();
478 MakeShell(aLF, aShell);
479 myShells.Append(aShell);
480 }
481 else {
482 aVCB.Append(aCB);
483 }
484 }
485 //
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();
493 aIt.Initialize(aLS);
494 for (; aIt.More(); aIt.Next()) {
495 const TopoDS_Shape& aShell=aIt.Value();
496 myShells.Append(aShell);
497 }
498 }
499}
500//=======================================================================
501//function : IsClosedShell
502//purpose :
503//=======================================================================
504Standard_Boolean IsClosedShell(const TopoDS_Shell& theShell)
505{
506 Standard_Integer aNbE;
507 Standard_Boolean bRet;
508 TopoDS_Iterator aIt;
509 TopExp_Explorer aExp;
510 BOPCol_MapOfShape aM;
511 //
512 bRet=Standard_False;
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)) {
520 continue;
521 }
522 //
523 if (aE.Orientation()==TopAbs_INTERNAL) {
524 continue;
525 }
526 if (!aM.Add(aE)) {
527 aM.Remove(aE);
528 }
529 }
530 }
531 //
532 aNbE=aM.Extent();
533 if (!aNbE) {
534 bRet=!bRet;
535 }
536 return bRet;
537}
538//=======================================================================
539//function : MakeShell
540//purpose :
541//=======================================================================
542void MakeShell(const BOPCol_ListOfShape& aLS,
543 TopoDS_Shell& aShell)
544{
545 BRep_Builder aBB;
546 BOPCol_ListIteratorOfListOfShape aIt;
547 //
548 aBB.MakeShell(aShell);
549 //
550 aIt.Initialize(aLS);
551 for (; aIt.More(); aIt.Next()) {
552 const TopoDS_Shape& aF=aIt.Value();
553 aBB.Add(aShell, aF);
554 }
555}