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 |
682c9d06 |
17 | |
42cf5bc1 |
18 | #include <BOPAlgo_ShellSplitter.hxx> |
19 | #include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx> |
682c9d06 |
20 | #include <BOPCol_IndexedMapOfShape.hxx> |
682c9d06 |
21 | #include <BOPCol_MapOfOrientedShape.hxx> |
42cf5bc1 |
22 | #include <BOPCol_MapOfShape.hxx> |
682c9d06 |
23 | #include <BOPCol_NCVector.hxx> |
42cf5bc1 |
24 | #include <BOPCol_Parallel.hxx> |
682c9d06 |
25 | #include <BOPTools.hxx> |
26 | #include <BOPTools_AlgoTools.hxx> |
27 | #include <BOPTools_CoupleOfShape.hxx> |
42cf5bc1 |
28 | #include <BRep_Builder.hxx> |
29 | #include <IntTools_Context.hxx> |
30 | #include <TopExp_Explorer.hxx> |
093a3fe5 |
31 | #include <TopoDS.hxx> |
42cf5bc1 |
32 | #include <TopoDS_Edge.hxx> |
33 | #include <TopoDS_Shape.hxx> |
34 | #include <TopoDS_Shell.hxx> |
69b558c4 |
35 | |
69b558c4 |
36 | // |
682c9d06 |
37 | static |
38 | void MakeShell(const BOPCol_ListOfShape& , |
df80c6dd |
39 | TopoDS_Shell& ); |
69b558c4 |
40 | // |
41 | static |
a2ab2702 |
42 | void RefineShell(TopoDS_Shell& theShell, |
093a3fe5 |
43 | const BOPCol_IndexedDataMapOfShapeListOfShape& theMEF, |
a2ab2702 |
44 | BOPCol_ListOfShape& aLShX); |
0090ae85 |
45 | // |
46 | static |
47 | void MapEdgesAndFaces |
48 | (const TopoDS_Shape& aF, |
49 | BOPCol_IndexedDataMapOfShapeListOfShape& aMEF, |
50 | const Handle(NCollection_BaseAllocator)& theAllocator); |
682c9d06 |
51 | |
69b558c4 |
52 | //======================================================================= |
53 | //class : BOPAlgo_CBK |
54 | //purpose : |
55 | //======================================================================= |
56 | class 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 | //======================================================================= |
80 | typedef BOPCol_NCVector |
81 | <BOPAlgo_CBK> BOPAlgo_VectorOfCBK; |
82 | // |
c7b59798 |
83 | typedef BOPCol_Functor |
69b558c4 |
84 | <BOPAlgo_CBK, |
85 | BOPAlgo_VectorOfCBK> BOPAlgo_CBKFunctor; |
86 | // |
c7b59798 |
87 | typedef BOPCol_Cnt |
69b558c4 |
88 | <BOPAlgo_CBKFunctor, |
89 | BOPAlgo_VectorOfCBK> BOPAlgo_CBKCnt; |
90 | // |
682c9d06 |
91 | //======================================================================= |
92 | //function : |
93 | //purpose : |
94 | //======================================================================= |
95 | BOPAlgo_ShellSplitter::BOPAlgo_ShellSplitter() |
96 | : |
97 | BOPAlgo_Algo(), |
98 | myStartShapes(myAllocator), |
99 | myShells(myAllocator), |
100 | myLCB(myAllocator) |
101 | { |
102 | } |
103 | //======================================================================= |
104 | //function : |
105 | //purpose : |
106 | //======================================================================= |
107 | BOPAlgo_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 | //======================================================================= |
120 | BOPAlgo_ShellSplitter::~BOPAlgo_ShellSplitter() |
121 | { |
122 | } |
123 | //======================================================================= |
124 | //function : AddStartElement |
125 | //purpose : |
126 | //======================================================================= |
127 | void BOPAlgo_ShellSplitter::AddStartElement(const TopoDS_Shape& aE) |
128 | { |
129 | myStartShapes.Append(aE); |
130 | } |
131 | //======================================================================= |
132 | //function : StartElements |
133 | //purpose : |
134 | //======================================================================= |
135 | const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::StartElements()const |
136 | { |
137 | return myStartShapes; |
138 | } |
139 | //======================================================================= |
140 | //function : Loops |
141 | //purpose : |
142 | //======================================================================= |
143 | const BOPCol_ListOfShape& BOPAlgo_ShellSplitter::Shells()const |
144 | { |
145 | return myShells; |
146 | } |
147 | //======================================================================= |
148 | //function : Perform |
149 | //purpose : |
150 | //======================================================================= |
151 | void 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 | //======================================================================= |
166 | void BOPAlgo_ShellSplitter::MakeConnexityBlocks() |
167 | { |
168 | Standard_Boolean bRegular; |
169 | Standard_Integer i, j, aNbE, aNbES, aNbEP, k, aNbCB; |
170 | TopoDS_Shape aFR; |
0090ae85 |
171 | TopoDS_Iterator aItF, aItW; |
682c9d06 |
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); |
0090ae85 |
191 | MapEdgesAndFaces(aSE, aMEF, myAllocator); |
682c9d06 |
192 | } |
193 | else { |
194 | aMER.Add(aSE); |
195 | } |
196 | } |
197 | // |
198 | // 2 |
199 | aNbE=aMEF.Extent(); |
200 | for (i=1; i<=aNbE; ++i) { |
201 | aNbES=aMES.Extent(); |
202 | if (aNbES==aNbE) { |
203 | break; |
204 | } |
205 | // |
206 | const TopoDS_Shape& aE=aMEF.FindKey(i); |
207 | // |
208 | if (!aMES.Add(aE)) { |
209 | continue; |
210 | } |
211 | // aMES - globally processed edges |
212 | // |
213 | //------------------------------------- goal: aMEC |
214 | aMFC.Clear(); // aMEC - edges of CB |
215 | aMEP.Clear(); // aMVP - edges to process right now |
216 | aMEAdd.Clear(); // aMVAdd edges to process on next step of for(;;) { |
217 | // |
218 | aMEP.Add(aE); |
219 | // |
220 | for(;;) { |
221 | aNbEP=aMEP.Extent(); |
222 | for (k=1; k<=aNbEP; ++k) { |
223 | const TopoDS_Shape& aEP=aMEP(k); |
224 | const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aEP); |
225 | aIt.Initialize(aLF); |
226 | for (; aIt.More(); aIt.Next()) { |
227 | const TopoDS_Shape& aF=aIt.Value(); |
228 | if (aMFC.Add(aF)) { |
0090ae85 |
229 | aItF.Initialize(aF); |
230 | while (aItF.More()) { |
231 | const TopoDS_Shape& aW=aItF.Value(); |
232 | if (aW.ShapeType()!=TopAbs_WIRE) { |
233 | aItF.Next(); |
234 | continue; |
235 | } |
236 | // |
237 | aItW.Initialize(aW); |
238 | while (aItW.More()) { |
239 | const TopoDS_Shape& aEF=aItW.Value(); |
240 | // |
241 | if (aMES.Add(aEF)) { |
242 | aMEAdd.Add(aEF); |
243 | } |
244 | // |
245 | aItW.Next(); |
682c9d06 |
246 | } |
0090ae85 |
247 | // |
248 | aItF.Next(); |
682c9d06 |
249 | } |
250 | } |
251 | } |
252 | } |
253 | // |
254 | aNbEP=aMEAdd.Extent(); |
255 | if (!aNbEP) { |
256 | break; // from for(;;) { |
257 | } |
258 | // |
259 | aMEP.Clear(); |
260 | // |
261 | for (k=1; k<=aNbEP; ++k) { |
262 | const TopoDS_Shape& aEF=aMEAdd(k); |
263 | aMEP.Add(aEF); |
264 | } |
265 | aMEAdd.Clear(); |
266 | }// for(;;) { |
267 | // |
268 | //------------------------------------- |
269 | BOPTools_ConnexityBlock aCB(myAllocator); |
270 | // |
271 | BOPCol_ListOfShape& aLECB=aCB.ChangeShapes(); |
272 | BOPCol_IndexedDataMapOfShapeListOfShape aMEFR(100, myAllocator); |
273 | // |
274 | bRegular=Standard_True; |
275 | aNbCB = aMFC.Extent(); |
276 | for (j=1; j<=aNbCB; ++j) { |
277 | aFR = aMFC(j); |
278 | // |
279 | if (aMER.Contains(aFR)) { |
280 | aFR.Orientation(TopAbs_FORWARD); |
281 | aLECB.Append(aFR); |
282 | aFR.Orientation(TopAbs_REVERSED); |
283 | aLECB.Append(aFR); |
284 | bRegular=Standard_False; |
285 | } |
286 | else { |
287 | aLECB.Append(aFR); |
288 | } |
289 | // |
290 | if (bRegular) { |
0090ae85 |
291 | MapEdgesAndFaces(aFR, aMEFR, myAllocator); |
682c9d06 |
292 | } |
293 | } |
294 | // |
295 | if (bRegular) { |
296 | Standard_Integer aNbER, aNbFR; |
297 | // |
298 | aNbER=aMEFR.Extent(); |
299 | for (k=1; k<=aNbER; ++k) { |
300 | const BOPCol_ListOfShape& aLFR=aMEFR(k); |
301 | aNbFR=aLFR.Extent(); |
302 | if (aNbFR>2) { |
303 | bRegular=!bRegular; |
304 | break; |
305 | } |
306 | } |
307 | } |
308 | // |
309 | aCB.SetRegular(bRegular); |
310 | myLCB.Append(aCB); |
311 | } |
312 | } |
313 | //======================================================================= |
314 | //function : SplitBlock |
315 | //purpose : |
316 | //======================================================================= |
317 | void BOPAlgo_ShellSplitter::SplitBlock(BOPTools_ConnexityBlock& aCB) |
318 | { |
319 | Standard_Integer aNbLF, aNbOff, aNbFP; |
320 | Standard_Integer i; |
321 | TopAbs_Orientation anOr; |
322 | TopoDS_Edge aEL; |
323 | BRep_Builder aBB; |
324 | TopoDS_Iterator aItS; |
325 | TopExp_Explorer aExp; |
326 | BOPCol_ListIteratorOfListOfShape aItF; |
327 | BOPTools_CoupleOfShape aCSOff; |
328 | BOPCol_MapOfOrientedShape AddedFacesMap; |
329 | BOPCol_IndexedDataMapOfShapeListOfShape aEFMap, aMEFP; |
a2ab2702 |
330 | Handle (IntTools_Context) aContext; |
682c9d06 |
331 | // |
a2ab2702 |
332 | aContext=new IntTools_Context; |
682c9d06 |
333 | // |
334 | const BOPCol_ListOfShape& myShapes=aCB.Shapes(); |
335 | // |
336 | BOPCol_ListOfShape& myLoops=aCB.ChangeLoops(); |
337 | myLoops.Clear(); |
338 | // |
093a3fe5 |
339 | // Copy faces into the map, for recursive search of free bounds |
340 | BOPCol_MapOfOrientedShape aMFaces; |
682c9d06 |
341 | aItF.Initialize (myShapes); |
342 | for (; aItF.More(); aItF.Next()) { |
093a3fe5 |
343 | aMFaces.Add(aItF.Value()); |
682c9d06 |
344 | } |
345 | // |
093a3fe5 |
346 | // remove the faces with free edges from processing |
347 | for (;;) { |
348 | // map the shapes |
349 | aEFMap.Clear(); |
350 | aItF.Initialize(myShapes); |
351 | for (; aItF.More(); aItF.Next()) { |
352 | const TopoDS_Shape& aF = aItF.Value(); |
353 | if (aMFaces.Contains(aF)) { |
354 | BOPTools::MapShapesAndAncestors (aF, TopAbs_EDGE, TopAbs_FACE, aEFMap); |
355 | } |
356 | } |
357 | // |
358 | Standard_Integer aNbBegin = aMFaces.Extent(); |
359 | // check the free edges |
360 | Standard_Integer aNbE = aEFMap.Extent(); |
361 | for (i = 1; i <= aNbE; ++i) { |
362 | const TopoDS_Edge& aE = TopoDS::Edge(aEFMap.FindKey(i)); |
363 | if (!(BRep_Tool::Degenerated(aE) || aE.Orientation() == TopAbs_INTERNAL)) { |
364 | const BOPCol_ListOfShape& aLF = aEFMap(i); |
365 | if (aLF.Extent() == 1) { |
366 | // remove the face |
367 | aMFaces.Remove(aLF.First()); |
368 | } |
369 | } |
370 | } |
371 | // |
372 | // check if any faces have been removed |
373 | Standard_Integer aNbEnd = aMFaces.Extent(); |
374 | if ((aNbEnd == aNbBegin) || (aNbEnd == 0)) { |
375 | break; |
376 | } |
377 | } |
378 | // |
379 | if (aMFaces.IsEmpty()) { |
380 | return; |
381 | } |
382 | // |
383 | // use only connected faces |
384 | BOPCol_ListOfShape aLFConnected; |
682c9d06 |
385 | aItF.Initialize (myShapes); |
093a3fe5 |
386 | for (; aItF.More(); aItF.Next()) { |
387 | const TopoDS_Shape& aF = aItF.Value(); |
388 | if (aMFaces.Contains(aF)) { |
389 | aLFConnected.Append(aF); |
390 | } |
391 | } |
392 | // |
393 | const Standard_Integer aNbShapes = aLFConnected.Extent(); |
394 | Standard_Boolean bAllFacesTaken = Standard_False; |
395 | // |
396 | // Build the shells |
397 | aItF.Initialize (aLFConnected); |
398 | for (i = 1; aItF.More() && !bAllFacesTaken; aItF.Next(), ++i) { |
682c9d06 |
399 | const TopoDS_Shape& aFF = aItF.Value(); |
400 | if (!AddedFacesMap.Add(aFF)) { |
401 | continue; |
402 | } |
403 | // |
404 | // make a new shell |
093a3fe5 |
405 | TopoDS_Shell aShellStart; |
406 | aBB.MakeShell(aShellStart); |
407 | aBB.Add(aShellStart, aFF); |
682c9d06 |
408 | // |
093a3fe5 |
409 | BOPCol_ListOfShape aLShells; |
410 | aLShells.Append(aShellStart); |
682c9d06 |
411 | // |
093a3fe5 |
412 | BOPCol_ListIteratorOfListOfShape aItLShells(aLShells); |
413 | for (; aItLShells.More(); aItLShells.Next()) { |
414 | TopoDS_Shell& aShell = TopoDS::Shell(aItLShells.ChangeValue()); |
682c9d06 |
415 | // |
093a3fe5 |
416 | aMEFP.Clear(); |
417 | BOPTools::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEFP); |
418 | // |
419 | // loop on faces added to Shell; |
420 | // add their neighbor faces to Shell and so on |
421 | aItS.Initialize(aShell); |
422 | for (; aItS.More(); aItS.Next()) { |
423 | const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value())); |
682c9d06 |
424 | // |
093a3fe5 |
425 | // loop on edges of aF; find a good neighbor face of aF by aE |
426 | aExp.Init(aF, TopAbs_EDGE); |
427 | for (; aExp.More(); aExp.Next()) { |
428 | const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current())); |
429 | // |
430 | // proceed only free edges in this shell |
431 | if (aMEFP.Contains(aE)) { |
432 | const BOPCol_ListOfShape& aLFP = aMEFP.FindFromKey(aE); |
433 | aNbFP = aLFP.Extent(); |
434 | if (aNbFP > 1) { |
435 | continue; |
436 | } |
437 | } |
438 | // avoid processing of internal edges |
439 | anOr = aE.Orientation(); |
440 | if (anOr == TopAbs_INTERNAL) { |
682c9d06 |
441 | continue; |
442 | } |
093a3fe5 |
443 | // avoid processing of degenerated edges |
444 | if (BRep_Tool::Degenerated(aE)) { |
682c9d06 |
445 | continue; |
093a3fe5 |
446 | } |
447 | // |
448 | // candidate faces list |
449 | const BOPCol_ListOfShape& aLF = aEFMap.FindFromKey(aE); |
450 | aNbLF = aLF.Extent(); |
451 | if (!aNbLF) { |
682c9d06 |
452 | continue; |
453 | } |
454 | // |
093a3fe5 |
455 | // prepare for selecting the next face |
456 | // take only not-processed faces as a candidates |
457 | BOPTools_ListOfCoupleOfShape aLCSOff; |
458 | // |
459 | BOPCol_ListIteratorOfListOfShape aItLF(aLF); |
460 | for (; aItLF.More(); aItLF.Next()) { |
461 | const TopoDS_Face& aFL = (*(TopoDS_Face*)(&aItLF.Value())); |
462 | if (aF.IsSame(aFL) || AddedFacesMap.Contains(aFL)) { |
463 | continue; |
464 | } |
465 | // |
466 | // find current edge in the face |
467 | if (!BOPTools_AlgoTools::GetEdgeOff(aE, aFL, aEL)) { |
468 | continue; |
469 | } |
470 | // |
471 | aCSOff.SetShape1(aEL); |
472 | aCSOff.SetShape2(aFL); |
473 | aLCSOff.Append(aCSOff); |
474 | }//for (; aItLF.More(); aItLF.Next()) { |
475 | // |
476 | aNbOff = aLCSOff.Extent(); |
477 | if (!aNbOff){ |
682c9d06 |
478 | continue; |
479 | } |
480 | // |
093a3fe5 |
481 | // among all the adjacent faces chose one with the minimal |
482 | // angle to the current one |
483 | TopoDS_Face aSelF; |
484 | if (aNbOff == 1) { |
485 | aSelF = (*(TopoDS_Face*)(&aLCSOff.First().Shape2())); |
486 | } |
487 | else if (aNbOff > 1) { |
488 | BOPTools_AlgoTools::GetFaceOff(aE, aF, aLCSOff, aSelF, aContext); |
489 | } |
490 | // |
491 | if (!aSelF.IsNull() && AddedFacesMap.Add(aSelF)) { |
492 | aBB.Add(aShell, aSelF); |
493 | BOPTools::MapShapesAndAncestors(aSelF, TopAbs_EDGE, TopAbs_FACE, aMEFP); |
494 | } |
495 | } // for (; aExp.More(); aExp.Next()) { |
496 | } // for (; aItS.More(); aItS.Next()) { |
497 | // |
498 | // split the shell on multi-connected edges |
499 | BOPCol_ListOfShape aLShSp; |
500 | RefineShell(aShell, aMEFP, aLShSp); |
501 | // |
502 | // collect the not closed shells for further processing |
503 | BOPCol_ListOfShape aLShNC; |
504 | // |
505 | BOPCol_ListIteratorOfListOfShape aItLShSp(aLShSp); |
506 | for (; aItLShSp.More(); aItLShSp.Next()) { |
507 | TopoDS_Shell& aShSp = *((TopoDS_Shell*)&aItLShSp.Value()); |
682c9d06 |
508 | // |
093a3fe5 |
509 | if (BRep_Tool::IsClosed(aShSp)) { |
510 | aShSp.Closed(Standard_True); |
511 | myLoops.Append(aShSp); |
682c9d06 |
512 | } |
093a3fe5 |
513 | else { |
514 | aLShNC.Append(aShSp); |
682c9d06 |
515 | } |
093a3fe5 |
516 | } |
517 | // |
518 | bAllFacesTaken = (AddedFacesMap.Extent() == aNbShapes); |
519 | if (bAllFacesTaken) { |
520 | break; |
521 | } |
522 | // |
523 | if (aLShSp.Extent() == 1) { |
524 | // not further processing of not closed shells is needed, |
525 | // as it will not bring any new results |
526 | continue; |
527 | } |
a2ab2702 |
528 | // |
093a3fe5 |
529 | Standard_Integer aNbShNC = aLShNC.Extent(); |
530 | if (aNbShNC == 1) { |
531 | // try to complete the shell with other faces |
532 | aLShells.Append(aLShNC); |
533 | } |
534 | else if (aNbShNC > 1) { |
535 | // remove th faces of not closed shells from the map of processed faces |
536 | // and try to rebuild the shells using all not processed faces, |
537 | // because faces of one shell might be needed for building the other |
538 | BOPCol_ListIteratorOfListOfShape aItLShNC(aLShNC); |
539 | for (; aItLShNC.More(); aItLShNC.Next()) { |
540 | TopoDS_Iterator aItNC(aItLShNC.Value()); |
541 | for (; aItNC.More(); aItNC.Next()) { |
542 | AddedFacesMap.Remove(aItNC.Value()); |
543 | } |
544 | } |
69b558c4 |
545 | } |
546 | } |
682c9d06 |
547 | } // for (; aItF.More(); aItF.Next()) { |
548 | } |
549 | //======================================================================= |
69b558c4 |
550 | //function : RefineShell |
551 | //purpose : |
682c9d06 |
552 | //======================================================================= |
093a3fe5 |
553 | void RefineShell(TopoDS_Shell& theShell, |
554 | const BOPCol_IndexedDataMapOfShapeListOfShape& theMEF, |
555 | BOPCol_ListOfShape& theLShSp) |
69b558c4 |
556 | { |
093a3fe5 |
557 | TopoDS_Iterator aIt(theShell); |
69b558c4 |
558 | if(!aIt.More()) { |
559 | return; |
682c9d06 |
560 | } |
561 | // |
093a3fe5 |
562 | // Find edges with more than 2 adjacent faces - branch edges - |
563 | // edges on which the input shell should be split |
564 | BOPCol_MapOfShape aMEStop; |
69b558c4 |
565 | // |
093a3fe5 |
566 | Standard_Integer i, aNbMEF = theMEF.Extent(); |
567 | for (i = 1; i <= aNbMEF; ++i) { |
568 | const TopoDS_Edge& aE = TopoDS::Edge(theMEF.FindKey(i)); |
569 | const BOPCol_ListOfShape& aLF = theMEF(i); |
570 | if (aLF.Extent() > 2) { |
571 | aMEStop.Add(aE); |
572 | continue; |
573 | } |
574 | // |
575 | // check for internal edges - count faces, in which the edge |
576 | // is internal, twice |
577 | Standard_Integer aNbF = 0; |
578 | BOPCol_ListIteratorOfListOfShape aItLF(aLF); |
579 | for (; aItLF.More() && aNbF <= 2; aItLF.Next()) { |
580 | const TopoDS_Face& aF = TopoDS::Face(aItLF.Value()); |
581 | ++aNbF; |
582 | TopExp_Explorer aExp(aF, TopAbs_EDGE); |
583 | for (; aExp.More(); aExp.Next()) { |
584 | const TopoDS_Shape& aEF = aExp.Current(); |
585 | if (aEF.IsSame(aE)) { |
586 | if (aEF.Orientation() == TopAbs_INTERNAL) { |
587 | ++aNbF; |
588 | } |
589 | break; |
590 | } |
591 | } |
592 | } |
593 | // |
594 | if (aNbF > 2) { |
69b558c4 |
595 | aMEStop.Add(aE); |
596 | } |
597 | } |
598 | // |
599 | if (aMEStop.IsEmpty()) { |
093a3fe5 |
600 | theLShSp.Append(theShell); |
69b558c4 |
601 | return; |
602 | } |
603 | // |
093a3fe5 |
604 | TopoDS_Builder aBB; |
605 | TopExp_Explorer aExp; |
606 | BOPCol_IndexedMapOfShape aMFB; |
607 | BOPCol_MapOfOrientedShape aMFProcessed; |
608 | BOPCol_ListOfShape aLFP, aLFP1; |
609 | BOPCol_ListIteratorOfListOfShape aItLF, aItLFP; |
610 | // |
611 | // The first Face |
a2ab2702 |
612 | for (; aIt.More(); aIt.Next()) { |
093a3fe5 |
613 | const TopoDS_Shape& aF1 = aIt.Value(); |
a2ab2702 |
614 | if (!aMFProcessed.Add(aF1)) { |
615 | continue; |
616 | } |
617 | // |
618 | aMFB.Clear(); |
619 | aLFP.Clear(); |
620 | // |
621 | aMFB.Add(aF1); |
622 | aLFP.Append(aF1); |
623 | // |
624 | // Trying to reach the branch point |
0f04f1e1 |
625 | for (;;) { |
a2ab2702 |
626 | aItLFP.Initialize(aLFP); |
093a3fe5 |
627 | for (; aItLFP.More(); aItLFP.Next()) { |
628 | const TopoDS_Shape& aFP = aItLFP.Value(); |
69b558c4 |
629 | // |
a2ab2702 |
630 | aExp.Init(aFP, TopAbs_EDGE); |
631 | for (; aExp.More(); aExp.Next()) { |
093a3fe5 |
632 | const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current())); |
a2ab2702 |
633 | if (aMEStop.Contains(aE)) { |
69b558c4 |
634 | continue; |
635 | } |
a2ab2702 |
636 | // |
0f04f1e1 |
637 | if (aE.Orientation() == TopAbs_INTERNAL) { |
638 | continue; |
639 | } |
640 | // |
a2ab2702 |
641 | if (BRep_Tool::Degenerated(aE)) { |
69b558c4 |
642 | continue; |
643 | } |
a2ab2702 |
644 | // |
093a3fe5 |
645 | const BOPCol_ListOfShape& aLF = theMEF.FindFromKey(aE); |
a2ab2702 |
646 | // |
647 | aItLF.Initialize(aLF); |
093a3fe5 |
648 | for (; aItLF.More(); aItLF.Next()) { |
649 | const TopoDS_Shape& aFP1 = aItLF.Value(); |
a2ab2702 |
650 | if (aFP1.IsSame(aFP)) { |
651 | continue; |
652 | } |
653 | if (aMFB.Contains(aFP1)) { |
654 | continue; |
655 | } |
656 | // |
093a3fe5 |
657 | if (aMFProcessed.Add(aFP1)) { |
658 | aMFB.Add(aFP1); |
659 | aLFP1.Append(aFP1); |
660 | } |
a2ab2702 |
661 | }// for (; aItLF.More(); aItLF.Next()) { |
662 | }// for (; aExp.More(); aExp.Next()) { |
663 | } // for (; aItLFP.More(); aItLFP.Next()) { |
664 | // |
665 | // |
666 | if (aLFP1.IsEmpty()) { |
667 | break; |
668 | } |
669 | // |
670 | aLFP.Clear(); |
093a3fe5 |
671 | aLFP.Append(aLFP1); |
0f04f1e1 |
672 | }// for (;;) { |
69b558c4 |
673 | // |
093a3fe5 |
674 | Standard_Integer aNbMFB = aMFB.Extent(); |
a2ab2702 |
675 | if (aNbMFB) { |
093a3fe5 |
676 | TopoDS_Shell aShSp; |
677 | aBB.MakeShell(aShSp); |
a2ab2702 |
678 | // |
093a3fe5 |
679 | for (i = 1; i <= aNbMFB; ++i) { |
680 | const TopoDS_Shape& aFB = aMFB(i); |
681 | aBB.Add(aShSp, aFB); |
a2ab2702 |
682 | } |
093a3fe5 |
683 | theLShSp.Append(aShSp); |
682c9d06 |
684 | } |
a2ab2702 |
685 | }//for (; aIt.More(); aIt.Next()) { |
0f04f1e1 |
686 | } |
682c9d06 |
687 | //======================================================================= |
69b558c4 |
688 | //function : MakeShells |
682c9d06 |
689 | //purpose : |
690 | //======================================================================= |
691 | void BOPAlgo_ShellSplitter::MakeShells() |
692 | { |
693 | Standard_Boolean bIsRegular; |
69b558c4 |
694 | Standard_Integer aNbVCBK, k; |
682c9d06 |
695 | BOPTools_ListIteratorOfListOfConnexityBlock aItCB; |
696 | BOPCol_ListIteratorOfListOfShape aIt; |
69b558c4 |
697 | BOPAlgo_VectorOfCBK aVCBK; |
682c9d06 |
698 | // |
699 | myErrorStatus=0; |
700 | myShells.Clear(); |
701 | // |
702 | aItCB.Initialize(myLCB); |
703 | for (; aItCB.More(); aItCB.Next()) { |
704 | BOPTools_ConnexityBlock& aCB=aItCB.ChangeValue(); |
705 | bIsRegular=aCB.IsRegular(); |
706 | if (bIsRegular) { |
707 | TopoDS_Shell aShell; |
708 | // |
709 | const BOPCol_ListOfShape& aLF=aCB.Shapes(); |
710 | MakeShell(aLF, aShell); |
ab860031 |
711 | aShell.Closed(Standard_True); |
682c9d06 |
712 | myShells.Append(aShell); |
713 | } |
714 | else { |
69b558c4 |
715 | BOPAlgo_CBK& aCBK=aVCBK.Append1(); |
716 | aCBK.SetConnexityBlock(aCB); |
682c9d06 |
717 | } |
718 | } |
719 | // |
69b558c4 |
720 | aNbVCBK=aVCBK.Extent(); |
682c9d06 |
721 | //=================================================== |
69b558c4 |
722 | BOPAlgo_CBKCnt::Perform(myRunParallel, aVCBK); |
682c9d06 |
723 | //=================================================== |
69b558c4 |
724 | for (k=0; k<aNbVCBK; ++k) { |
725 | BOPAlgo_CBK& aCBK=aVCBK(k); |
726 | const BOPTools_ConnexityBlock& aCB=aCBK.ConnexityBlock(); |
682c9d06 |
727 | const BOPCol_ListOfShape& aLS=aCB.Loops(); |
728 | aIt.Initialize(aLS); |
729 | for (; aIt.More(); aIt.Next()) { |
ab860031 |
730 | TopoDS_Shape& aShell=aIt.ChangeValue(); |
731 | aShell.Closed(Standard_True); |
682c9d06 |
732 | myShells.Append(aShell); |
733 | } |
734 | } |
735 | } |
736 | //======================================================================= |
682c9d06 |
737 | //function : MakeShell |
738 | //purpose : |
739 | //======================================================================= |
740 | void MakeShell(const BOPCol_ListOfShape& aLS, |
df80c6dd |
741 | TopoDS_Shell& aShell) |
682c9d06 |
742 | { |
743 | BRep_Builder aBB; |
744 | BOPCol_ListIteratorOfListOfShape aIt; |
745 | // |
746 | aBB.MakeShell(aShell); |
747 | // |
748 | aIt.Initialize(aLS); |
749 | for (; aIt.More(); aIt.Next()) { |
750 | const TopoDS_Shape& aF=aIt.Value(); |
751 | aBB.Add(aShell, aF); |
752 | } |
6fd4ffd9 |
753 | // |
754 | BOPTools_AlgoTools::OrientFacesOnShell(aShell); |
682c9d06 |
755 | } |
0090ae85 |
756 | //======================================================================= |
757 | // function: MapEdgesAndFaces |
758 | // purpose: |
759 | //======================================================================= |
760 | void MapEdgesAndFaces |
761 | (const TopoDS_Shape& aF, |
762 | BOPCol_IndexedDataMapOfShapeListOfShape& aMEF, |
763 | const Handle(NCollection_BaseAllocator)& theAllocator) |
764 | { |
765 | TopoDS_Iterator aItF, aItW; |
766 | // |
767 | aItF.Initialize(aF); |
768 | while (aItF.More()) { |
769 | const TopoDS_Shape& aW=aItF.Value(); |
770 | if (aW.ShapeType()!=TopAbs_WIRE) { |
771 | aItF.Next(); |
772 | continue; |
773 | } |
774 | // |
775 | aItW.Initialize(aW); |
776 | while (aItW.More()) { |
777 | const TopoDS_Shape& aE=aItW.Value(); |
778 | // |
779 | if (aMEF.Contains(aE)) { |
780 | BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE); |
781 | aLF.Append(aF); |
782 | } |
783 | else { |
784 | BOPCol_ListOfShape aLS(theAllocator); |
785 | // |
786 | aLS.Append(aF); |
787 | aMEF.Add(aE, aLS); |
788 | } |
789 | // |
790 | aItW.Next(); |
791 | } |
792 | // |
793 | aItF.Next(); |
794 | } |
795 | } |