4e57c75e |
1 | // Created by: Peter KURNEV |
973c2be1 |
2 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
4e57c75e |
3 | // |
973c2be1 |
4 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
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 |
973c2be1 |
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. |
4e57c75e |
11 | // |
973c2be1 |
12 | // Alternatively, this file may be used under the terms of Open CASCADE |
13 | // commercial license or contractual agreement. |
4e57c75e |
14 | |
4e57c75e |
15 | |
42cf5bc1 |
16 | #include <BOPAlgo_BOP.hxx> |
17 | #include <BOPAlgo_BuilderSolid.hxx> |
18 | #include <BOPAlgo_PaveFiller.hxx> |
977ad983 |
19 | #include <BOPAlgo_Tools.hxx> |
33ba8565 |
20 | #include <BOPAlgo_Alerts.hxx> |
8620e18d |
21 | #include <BOPDS_DS.hxx> |
4e57c75e |
22 | #include <BOPTools_AlgoTools.hxx> |
23 | #include <BOPTools_AlgoTools3D.hxx> |
1155d05a |
24 | #include <BOPTools_IndexedDataMapOfSetShape.hxx> |
955b3e71 |
25 | #include <BOPTools_Set.hxx> |
26 | #include <BOPTools_SetMapHasher.hxx> |
42cf5bc1 |
27 | #include <BRep_Builder.hxx> |
28 | #include <BRep_Tool.hxx> |
955b3e71 |
29 | #include <NCollection_DataMap.hxx> |
42cf5bc1 |
30 | #include <TopAbs_ShapeEnum.hxx> |
1155d05a |
31 | #include <TopExp.hxx> |
42cf5bc1 |
32 | #include <TopExp_Explorer.hxx> |
13c0e402 |
33 | #include <TopoDS.hxx> |
42cf5bc1 |
34 | #include <TopoDS_Compound.hxx> |
35 | #include <TopoDS_Edge.hxx> |
36 | #include <TopoDS_Iterator.hxx> |
37 | #include <TopoDS_Shape.hxx> |
1155d05a |
38 | #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx> |
39 | #include <TopTools_IndexedMapOfShape.hxx> |
40 | #include <TopTools_ListOfShape.hxx> |
41 | #include <TopTools_MapOfShape.hxx> |
955b3e71 |
42 | |
4e57c75e |
43 | static |
44 | TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim); |
9526aa6a |
45 | // |
46 | static |
47 | void CollectContainers(const TopoDS_Shape& theS, |
1155d05a |
48 | TopTools_ListOfShape& theLSC); |
77a11d3d |
49 | // |
50 | static |
1155d05a |
51 | void RemoveDuplicates(TopTools_ListOfShape& theContainers); |
77a11d3d |
52 | // |
53 | static |
1155d05a |
54 | void RemoveDuplicates(TopTools_ListOfShape& theContainers, |
77a11d3d |
55 | const TopAbs_ShapeEnum theType); |
56 | // |
57 | static |
1155d05a |
58 | Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1, |
59 | const TopTools_MapOfShape& theM2); |
25dfc507 |
60 | // |
61 | static |
62 | void MapFacesToBuildSolids(const TopoDS_Shape& theSol, |
1155d05a |
63 | TopTools_IndexedDataMapOfShapeListOfShape& theMFS, |
64 | TopTools_IndexedMapOfShape& theMFI); |
8620e18d |
65 | |
4e57c75e |
66 | //======================================================================= |
67 | //function : |
68 | //purpose : |
69 | //======================================================================= |
8620e18d |
70 | BOPAlgo_BOP::BOPAlgo_BOP() |
5fbe3d01 |
71 | : BOPAlgo_ToolsProvider() |
4e57c75e |
72 | { |
4e57c75e |
73 | Clear(); |
74 | } |
75 | //======================================================================= |
76 | //function : |
77 | //purpose : |
78 | //======================================================================= |
5fbe3d01 |
79 | BOPAlgo_BOP::BOPAlgo_BOP(const Handle(NCollection_BaseAllocator)& theAllocator) |
80 | : BOPAlgo_ToolsProvider(theAllocator) |
4e57c75e |
81 | { |
4e57c75e |
82 | Clear(); |
83 | } |
84 | //======================================================================= |
85 | //function : ~ |
86 | //purpose : |
87 | //======================================================================= |
8620e18d |
88 | BOPAlgo_BOP::~BOPAlgo_BOP() |
4e57c75e |
89 | { |
90 | } |
91 | //======================================================================= |
92 | //function : Clear |
93 | //purpose : |
94 | //======================================================================= |
8620e18d |
95 | void BOPAlgo_BOP::Clear() |
4e57c75e |
96 | { |
97 | myOperation=BOPAlgo_UNKNOWN; |
4e57c75e |
98 | myDims[0]=-1; |
99 | myDims[1]=-1; |
5fbe3d01 |
100 | |
101 | BOPAlgo_ToolsProvider::Clear(); |
4e57c75e |
102 | } |
103 | //======================================================================= |
8620e18d |
104 | //function : SetOperation |
4e57c75e |
105 | //purpose : |
106 | //======================================================================= |
8620e18d |
107 | void BOPAlgo_BOP::SetOperation(const BOPAlgo_Operation theOperation) |
4e57c75e |
108 | { |
8620e18d |
109 | myOperation=theOperation; |
4e57c75e |
110 | } |
111 | //======================================================================= |
8620e18d |
112 | //function : Operation |
4e57c75e |
113 | //purpose : |
114 | //======================================================================= |
8620e18d |
115 | BOPAlgo_Operation BOPAlgo_BOP::Operation()const |
4e57c75e |
116 | { |
8620e18d |
117 | return myOperation; |
4e57c75e |
118 | } |
119 | //======================================================================= |
4e57c75e |
120 | //function : CheckData |
121 | //purpose : |
122 | //======================================================================= |
8620e18d |
123 | void BOPAlgo_BOP::CheckData() |
4e57c75e |
124 | { |
8620e18d |
125 | Standard_Integer i, j, iDim, aNbArgs, aNbTools; |
33ba8565 |
126 | Standard_Boolean bFuse; |
1155d05a |
127 | TopTools_ListIteratorOfListOfShape aItLS; |
4e57c75e |
128 | // |
85915310 |
129 | if (!(myOperation==BOPAlgo_COMMON || |
130 | myOperation==BOPAlgo_FUSE || |
131 | myOperation==BOPAlgo_CUT|| |
132 | myOperation==BOPAlgo_CUT21)) { |
133 | // non-licit operation |
33ba8565 |
134 | AddError (new BOPAlgo_AlertBOPNotSet); |
85915310 |
135 | return; |
136 | } |
137 | // |
8620e18d |
138 | aNbArgs=myArguments.Extent(); |
139 | if (!aNbArgs) { |
85915310 |
140 | // invalid number of Arguments |
33ba8565 |
141 | AddError (new BOPAlgo_AlertTooFewArguments); |
8620e18d |
142 | return; |
143 | } |
144 | // |
145 | aNbTools=myTools.Extent(); |
85915310 |
146 | if (!aNbTools) { |
147 | // invalid number of Tools |
33ba8565 |
148 | AddError (new BOPAlgo_AlertTooFewArguments); |
4e57c75e |
149 | return; |
150 | } |
151 | // |
33ba8565 |
152 | CheckFiller(); |
153 | if (HasErrors()) { |
4e57c75e |
154 | return; |
155 | } |
156 | // |
9526aa6a |
157 | bFuse = (myOperation == BOPAlgo_FUSE); |
158 | // |
159 | // The rules for different types of operations are the following: |
160 | // 1. FUSE: All arguments and tools should have the same dimension; |
161 | // 2. CUT: The MAXIMAL dimension of the ARGUMENTS should be less |
162 | // or equal to the MINIMAL dimension of the TOOLS; |
163 | // 3. CUT21: The MINIMAL dimension of ARGUMENTS should be grater |
164 | // or equal to the MAXIMAL dimension of the TOOLS; |
165 | // 4. COMMON: The arguments and tools could have any dimensions. |
166 | // |
3dc58095 |
167 | Standard_Integer iDimMin[2] = { 0, 0 }, iDimMax[2] = { 0, 0 }; |
33ba8565 |
168 | Standard_Boolean bHasValid[2] = {Standard_False, Standard_False}; |
9526aa6a |
169 | // |
8620e18d |
170 | for (i=0; i<2; ++i) { |
1155d05a |
171 | const TopTools_ListOfShape& aLS=(!i)? myArguments : myTools; |
8620e18d |
172 | aItLS.Initialize(aLS); |
173 | for (j=0; aItLS.More(); aItLS.Next(), ++j) { |
174 | const TopoDS_Shape& aS=aItLS.Value(); |
33ba8565 |
175 | Standard_Boolean bIsEmpty = BOPTools_AlgoTools3D::IsEmptyShape(aS); |
176 | if (bIsEmpty) { |
177 | AddWarning(new BOPAlgo_AlertEmptyShape (aS)); |
178 | continue; |
8620e18d |
179 | } |
180 | // |
33ba8565 |
181 | iDim = BOPTools_AlgoTools::Dimension(aS); |
182 | if (iDim < 0) { |
183 | // non-homogeneous argument |
184 | AddError (new BOPAlgo_AlertBOPNotAllowed); |
8620e18d |
185 | return; |
186 | } |
187 | // |
33ba8565 |
188 | bHasValid[i] = Standard_True; |
189 | // |
8620e18d |
190 | if (!j) { |
9526aa6a |
191 | iDimMin[i] = iDim; |
192 | iDimMax[i] = iDim; |
8620e18d |
193 | continue; |
194 | } |
195 | // |
9526aa6a |
196 | if (iDim < iDimMin[i]) { |
197 | iDimMin[i] = iDim; |
198 | } |
199 | else if (iDim > iDimMax[i]) { |
200 | iDimMax[i] = iDim; |
201 | } |
202 | // |
203 | if (bFuse && (iDimMin[i] != iDimMax[i])) { |
33ba8565 |
204 | // non-homogeneous argument |
205 | AddError (new BOPAlgo_AlertBOPNotAllowed); |
8620e18d |
206 | return; |
207 | } |
4e57c75e |
208 | } |
209 | } |
210 | // |
33ba8565 |
211 | if (bHasValid[0] && bHasValid[1]) { |
212 | if (((myOperation == BOPAlgo_FUSE) && (iDimMax[0] != iDimMax[1])) || |
213 | ((myOperation == BOPAlgo_CUT) && (iDimMax[0] > iDimMin[1])) || |
214 | ((myOperation == BOPAlgo_CUT21) && (iDimMin[0] < iDimMax[1])) ) |
215 | { |
216 | // non-licit operation for the arguments |
217 | AddError (new BOPAlgo_AlertBOPNotAllowed); |
218 | return; |
219 | } |
3dc58095 |
220 | } |
221 | |
222 | if (bHasValid[0] || bHasValid[1]) |
223 | { |
224 | // In case of all empty shapes in one of the groups |
225 | // this group aquires the dimension of other group |
226 | myDims[0] = bHasValid[0] ? iDimMin[0] : iDimMin[1]; |
227 | myDims[1] = bHasValid[1] ? iDimMin[1] : iDimMin[0]; |
4e57c75e |
228 | } |
229 | } |
230 | //======================================================================= |
33ba8565 |
231 | //function : TreatEmtpyShape |
4e57c75e |
232 | //purpose : |
233 | //======================================================================= |
33ba8565 |
234 | Standard_Boolean BOPAlgo_BOP::TreatEmptyShape() |
4e57c75e |
235 | { |
33ba8565 |
236 | if (! GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape))) |
237 | { |
238 | return Standard_False; |
239 | } |
4e57c75e |
240 | // |
33ba8565 |
241 | // Find non-empty objects |
1155d05a |
242 | TopTools_ListOfShape aLValidObjs; |
243 | TopTools_ListIteratorOfListOfShape aItLS(myArguments); |
33ba8565 |
244 | for (; aItLS.More(); aItLS.Next()) { |
245 | if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) { |
246 | aLValidObjs.Append(aItLS.Value()); |
247 | } |
248 | } |
4e57c75e |
249 | // |
33ba8565 |
250 | // Find non-empty tools |
1155d05a |
251 | TopTools_ListOfShape aLValidTools; |
33ba8565 |
252 | aItLS.Initialize(myTools); |
253 | for (; aItLS.More() ; aItLS.Next()) { |
254 | if (!BOPTools_AlgoTools3D::IsEmptyShape(aItLS.Value())) { |
255 | aLValidTools.Append(aItLS.Value()); |
256 | } |
257 | } |
258 | // |
259 | Standard_Boolean bHasValidObj = (aLValidObjs .Extent() > 0); |
260 | Standard_Boolean bHasValidTool = (aLValidTools.Extent() > 0); |
261 | // |
262 | if (bHasValidObj && bHasValidTool) { |
263 | // We need to continue the operation to obtain the result |
264 | return Standard_False; |
265 | } |
266 | // |
267 | if (!bHasValidObj && !bHasValidTool) { |
268 | // All shapes are empty shapes, the result will always be empty shape |
269 | return Standard_True; |
8620e18d |
270 | } |
33ba8565 |
271 | // |
272 | // One of the groups of arguments consists of empty shapes only, |
273 | // so we can build the result of operation right away just by |
274 | // choosing the list of shapes to add to result, depending on |
3dc58095 |
275 | // the type of the operation. |
276 | // Although, if the group with valid shapes consists from more |
277 | // than just one shape, depending on the operation type we may need |
278 | // to split the shapes in this group before adding them into result. |
279 | |
1155d05a |
280 | TopTools_ListOfShape *pLResult = NULL; |
33ba8565 |
281 | // |
282 | switch (myOperation) { |
283 | case BOPAlgo_FUSE: |
3dc58095 |
284 | { |
285 | if (aLValidObjs.Extent() + aLValidTools.Extent() > 1) |
286 | // The arguments must be split before adding into result |
287 | return Standard_False; |
288 | |
33ba8565 |
289 | // Add not empty shapes into result |
290 | pLResult = bHasValidObj ? &aLValidObjs : &aLValidTools; |
291 | break; |
3dc58095 |
292 | } |
33ba8565 |
293 | case BOPAlgo_CUT: |
3dc58095 |
294 | { |
295 | if (aLValidObjs.Extent() > 1) |
296 | // The objects must be split before adding into result |
297 | return Standard_False; |
298 | |
33ba8565 |
299 | // Add objects into result |
300 | pLResult = &aLValidObjs; |
301 | break; |
3dc58095 |
302 | } |
33ba8565 |
303 | case BOPAlgo_CUT21: |
3dc58095 |
304 | { |
305 | if (aLValidTools.Extent() > 1) |
306 | // The tools must be split before adding into result |
307 | return Standard_False; |
308 | |
33ba8565 |
309 | // Add tools into result |
310 | pLResult = &aLValidTools; |
311 | break; |
3dc58095 |
312 | } |
33ba8565 |
313 | case BOPAlgo_COMMON: |
3dc58095 |
314 | // Common will always be empty |
33ba8565 |
315 | break; |
316 | default: |
317 | break; |
318 | } |
319 | // |
320 | if (pLResult) { |
321 | aItLS.Initialize(*pLResult); |
322 | for (; aItLS.More(); aItLS.Next()) { |
323 | BRep_Builder().Add(myShape, aItLS.Value()); |
324 | } |
325 | } |
326 | return Standard_True; |
8620e18d |
327 | } |
328 | //======================================================================= |
329 | //function : BuildResult |
330 | //purpose : |
331 | //======================================================================= |
332 | void BOPAlgo_BOP::BuildResult(const TopAbs_ShapeEnum theType) |
333 | { |
334 | TopAbs_ShapeEnum aType; |
335 | BRep_Builder aBB; |
1155d05a |
336 | TopTools_MapOfShape aM; |
337 | TopTools_ListIteratorOfListOfShape aIt, aItIm; |
8620e18d |
338 | // |
1155d05a |
339 | const TopTools_ListOfShape& aLA=myDS->Arguments(); |
8620e18d |
340 | aIt.Initialize(aLA); |
341 | for (; aIt.More(); aIt.Next()) { |
342 | const TopoDS_Shape& aS=aIt.Value(); |
343 | aType=aS.ShapeType(); |
344 | if (aType==theType) { |
345 | if (myImages.IsBound(aS)){ |
1155d05a |
346 | const TopTools_ListOfShape& aLSIm=myImages.Find(aS); |
8620e18d |
347 | aItIm.Initialize(aLSIm); |
348 | for (; aItIm.More(); aItIm.Next()) { |
349 | const TopoDS_Shape& aSIm=aItIm.Value(); |
350 | if (aM.Add(aSIm)) { |
351 | aBB.Add(myShape, aSIm); |
352 | } |
353 | } |
354 | } |
355 | else { |
356 | if (aM.Add(aS)) { |
357 | aBB.Add(myShape, aS); |
358 | } |
359 | } |
4e57c75e |
360 | } |
361 | } |
362 | } |
363 | //======================================================================= |
8620e18d |
364 | //function : Perform |
365 | //purpose : |
366 | //======================================================================= |
367 | void BOPAlgo_BOP::Perform() |
368 | { |
369 | Handle(NCollection_BaseAllocator) aAllocator; |
370 | BOPAlgo_PaveFiller* pPF; |
1155d05a |
371 | TopTools_ListIteratorOfListOfShape aItLS; |
8620e18d |
372 | // |
33ba8565 |
373 | GetReport()->Clear(); |
8620e18d |
374 | // |
375 | if (myEntryPoint==1) { |
376 | if (myPaveFiller) { |
377 | delete myPaveFiller; |
378 | myPaveFiller=NULL; |
379 | } |
380 | } |
381 | // |
488e5b9d |
382 | aAllocator= |
383 | NCollection_BaseAllocator::CommonBaseAllocator(); |
1155d05a |
384 | TopTools_ListOfShape aLS(aAllocator); |
8620e18d |
385 | // |
386 | aItLS.Initialize(myArguments); |
387 | for (; aItLS.More(); aItLS.Next()) { |
388 | const TopoDS_Shape& aS=aItLS.Value(); |
389 | aLS.Append(aS); |
390 | } |
391 | // |
392 | aItLS.Initialize(myTools); |
393 | for (; aItLS.More(); aItLS.Next()) { |
394 | const TopoDS_Shape& aS=aItLS.Value(); |
395 | aLS.Append(aS); |
396 | } |
397 | // |
398 | pPF=new BOPAlgo_PaveFiller(aAllocator); |
399 | pPF->SetArguments(aLS); |
b1d15f53 |
400 | pPF->SetRunParallel(myRunParallel); |
401 | pPF->SetProgressIndicator(myProgressIndicator); |
402 | pPF->SetFuzzyValue(myFuzzyValue); |
3510db62 |
403 | pPF->SetNonDestructive(myNonDestructive); |
483ce1bd |
404 | pPF->SetGlue(myGlue); |
944768d2 |
405 | pPF->SetUseOBB(myUseOBB); |
8620e18d |
406 | // |
407 | pPF->Perform(); |
408 | // |
409 | myEntryPoint=1; |
410 | PerformInternal(*pPF); |
411 | } |
412 | //======================================================================= |
36f4947b |
413 | //function : PerformInternal1 |
4e57c75e |
414 | //purpose : |
415 | //======================================================================= |
36f4947b |
416 | void BOPAlgo_BOP::PerformInternal1(const BOPAlgo_PaveFiller& theFiller) |
4e57c75e |
417 | { |
4e57c75e |
418 | myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller; |
419 | myDS=myPaveFiller->PDS(); |
420 | myContext=myPaveFiller->Context(); |
0d0481c7 |
421 | myFuzzyValue = myPaveFiller->FuzzyValue(); |
422 | myNonDestructive = myPaveFiller->NonDestructive(); |
4e57c75e |
423 | // |
424 | // 1. CheckData |
425 | CheckData(); |
33ba8565 |
426 | if (HasErrors()) { |
4e57c75e |
427 | return; |
428 | } |
429 | // |
430 | // 2. Prepare |
431 | Prepare(); |
33ba8565 |
432 | if (HasErrors()) { |
4e57c75e |
433 | return; |
434 | } |
8620e18d |
435 | // |
33ba8565 |
436 | if (GetReport()->HasAlert (STANDARD_TYPE(BOPAlgo_AlertEmptyShape))) |
437 | { |
438 | Standard_Boolean bDone = TreatEmptyShape(); |
439 | if (bDone) { |
3dc58095 |
440 | PrepareHistory(); |
33ba8565 |
441 | return; |
442 | } |
4e57c75e |
443 | } |
33ba8565 |
444 | // |
4e57c75e |
445 | // 3. Fill Images |
446 | // 3.1 Vertices |
447 | FillImagesVertices(); |
33ba8565 |
448 | if (HasErrors()) { |
4e57c75e |
449 | return; |
450 | } |
451 | // |
452 | BuildResult(TopAbs_VERTEX); |
33ba8565 |
453 | if (HasErrors()) { |
4e57c75e |
454 | return; |
455 | } |
456 | // 3.2 Edges |
457 | FillImagesEdges(); |
33ba8565 |
458 | if (HasErrors()) { |
4e57c75e |
459 | return; |
460 | } |
85915310 |
461 | // |
4e57c75e |
462 | BuildResult(TopAbs_EDGE); |
33ba8565 |
463 | if (HasErrors()) { |
4e57c75e |
464 | return; |
465 | } |
4e57c75e |
466 | // |
467 | // 3.3 Wires |
468 | FillImagesContainers(TopAbs_WIRE); |
33ba8565 |
469 | if (HasErrors()) { |
4e57c75e |
470 | return; |
471 | } |
85915310 |
472 | // |
4e57c75e |
473 | BuildResult(TopAbs_WIRE); |
33ba8565 |
474 | if (HasErrors()) { |
4e57c75e |
475 | return; |
476 | } |
85915310 |
477 | // |
4e57c75e |
478 | // 3.4 Faces |
479 | FillImagesFaces(); |
33ba8565 |
480 | if (HasErrors()) { |
4e57c75e |
481 | return; |
482 | } |
483 | |
484 | BuildResult(TopAbs_FACE); |
33ba8565 |
485 | if (HasErrors()) { |
4e57c75e |
486 | return; |
487 | } |
85915310 |
488 | // |
4e57c75e |
489 | // 3.5 Shells |
4e57c75e |
490 | FillImagesContainers(TopAbs_SHELL); |
33ba8565 |
491 | if (HasErrors()) { |
4e57c75e |
492 | return; |
493 | } |
85915310 |
494 | // |
4e57c75e |
495 | BuildResult(TopAbs_SHELL); |
33ba8565 |
496 | if (HasErrors()) { |
4e57c75e |
497 | return; |
498 | } |
85915310 |
499 | // |
4e57c75e |
500 | // 3.6 Solids |
501 | FillImagesSolids(); |
33ba8565 |
502 | if (HasErrors()) { |
4e57c75e |
503 | return; |
504 | } |
85915310 |
505 | // |
4e57c75e |
506 | BuildResult(TopAbs_SOLID); |
33ba8565 |
507 | if (HasErrors()) { |
4e57c75e |
508 | return; |
509 | } |
85915310 |
510 | // |
4e57c75e |
511 | // 3.7 CompSolids |
512 | FillImagesContainers(TopAbs_COMPSOLID); |
33ba8565 |
513 | if (HasErrors()) { |
4e57c75e |
514 | return; |
515 | } |
85915310 |
516 | // |
4e57c75e |
517 | BuildResult(TopAbs_COMPSOLID); |
33ba8565 |
518 | if (HasErrors()) { |
4e57c75e |
519 | return; |
520 | } |
85915310 |
521 | // |
4e57c75e |
522 | // 3.8 Compounds |
523 | FillImagesCompounds(); |
33ba8565 |
524 | if (HasErrors()) { |
4e57c75e |
525 | return; |
526 | } |
85915310 |
527 | // |
4e57c75e |
528 | BuildResult(TopAbs_COMPOUND); |
33ba8565 |
529 | if (HasErrors()) { |
4e57c75e |
530 | return; |
531 | } |
532 | // |
8620e18d |
533 | // 4.BuildShape; |
4e57c75e |
534 | BuildShape(); |
33ba8565 |
535 | if (HasErrors()) { |
8620e18d |
536 | return; |
537 | } |
4e57c75e |
538 | // |
8620e18d |
539 | // 5.History |
4e57c75e |
540 | PrepareHistory(); |
4e57c75e |
541 | // |
8620e18d |
542 | // 6 Post-treatment |
4e57c75e |
543 | PostTreat(); |
544 | } |
545 | //======================================================================= |
8620e18d |
546 | //function : BuildRC |
547 | //purpose : |
548 | //======================================================================= |
549 | void BOPAlgo_BOP::BuildRC() |
550 | { |
9526aa6a |
551 | TopAbs_ShapeEnum aType; |
8620e18d |
552 | TopoDS_Compound aC; |
8620e18d |
553 | BRep_Builder aBB; |
8620e18d |
554 | // |
8620e18d |
555 | aBB.MakeCompound(aC); |
556 | // |
557 | // A. Fuse |
9526aa6a |
558 | if (myOperation == BOPAlgo_FUSE) { |
1155d05a |
559 | TopTools_MapOfShape aMFence; |
9526aa6a |
560 | aType = TypeToExplore(myDims[0]); |
561 | TopExp_Explorer aExp(myShape, aType); |
8620e18d |
562 | for (; aExp.More(); aExp.Next()) { |
9526aa6a |
563 | const TopoDS_Shape& aS = aExp.Current(); |
564 | if (aMFence.Add(aS)) { |
565 | aBB.Add(aC, aS); |
566 | } |
8620e18d |
567 | } |
9526aa6a |
568 | myRC = aC; |
8620e18d |
569 | return; |
8620e18d |
570 | } |
8620e18d |
571 | // |
572 | // B. Common, Cut, Cut21 |
573 | // |
9526aa6a |
574 | Standard_Integer i, j, aNb, iDim; |
575 | Standard_Boolean bCheckEdges, bContains, bCut21, bCommon; |
1155d05a |
576 | TopTools_ListIteratorOfListOfShape aItLS; |
8620e18d |
577 | // |
25dfc507 |
578 | // prepare the building elements of arguments to get its splits |
1155d05a |
579 | TopTools_IndexedMapOfShape aMArgs, aMTools; |
9526aa6a |
580 | for (i = 0; i < 2; ++i) { |
1155d05a |
581 | const TopTools_ListOfShape& aLS = !i ? myArguments : myTools; |
582 | TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools; |
9526aa6a |
583 | aItLS.Initialize(aLS); |
584 | for (; aItLS.More(); aItLS.Next()) { |
585 | const TopoDS_Shape& aS = aItLS.Value(); |
586 | iDim = BOPTools_AlgoTools::Dimension(aS); |
33ba8565 |
587 | if (iDim < 0) { |
588 | continue; |
589 | } |
9526aa6a |
590 | aType = TypeToExplore(iDim); |
1155d05a |
591 | TopExp::MapShapes(aS, aType, aMS); |
9526aa6a |
592 | } |
593 | } |
594 | // |
595 | bCheckEdges = Standard_False; |
596 | // |
25dfc507 |
597 | // get splits of building elements |
1155d05a |
598 | TopTools_IndexedMapOfShape aMArgsIm, aMToolsIm; |
25dfc507 |
599 | BOPTools_IndexedDataMapOfSetShape aMSetArgs, aMSetTools; |
600 | |
9526aa6a |
601 | for (i = 0; i < 2; ++i) { |
1155d05a |
602 | const TopTools_IndexedMapOfShape& aMS = !i ? aMArgs : aMTools; |
603 | TopTools_IndexedMapOfShape& aMSIm = !i ? aMArgsIm : aMToolsIm; |
25dfc507 |
604 | BOPTools_IndexedDataMapOfSetShape& aMSet = !i ? aMSetArgs : aMSetTools; |
8620e18d |
605 | // |
9526aa6a |
606 | aNb = aMS.Extent(); |
607 | for (j = 1; j <= aNb; ++j) { |
608 | const TopoDS_Shape& aS = aMS(j); |
609 | aType = aS.ShapeType(); |
610 | if (aType == TopAbs_EDGE) { |
611 | const TopoDS_Edge& aE = *(TopoDS_Edge*)&aS; |
612 | bCheckEdges = Standard_True; |
613 | if (BRep_Tool::Degenerated(aE)) { |
614 | continue; |
8620e18d |
615 | } |
616 | } |
9526aa6a |
617 | // |
618 | if (myImages.IsBound(aS)) { |
1155d05a |
619 | const TopTools_ListOfShape& aLSIm = myImages.Find(aS); |
9526aa6a |
620 | aItLS.Initialize(aLSIm); |
621 | for (; aItLS.More(); aItLS.Next()) { |
622 | const TopoDS_Shape& aSIm = aItLS.Value(); |
623 | aMSIm.Add(aSIm); |
955b3e71 |
624 | } |
8620e18d |
625 | } |
9526aa6a |
626 | else { |
627 | aMSIm.Add(aS); |
25dfc507 |
628 | if (aS.ShapeType() == TopAbs_SOLID) { |
629 | BOPTools_Set aST; |
630 | aST.Add(aS, TopAbs_FACE); |
631 | if (!aMSet.Contains(aST)) { |
632 | aMSet.Add(aST, aS); |
633 | } |
634 | } |
9526aa6a |
635 | } |
8620e18d |
636 | } |
9526aa6a |
637 | } |
8620e18d |
638 | // |
9526aa6a |
639 | // compare the maps and make the result |
640 | // |
641 | Standard_Integer iDimMin, iDimMax; |
642 | // |
643 | iDimMin = Min(myDims[0], myDims[1]); |
644 | bCommon = (myOperation == BOPAlgo_COMMON); |
645 | bCut21 = (myOperation == BOPAlgo_CUT21); |
646 | // |
1155d05a |
647 | const TopTools_IndexedMapOfShape& aMIt = bCut21 ? aMToolsIm : aMArgsIm; |
648 | const TopTools_IndexedMapOfShape& aMCheck = bCut21 ? aMArgsIm : aMToolsIm; |
25dfc507 |
649 | const BOPTools_IndexedDataMapOfSetShape& aMSetCheck = bCut21 ? aMSetArgs : aMSetTools; |
9526aa6a |
650 | // |
1155d05a |
651 | TopTools_IndexedMapOfShape aMCheckExp, aMItExp; |
9526aa6a |
652 | // |
653 | if (bCommon) { |
654 | aNb = aMIt.Extent(); |
655 | for (i = 1; i <= aNb; ++i) { |
656 | const TopoDS_Shape& aS = aMIt(i); |
657 | iDimMax = BOPTools_AlgoTools::Dimension(aS); |
658 | for (iDim = iDimMin; iDim < iDimMax; ++iDim) { |
659 | aType = TypeToExplore(iDim); |
1155d05a |
660 | TopExp::MapShapes(aS, aType, aMItExp); |
9526aa6a |
661 | } |
662 | aMItExp.Add(aS); |
663 | } |
664 | } |
665 | else { |
666 | aMItExp = aMIt; |
667 | } |
668 | // |
669 | aNb = aMCheck.Extent(); |
670 | for (i = 1; i <= aNb; ++i) { |
671 | const TopoDS_Shape& aS = aMCheck(i); |
672 | iDimMax = BOPTools_AlgoTools::Dimension(aS); |
673 | for (iDim = iDimMin; iDim < iDimMax; ++iDim) { |
674 | aType = TypeToExplore(iDim); |
1155d05a |
675 | TopExp::MapShapes(aS, aType, aMCheckExp); |
9526aa6a |
676 | } |
677 | aMCheckExp.Add(aS); |
678 | } |
679 | // |
680 | aNb = aMItExp.Extent(); |
681 | for (i = 1; i <= aNb; ++i) { |
682 | const TopoDS_Shape& aS = aMItExp(i); |
683 | // |
684 | bContains = aMCheckExp.Contains(aS); |
25dfc507 |
685 | if (!bContains && aS.ShapeType() == TopAbs_SOLID) { |
686 | BOPTools_Set aST; |
687 | aST.Add(aS, TopAbs_FACE); |
688 | bContains = aMSetCheck.Contains(aST); |
689 | } |
690 | // |
9526aa6a |
691 | if (bCommon) { |
692 | if (bContains) { |
693 | aBB.Add(aC, aS); |
8620e18d |
694 | } |
9526aa6a |
695 | } |
8620e18d |
696 | else { |
9526aa6a |
697 | if (!bContains) { |
698 | aBB.Add(aC, aS); |
699 | } |
700 | } |
701 | } |
702 | // |
703 | // filter result for COMMON operation |
704 | if (bCommon) { |
1155d05a |
705 | TopTools_MapOfShape aMFence; |
9526aa6a |
706 | TopExp_Explorer aExp; |
707 | TopoDS_Compound aCx; |
708 | aBB.MakeCompound(aCx); |
709 | // |
710 | for (iDim = 3; iDim >= iDimMin; --iDim) { |
711 | aType = TypeToExplore(iDim); |
712 | aExp.Init(aC, aType); |
8620e18d |
713 | for (; aExp.More(); aExp.Next()) { |
9526aa6a |
714 | const TopoDS_Shape& aS = aExp.Current(); |
715 | if (aMFence.Add(aS)) { |
716 | aBB.Add(aCx, aS); |
1155d05a |
717 | TopExp::MapShapes(aS, aMFence); |
8620e18d |
718 | } |
719 | } |
720 | } |
9526aa6a |
721 | aC = aCx; |
722 | } |
8620e18d |
723 | // |
9526aa6a |
724 | if (!bCheckEdges) { |
725 | myRC = aC; |
8620e18d |
726 | return; |
727 | } |
8620e18d |
728 | // |
729 | // The squats around degenerated edges |
9526aa6a |
730 | Standard_Integer nVD; |
1155d05a |
731 | TopTools_IndexedMapOfShape aMVC; |
8620e18d |
732 | // |
733 | // 1. Vertices of aC |
1155d05a |
734 | TopExp::MapShapes(aC, TopAbs_VERTEX, aMVC); |
8620e18d |
735 | // |
736 | // 2. DE candidates |
9526aa6a |
737 | aNb = myDS->NbSourceShapes(); |
738 | for (i = 0; i < aNb; ++i) { |
739 | const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); |
740 | aType = aSI.ShapeType(); |
741 | if (aType != TopAbs_EDGE) { |
8620e18d |
742 | continue; |
743 | } |
744 | // |
9526aa6a |
745 | const TopoDS_Edge& aE = *((TopoDS_Edge*)&aSI.Shape()); |
8620e18d |
746 | if (!BRep_Tool::Degenerated(aE)) { |
747 | continue; |
748 | } |
749 | // |
9526aa6a |
750 | nVD = aSI.SubShapes().First(); |
751 | const TopoDS_Shape& aVD = myDS->Shape(nVD); |
8620e18d |
752 | // |
753 | if (!aMVC.Contains(aVD)) { |
754 | continue; |
755 | } |
756 | // |
757 | if (myDS->IsNewShape(nVD)) { |
758 | continue; |
759 | } |
760 | // |
761 | if (myDS->HasInterf(nVD)) { |
762 | continue; |
763 | } |
764 | // |
765 | aBB.Add(aC, aE); |
766 | } |
767 | // |
768 | myRC=aC; |
769 | } |
770 | //======================================================================= |
4e57c75e |
771 | //function : BuildShape |
772 | //purpose : |
773 | //======================================================================= |
8620e18d |
774 | void BOPAlgo_BOP::BuildShape() |
4e57c75e |
775 | { |
13c0e402 |
776 | if (myDims[0] == 3 && myDims[1] == 3) |
777 | { |
778 | // For the Boolean operation on solids we need to check first |
779 | // if we are dealing with closed solids, because for open solids |
780 | // we cannot expect the BuilderSolid algorithm to produce good |
781 | // splits for them and have to try the alternative approach for |
782 | // building the result shape. |
783 | // This approach is not used by default as it will loose the |
784 | // modification history for solids, because the result solid |
785 | // will be built from scratch using the splits of faces. |
786 | Standard_Boolean hasNotClosedSolids = CheckArgsForOpenSolid(); |
787 | if (hasNotClosedSolids) |
788 | { |
789 | Handle(Message_Report) aReport = new Message_Report(); |
790 | BuildBOP(myArguments, myTools, myOperation, aReport); |
791 | if (aReport->GetAlerts(Message_Fail).IsEmpty()) |
792 | { |
793 | // Success. Merge the report into the main report. |
794 | myReport->Merge(aReport); |
795 | return; |
796 | } |
797 | } |
798 | } |
799 | |
800 | // Build the result using splits of arguments. |
801 | |
9526aa6a |
802 | BuildRC(); |
803 | // |
804 | if ((myOperation == BOPAlgo_FUSE) && (myDims[0] == 3)) { |
805 | BuildSolid(); |
806 | return; |
807 | } |
808 | // |
809 | Standard_Integer i; |
810 | TopAbs_ShapeEnum aType, aT1, aT2; |
1155d05a |
811 | TopTools_ListOfShape aLSC, aLCB; |
812 | TopTools_ListIteratorOfListOfShape aItLS, aItLSIm, aItLCB; |
4e57c75e |
813 | TopoDS_Iterator aIt; |
814 | BRep_Builder aBB; |
9526aa6a |
815 | TopoDS_Shape aRC, aRCB; |
4e57c75e |
816 | // |
1155d05a |
817 | TopTools_MapOfShape aMSRC; |
818 | TopExp::MapShapes(myRC, aMSRC); |
4e57c75e |
819 | // |
9526aa6a |
820 | // collect images of containers |
821 | for (i = 0; i < 2; ++i) { |
1155d05a |
822 | const TopTools_ListOfShape& aLS = !i ? myArguments : myTools; |
9526aa6a |
823 | // |
824 | aItLS.Initialize(aLS); |
825 | for (; aItLS.More(); aItLS.Next()) { |
826 | const TopoDS_Shape& aS = aItLS.Value(); |
827 | // |
828 | CollectContainers(aS, aLSC); |
829 | } |
4e57c75e |
830 | } |
9526aa6a |
831 | // make containers |
1155d05a |
832 | TopTools_ListOfShape aLCRes; |
833 | TopTools_MapOfShape aMInpFence; |
9526aa6a |
834 | aItLS.Initialize(aLSC); |
835 | for (; aItLS.More(); aItLS.Next()) { |
836 | const TopoDS_Shape& aSC = aItLS.Value(); |
977ad983 |
837 | aMInpFence.Add(aSC); |
9526aa6a |
838 | // |
839 | BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC); |
840 | // |
841 | aIt.Initialize(aSC); |
842 | for (; aIt.More(); aIt.Next()) { |
843 | const TopoDS_Shape& aS = aIt.Value(); |
844 | if (myImages.IsBound(aS)) { |
1155d05a |
845 | const TopTools_ListOfShape& aLSIm = myImages.Find(aS); |
9526aa6a |
846 | // |
847 | aItLSIm.Initialize(aLSIm); |
848 | for (; aItLSIm.More(); aItLSIm.Next()) { |
849 | const TopoDS_Shape& aSIm = aItLSIm.Value(); |
1511c7e9 |
850 | if (aMSRC.Contains(aSIm)) { |
9526aa6a |
851 | aBB.Add(aRC, aSIm); |
852 | } |
853 | } |
854 | } |
1511c7e9 |
855 | else if (aMSRC.Contains(aS)) { |
9526aa6a |
856 | aBB.Add(aRC, aS); |
857 | } |
4e57c75e |
858 | } |
859 | // |
9526aa6a |
860 | aType = aSC.ShapeType(); |
861 | switch (aType) { |
862 | case TopAbs_WIRE: { |
863 | aT1 = TopAbs_VERTEX; |
864 | aT2 = TopAbs_EDGE; |
865 | break; |
866 | } |
867 | case TopAbs_SHELL: { |
868 | aT1 = TopAbs_EDGE; |
869 | aT2 = TopAbs_FACE; |
870 | break; |
871 | } |
872 | default: { |
873 | aT1 = TopAbs_FACE; |
874 | aT2 = TopAbs_SOLID; |
875 | } |
4e57c75e |
876 | } |
877 | // |
9526aa6a |
878 | aLCB.Clear(); |
879 | BOPTools_AlgoTools::MakeConnexityBlocks(aRC, aT1, aT2, aLCB); |
880 | if (aLCB.IsEmpty()) { |
881 | continue; |
882 | } |
4e57c75e |
883 | // |
884 | aItLCB.Initialize(aLCB); |
885 | for (; aItLCB.More(); aItLCB.Next()) { |
9526aa6a |
886 | BOPTools_AlgoTools::MakeContainer(aType, aRCB); |
4e57c75e |
887 | // |
9526aa6a |
888 | const TopoDS_Shape& aCB = aItLCB.Value(); |
4e57c75e |
889 | aIt.Initialize(aCB); |
890 | for (; aIt.More(); aIt.Next()) { |
9526aa6a |
891 | const TopoDS_Shape& aCBS = aIt.Value(); |
892 | aBB.Add(aRCB, aCBS); |
4e57c75e |
893 | } |
894 | // |
77a11d3d |
895 | if (aType == TopAbs_WIRE) { |
896 | // reorient wire |
897 | BOPTools_AlgoTools::OrientEdgesOnWire(aRCB); |
898 | } |
899 | else if (aType == TopAbs_SHELL) { |
9526aa6a |
900 | BOPTools_AlgoTools::OrientFacesOnShell(aRCB); |
4e57c75e |
901 | } |
902 | // |
77a11d3d |
903 | aRCB.Orientation(aSC.Orientation()); |
904 | // |
905 | aLCRes.Append(aRCB); |
4e57c75e |
906 | } |
9526aa6a |
907 | } |
908 | // |
77a11d3d |
909 | RemoveDuplicates(aLCRes); |
910 | // |
911 | // add containers to result |
912 | TopoDS_Compound aResult; |
913 | aBB.MakeCompound(aResult); |
914 | // |
915 | aItLS.Initialize(aLCRes); |
916 | for (; aItLS.More(); aItLS.Next()) { |
917 | aBB.Add(aResult, aItLS.Value()); |
918 | } |
977ad983 |
919 | |
920 | // create map of containers |
1155d05a |
921 | TopTools_MapOfShape aMSResult; |
922 | TopExp::MapShapes(aResult, aMSResult); |
977ad983 |
923 | |
924 | // get input non-container shapes |
1155d05a |
925 | TopTools_ListOfShape aLSNonCont; |
977ad983 |
926 | for (i = 0; i < 2; ++i) |
927 | { |
1155d05a |
928 | const TopTools_ListOfShape& aLS = !i ? myArguments : myTools; |
977ad983 |
929 | aItLS.Initialize(aLS); |
930 | for (; aItLS.More(); aItLS.Next()) |
931 | { |
932 | const TopoDS_Shape& aS = aItLS.Value(); |
933 | BOPAlgo_Tools::TreatCompound(aS, aMInpFence, aLSNonCont); |
4e57c75e |
934 | } |
935 | } |
977ad983 |
936 | |
937 | // put non-container shapes in the result |
938 | aItLS.Initialize(aLSNonCont); |
939 | for (; aItLS.More(); aItLS.Next()) |
940 | { |
941 | const TopoDS_Shape& aS = aItLS.Value(); |
942 | if (myImages.IsBound(aS)) |
943 | { |
1155d05a |
944 | const TopTools_ListOfShape& aLSIm = myImages.Find(aS); |
977ad983 |
945 | aItLSIm.Initialize(aLSIm); |
946 | for (; aItLSIm.More(); aItLSIm.Next()) |
947 | { |
948 | const TopoDS_Shape& aSIm = aItLSIm.Value(); |
949 | if (aMSRC.Contains(aSIm) && aMSResult.Add(aSIm)) |
950 | aBB.Add(aResult, aSIm); |
951 | } |
952 | } |
953 | else if (aMSRC.Contains(aS) && aMSResult.Add(aS)) |
954 | aBB.Add(aResult, aS); |
955 | } |
956 | |
9526aa6a |
957 | myShape = aResult; |
4e57c75e |
958 | } |
959 | //======================================================================= |
960 | //function : BuildSolid |
961 | //purpose : |
962 | //======================================================================= |
8620e18d |
963 | void BOPAlgo_BOP::BuildSolid() |
4e57c75e |
964 | { |
25dfc507 |
965 | // Containers |
1155d05a |
966 | TopTools_ListOfShape aLSC; |
4e57c75e |
967 | // |
1155d05a |
968 | TopTools_ListIteratorOfListOfShape aItLS; |
25dfc507 |
969 | TopExp_Explorer aExp; |
970 | BRep_Builder aBB; |
971 | // |
25dfc507 |
972 | // Get solids from input arguments |
1155d05a |
973 | TopTools_MapOfShape aMSA; |
25dfc507 |
974 | // Map the arguments to find shared faces |
1155d05a |
975 | TopTools_IndexedDataMapOfShapeListOfShape aMFS; |
25dfc507 |
976 | for (Standard_Integer i = 0; i < 2; ++i) { |
1155d05a |
977 | const TopTools_ListOfShape& aLSA = (i) ? myArguments : myTools; |
955b3e71 |
978 | aItLS.Initialize(aLSA); |
979 | for (; aItLS.More(); aItLS.Next()) { |
25dfc507 |
980 | const TopoDS_Shape& aSA = aItLS.Value(); |
955b3e71 |
981 | aExp.Init(aSA, TopAbs_SOLID); |
982 | for (; aExp.More(); aExp.Next()) { |
25dfc507 |
983 | const TopoDS_Shape& aSol = aExp.Current(); |
984 | aMSA.Add(aSol); |
1155d05a |
985 | TopExp::MapShapesAndAncestors(aSol, TopAbs_FACE, TopAbs_SOLID, aMFS); |
955b3e71 |
986 | } |
25dfc507 |
987 | // |
988 | // get Compsolids from input arguments |
989 | CollectContainers(aSA, aLSC); |
955b3e71 |
990 | } |
991 | } |
992 | // |
25dfc507 |
993 | // Find solids in input arguments sharing faces with other solids |
1155d05a |
994 | TopTools_MapOfShape aMTSols; |
25dfc507 |
995 | Standard_Integer i, aNb = aMFS.Extent(); |
996 | for (i = 1; i < aNb; ++i) { |
1155d05a |
997 | const TopTools_ListOfShape& aLSols = aMFS(i); |
25dfc507 |
998 | if (aLSols.Extent() > 1) { |
999 | aItLS.Initialize(aLSols); |
955b3e71 |
1000 | for(; aItLS.More(); aItLS.Next()) { |
25dfc507 |
1001 | aMTSols.Add(aItLS.Value()); |
955b3e71 |
1002 | } |
1003 | } |
1004 | } |
1005 | // |
25dfc507 |
1006 | // Possibly untouched solids - to be added to results as is |
1155d05a |
1007 | TopTools_IndexedMapOfShape aMUSols; |
25dfc507 |
1008 | // Use map to chose the most outer faces to build result solids |
955b3e71 |
1009 | aMFS.Clear(); |
25dfc507 |
1010 | // Internal faces |
1155d05a |
1011 | TopTools_IndexedMapOfShape aMFI; |
955b3e71 |
1012 | // |
25dfc507 |
1013 | TopoDS_Iterator aIt(myRC); |
4e57c75e |
1014 | for (; aIt.More(); aIt.Next()) { |
25dfc507 |
1015 | const TopoDS_Shape& aSx = aIt.Value(); |
955b3e71 |
1016 | if (aMSA.Contains(aSx)) { |
25dfc507 |
1017 | if (!aMTSols.Contains(aSx)) { |
1018 | aMUSols.Add(aSx); |
1019 | continue; |
955b3e71 |
1020 | } |
25dfc507 |
1021 | } |
1022 | // |
1023 | MapFacesToBuildSolids(aSx, aMFS, aMFI); |
1024 | } // for (; aIt.More(); aIt.Next()) { |
1025 | // |
1026 | // Process possibly untouched solids. |
1027 | // Really untouched solids will be added into result as is. |
1028 | // Others will be processed by BuilderSolid. |
1029 | BOPTools_IndexedDataMapOfSetShape aDMSTS; |
1030 | // |
1031 | aNb = aMUSols.Extent(); |
1032 | for (i = 1; i <= aNb; ++i) { |
1033 | const TopoDS_Shape& aSx = aMUSols(i); |
955b3e71 |
1034 | // |
4e57c75e |
1035 | aExp.Init(aSx, TopAbs_FACE); |
1036 | for (; aExp.More(); aExp.Next()) { |
25dfc507 |
1037 | if (aMFS.Contains(aExp.Current())) { |
1038 | break; |
4e57c75e |
1039 | } |
25dfc507 |
1040 | } |
1041 | // |
1042 | if (aExp.More()) { |
1043 | MapFacesToBuildSolids(aSx, aMFS, aMFI); |
1044 | } |
1045 | else { |
1046 | BOPTools_Set aST; |
1047 | aST.Add(aSx, TopAbs_FACE); |
1048 | if (!aDMSTS.Contains(aST)) { |
1049 | aDMSTS.Add(aST, aSx); |
4e57c75e |
1050 | } |
1051 | } |
25dfc507 |
1052 | } |
1053 | // |
1155d05a |
1054 | TopTools_IndexedDataMapOfShapeListOfShape aMEF; |
81a55a69 |
1055 | // Fill the list of faces to build the result solids |
1056 | TopTools_ListOfShape aSFS; |
25dfc507 |
1057 | aNb = aMFS.Extent(); |
1058 | for (i = 1; i <= aNb; ++i) { |
1155d05a |
1059 | const TopTools_ListOfShape& aLSx = aMFS(i); |
25dfc507 |
1060 | if (aLSx.Extent() == 1) { |
1061 | const TopoDS_Shape& aFx = aMFS.FindKey(i); |
1155d05a |
1062 | TopExp::MapShapesAndAncestors(aFx, TopAbs_EDGE, TopAbs_FACE, aMEF); |
81a55a69 |
1063 | aSFS.Append(aFx); |
4e57c75e |
1064 | } |
1065 | } |
25dfc507 |
1066 | // Internal faces |
1067 | aNb = aMFI.Extent(); |
1068 | for (i = 1; i <= aNb; ++i) { |
1069 | TopoDS_Shape aFx = aMFI.FindKey(i); |
1070 | aSFS.Append(aFx.Oriented(TopAbs_FORWARD)); |
1071 | aSFS.Append(aFx.Oriented(TopAbs_REVERSED)); |
4e57c75e |
1072 | } |
1073 | // |
25dfc507 |
1074 | TopoDS_Shape aRC; |
1075 | BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aRC); |
1076 | if (aSFS.Extent()) { |
1077 | // Build solids from set of faces |
7f3408c8 |
1078 | BOPAlgo_BuilderSolid aBS; |
1079 | aBS.SetContext(myContext); |
1080 | aBS.SetShapes(aSFS); |
1081 | aBS.Perform(); |
1082 | if (aBS.HasErrors()) { |
33ba8565 |
1083 | AddError (new BOPAlgo_AlertSolidBuilderFailed); // SolidBuilder failed |
25dfc507 |
1084 | return; |
1085 | } |
7f3408c8 |
1086 | |
1087 | myReport->Merge(aBS.GetReport()); |
1088 | |
25dfc507 |
1089 | // new solids |
7f3408c8 |
1090 | const TopTools_ListOfShape& aLSR = aBS.Areas(); |
25dfc507 |
1091 | // |
1092 | // add new solids to result |
1093 | aItLS.Initialize(aLSR); |
1094 | for (; aItLS.More(); aItLS.Next()) { |
1095 | const TopoDS_Shape& aSR = aItLS.Value(); |
1096 | aBB.Add(aRC, aSR); |
1097 | } |
4e57c75e |
1098 | } |
955b3e71 |
1099 | // |
25dfc507 |
1100 | // add untouched solids to result |
1101 | aNb = aDMSTS.Extent(); |
1102 | for (i = 1; i <= aNb; ++i) { |
319da2e4 |
1103 | const TopoDS_Shape& aSx = aDMSTS(i); |
955b3e71 |
1104 | aBB.Add(aRC, aSx); |
1105 | } |
1106 | // |
77a11d3d |
1107 | if (aLSC.IsEmpty()) { |
1108 | // no Compsolids in arguments |
25dfc507 |
1109 | myShape = aRC; |
77a11d3d |
1110 | return; |
1111 | } |
1112 | // |
1113 | // build new Compsolids from new solids containing splits |
1114 | // of faces from arguments of type Compsolid |
1115 | // |
1116 | TopoDS_Shape aResult; |
1117 | BOPTools_AlgoTools::MakeContainer(TopAbs_COMPOUND, aResult); |
1118 | // |
25dfc507 |
1119 | aIt.Initialize(aRC); |
1120 | if (!aIt.More()) { |
1121 | // no solids in the result |
1122 | myShape = aRC; |
1123 | return; |
1124 | } |
1125 | // |
1126 | const TopoDS_Shape& aSol1 = aIt.Value(); |
1127 | aIt.Next(); |
1128 | // |
77a11d3d |
1129 | // optimization for one solid in the result |
25dfc507 |
1130 | if (!aIt.More()) { |
77a11d3d |
1131 | TopoDS_Shape aCS; |
1132 | BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS); |
25dfc507 |
1133 | aBB.Add(aCS, aSol1); |
77a11d3d |
1134 | // |
1135 | aBB.Add(aResult, aCS); |
1136 | myShape = aResult; |
1137 | return; |
1138 | } |
1139 | // |
1140 | // get splits of faces of the Compsolid arguments |
1155d05a |
1141 | TopTools_MapOfShape aMFCs; |
77a11d3d |
1142 | aItLS.Initialize(aLSC); |
1143 | for (; aItLS.More(); aItLS.Next()) { |
1144 | const TopoDS_Shape& aCs = aItLS.Value(); |
1145 | aExp.Init(aCs, TopAbs_FACE); |
1146 | for (; aExp.More(); aExp.Next()) { |
1147 | const TopoDS_Shape& aF = aExp.Current(); |
1155d05a |
1148 | const TopTools_ListOfShape* pLFIm = myImages.Seek(aF); |
77a11d3d |
1149 | if (!pLFIm) { |
1150 | aMFCs.Add(aF); |
1151 | } |
1152 | else { |
1155d05a |
1153 | TopTools_ListIteratorOfListOfShape aItLFIm(*pLFIm); |
77a11d3d |
1154 | for (; aItLFIm.More(); aItLFIm.Next()) { |
1155 | aMFCs.Add(aItLFIm.Value()); |
1156 | } |
1157 | } |
1158 | } |
1159 | } |
1160 | // |
1161 | // build connexity blocks from new solids |
1155d05a |
1162 | TopTools_ListOfShape aLCBS; |
77a11d3d |
1163 | BOPTools_AlgoTools::MakeConnexityBlocks(aRC, TopAbs_FACE, TopAbs_SOLID, aLCBS); |
1164 | // |
1165 | aItLS.Initialize(aLCBS); |
1166 | for (; aItLS.More(); aItLS.Next()) { |
1167 | const TopoDS_Shape& aCB = aItLS.Value(); |
1168 | // |
1169 | // check if the Compsolid should be created |
1170 | aExp.Init(aCB, TopAbs_FACE); |
1171 | for (; aExp.More(); aExp.Next()) { |
1172 | if (aMFCs.Contains(aExp.Current())) { |
1173 | break; |
1174 | } |
1175 | } |
1176 | // |
1177 | if (!aExp.More()) { |
1178 | // add solids directly into result as their origins are not Compsolids |
1179 | for (aIt.Initialize(aCB); aIt.More(); aIt.Next()) { |
1180 | aBB.Add(aResult, aIt.Value()); |
1181 | } |
1182 | continue; |
1183 | } |
1184 | // |
1185 | // make Compsolid |
1186 | TopoDS_Shape aCS; |
1187 | BOPTools_AlgoTools::MakeContainer(TopAbs_COMPSOLID, aCS); |
1188 | // |
1189 | aIt.Initialize(aCB); |
1190 | for (; aIt.More(); aIt.Next()) { |
1191 | aBB.Add(aCS, aIt.Value()); |
1192 | } |
1193 | // |
1194 | aBB.Add(aResult, aCS); |
1195 | } |
1196 | // |
1197 | myShape = aResult; |
4e57c75e |
1198 | } |
13c0e402 |
1199 | |
1200 | //======================================================================= |
1201 | //function : CheckArgsForOpenSolid |
1202 | //purpose : |
1203 | //======================================================================= |
1204 | Standard_Boolean BOPAlgo_BOP::CheckArgsForOpenSolid() |
1205 | { |
1206 | // Analyze the report to find if BuilderSolid has generated warnings |
1207 | // for any of the solids and collect these solids to check if they are open. |
1208 | TopTools_MapOfShape aFailedSolids; |
1209 | { |
1210 | const Message_ListOfAlert& aList = myReport->GetAlerts(Message_Warning); |
1211 | for (Message_ListOfAlert::Iterator aIt(aList); aIt.More(); aIt.Next()) |
1212 | { |
1213 | const Handle(Standard_Type)& aType = aIt.Value()->DynamicType(); |
1214 | if (aType != STANDARD_TYPE(BOPAlgo_AlertSolidBuilderUnusedFaces)) |
1215 | continue; |
1216 | |
1217 | Handle(TopoDS_AlertWithShape) aShapeAlert = Handle(TopoDS_AlertWithShape)::DownCast(aIt.Value()); |
1218 | if (!aShapeAlert.IsNull()) |
1219 | { |
1220 | const TopoDS_Shape& aWarnShape = aShapeAlert->GetShape(); |
1221 | if (!aWarnShape.IsNull()) |
1222 | { |
1223 | TopExp_Explorer expS(aWarnShape, TopAbs_SOLID); |
1224 | for (; expS.More(); expS.Next()) |
1225 | aFailedSolids.Add(expS.Current()); |
1226 | } |
1227 | } |
1228 | } |
1229 | } |
1230 | |
1231 | // Iterate on all solids from the arguments and check if any |
1232 | // of them are not closed. |
1233 | // At the same time, collect all internal faces of the input solids |
1234 | // to check if the splits of open solids did not acquire any new |
1235 | // internal faces. |
1236 | |
1237 | const Standard_Integer aNbS = myDS->NbSourceShapes(); |
1238 | for (Standard_Integer i = 0; i < aNbS; ++i) |
1239 | { |
1240 | const BOPDS_ShapeInfo& aSI = myDS->ShapeInfo(i); |
1241 | if (aSI.ShapeType() != TopAbs_SOLID) |
1242 | continue; |
1243 | |
1244 | const TopoDS_Shape& aSolid = aSI.Shape(); |
1245 | |
1246 | // Check that not INTERNAL faces create closed loops |
1247 | TopTools_IndexedDataMapOfShapeListOfShape aMEF; |
1248 | // Collect all splits of internal faces |
1249 | TopTools_MapOfShape aMFInternal; |
1250 | |
1251 | for (TopoDS_Iterator itSh(aSolid); itSh.More(); itSh.Next()) |
1252 | { |
1253 | const TopoDS_Shape& aSh = itSh.Value(); |
1254 | if (aSh.ShapeType() != TopAbs_SHELL) |
1255 | continue; |
1256 | |
1257 | for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next()) |
1258 | { |
1259 | const TopoDS_Shape& aF = itF.Value(); |
1260 | if (aF.Orientation() == TopAbs_INTERNAL) |
1261 | { |
1262 | const TopTools_ListOfShape* pLFIm = myImages.Seek(aF); |
1263 | if (pLFIm) |
1264 | { |
1265 | TopTools_ListOfShape::Iterator itLFIm(*pLFIm); |
1266 | for (; itLFIm.More(); itLFIm.Next()) |
1267 | aMFInternal.Add(itLFIm.Value()); |
1268 | } |
1269 | else |
1270 | aMFInternal.Add(aF); |
1271 | } |
1272 | else |
1273 | TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF); |
1274 | } |
1275 | } |
1276 | |
1277 | // Analyze the Edge-Face connection map on free edges |
1278 | Standard_Boolean isClosed = Standard_True; |
1279 | const Standard_Integer aNbE = aMEF.Extent(); |
1280 | for (Standard_Integer j = 1; j <= aNbE && isClosed; ++j) |
1281 | { |
1282 | const TopoDS_Edge& aE = TopoDS::Edge(aMEF.FindKey(j)); |
1283 | if (BRep_Tool::Degenerated(aE)) |
1284 | // Skip degenerated edges |
1285 | continue; |
1286 | |
1287 | isClosed = (aMEF(j).Extent() > 1); |
1288 | if (!isClosed) |
1289 | { |
1290 | const TopoDS_Face& aF = TopoDS::Face(aMEF(j).First()); |
1291 | isClosed = BRep_Tool::IsClosed(aE, aF); // Check for seam edges |
1292 | if (!isClosed) |
1293 | { |
1294 | // Check if the edge is not internal in the face |
1295 | TopExp_Explorer expE(aF, TopAbs_EDGE); |
1296 | for (; expE.More(); expE.Next()) |
1297 | { |
1298 | if (expE.Current().IsSame(aE)) |
1299 | { |
1300 | isClosed = (expE.Current().Orientation() == TopAbs_INTERNAL); |
1301 | break; |
1302 | } |
1303 | } |
1304 | } |
1305 | } |
1306 | } |
1307 | |
1308 | if (isClosed) |
1309 | continue; |
1310 | |
1311 | // Not closed solid is found |
1312 | |
1313 | if (aFailedSolids.Contains(aSolid)) |
1314 | // Warning has been generated for this solid, return positive result right away. |
1315 | return Standard_True; |
1316 | |
1317 | |
1318 | // Check the splits not to acquire new INTERNAL faces |
1319 | const TopTools_ListOfShape *pLSIm = myImages.Seek(aSolid); |
1320 | if (!pLSIm) |
1321 | continue; |
1322 | |
1323 | TopTools_ListOfShape::Iterator itLSIm(*pLSIm); |
1324 | for (; itLSIm.More(); itLSIm.Next()) |
1325 | { |
1326 | const TopoDS_Shape& aSIm = itLSIm.Value(); |
1327 | for (TopoDS_Iterator itSh(aSIm); itSh.More(); itSh.Next()) |
1328 | { |
1329 | const TopoDS_Shape& aSh = itSh.Value(); |
1330 | if (aSh.ShapeType() != TopAbs_SHELL) |
1331 | continue; |
1332 | |
1333 | for (TopoDS_Iterator itF(aSh); itF.More(); itF.Next()) |
1334 | { |
1335 | const TopoDS_Shape& aF = itF.Value(); |
1336 | if (aF.Orientation() == TopAbs_INTERNAL) |
1337 | { |
1338 | if (!aMFInternal.Contains(aF)) |
1339 | // New internal face is found |
1340 | return Standard_True; |
1341 | } |
1342 | } |
1343 | } |
1344 | } |
1345 | } |
1346 | |
1347 | return Standard_False; |
1348 | } |
1349 | |
4e57c75e |
1350 | //======================================================================= |
8620e18d |
1351 | //function : TypeToExplore |
1352 | //purpose : |
1353 | //======================================================================= |
1354 | TopAbs_ShapeEnum TypeToExplore(const Standard_Integer theDim) |
1355 | { |
1356 | TopAbs_ShapeEnum aRet; |
1357 | // |
1358 | switch(theDim) { |
1359 | case 0: |
1360 | aRet=TopAbs_VERTEX; |
1361 | break; |
1362 | case 1: |
1363 | aRet=TopAbs_EDGE; |
1364 | break; |
1365 | case 2: |
1366 | aRet=TopAbs_FACE; |
1367 | break; |
1368 | case 3: |
1369 | aRet=TopAbs_SOLID; |
1370 | break; |
1371 | default: |
1372 | aRet=TopAbs_SHAPE; |
1373 | break; |
1374 | } |
1375 | return aRet; |
1376 | } |
9526aa6a |
1377 | //======================================================================= |
1378 | //function : CollectContainers |
1379 | //purpose : |
1380 | //======================================================================= |
1381 | void CollectContainers(const TopoDS_Shape& theS, |
1155d05a |
1382 | TopTools_ListOfShape& theLSC) |
9526aa6a |
1383 | { |
1384 | TopAbs_ShapeEnum aType = theS.ShapeType(); |
1385 | if (aType == TopAbs_WIRE || |
1386 | aType == TopAbs_SHELL || |
1387 | aType == TopAbs_COMPSOLID) { |
1388 | theLSC.Append(theS); |
1389 | return; |
1390 | } |
1391 | // |
1392 | if (aType != TopAbs_COMPOUND) { |
1393 | return; |
1394 | } |
1395 | // |
1396 | TopoDS_Iterator aIt(theS); |
1397 | for (; aIt.More(); aIt.Next()) { |
1398 | const TopoDS_Shape& aS = aIt.Value(); |
1399 | CollectContainers(aS, theLSC); |
1400 | } |
1401 | } |
1402 | |
77a11d3d |
1403 | //======================================================================= |
1404 | //function : RemoveDuplicates |
1405 | //purpose : Filters the containers with identical contents |
1406 | //======================================================================= |
1155d05a |
1407 | void RemoveDuplicates(TopTools_ListOfShape& theContainers) |
77a11d3d |
1408 | { |
1409 | RemoveDuplicates(theContainers, TopAbs_WIRE); |
1410 | RemoveDuplicates(theContainers, TopAbs_SHELL); |
1411 | RemoveDuplicates(theContainers, TopAbs_COMPSOLID); |
1412 | } |
1413 | |
1414 | //======================================================================= |
1415 | //function : RemoveDuplicates |
1416 | //purpose : Filters the containers of given type with identical contents |
1417 | //======================================================================= |
1155d05a |
1418 | void RemoveDuplicates(TopTools_ListOfShape& theContainers, |
77a11d3d |
1419 | const TopAbs_ShapeEnum theType) |
1420 | { |
1421 | // get containers of given type |
1155d05a |
1422 | TopTools_ListOfShape aLC; |
1423 | TopTools_ListIteratorOfListOfShape aItLC(theContainers); |
77a11d3d |
1424 | for (; aItLC.More(); aItLC.Next()) { |
1425 | const TopoDS_Shape& aC = aItLC.Value(); |
1426 | if (aC.ShapeType() == theType) { |
1427 | aLC.Append(aC); |
1428 | } |
1429 | } |
1430 | // |
1431 | if (aLC.IsEmpty()) { |
1432 | return; |
1433 | } |
1434 | // |
1435 | // map containers to compare its contents |
1155d05a |
1436 | NCollection_IndexedDataMap<TopoDS_Shape, TopTools_MapOfShape> aContents; |
77a11d3d |
1437 | // |
1438 | aItLC.Initialize(aLC); |
1439 | for (; aItLC.More(); aItLC.Next()) { |
1440 | const TopoDS_Shape& aC = aItLC.Value(); |
1441 | // |
1155d05a |
1442 | TopTools_MapOfShape& aMC = aContents(aContents.Add(aC, TopTools_MapOfShape())); |
77a11d3d |
1443 | // |
1444 | TopoDS_Iterator aIt(aC); |
1445 | for (; aIt.More(); aIt.Next()) { |
1446 | aMC.Add(aIt.Value()); |
1447 | } |
1448 | } |
1449 | // |
1450 | // compare the contents of the containers and find duplicates |
1155d05a |
1451 | TopTools_MapOfShape aDuplicates; |
77a11d3d |
1452 | // |
1453 | Standard_Integer i, j, aNb = aContents.Extent(); |
1454 | for (i = 1; i <= aNb; ++i) { |
1455 | const TopoDS_Shape& aCi = aContents.FindKey(i); |
1456 | if (aDuplicates.Contains(aCi)) { |
1457 | continue; |
1458 | } |
1155d05a |
1459 | const TopTools_MapOfShape& aMi = aContents(i); |
77a11d3d |
1460 | Standard_Integer aNbi = aMi.Extent(); |
1461 | // |
1462 | for (j = i + 1; j <= aNb; ++j) { |
1463 | const TopoDS_Shape& aCj = aContents.FindKey(j); |
1464 | if (aDuplicates.Contains(aCj)) { |
1465 | continue; |
1466 | } |
1155d05a |
1467 | const TopTools_MapOfShape& aMj = aContents(j); |
77a11d3d |
1468 | Standard_Integer aNbj = aMj.Extent(); |
1469 | // |
1470 | Standard_Integer aNbCommon = NbCommonItemsInMap(aMi, aMj); |
1471 | // |
1472 | if (aNbj == aNbCommon) { |
1473 | aDuplicates.Add(aCj); |
1474 | continue; |
1475 | } |
1476 | // |
1477 | if (aNbi == aNbCommon) { |
1478 | aDuplicates.Add(aCi); |
1479 | break; |
1480 | } |
1481 | } |
1482 | } |
1483 | // |
1484 | if (aDuplicates.IsEmpty()) { |
1485 | return; |
1486 | } |
1487 | // |
1488 | // remove duplicating containers |
1489 | aItLC.Initialize(theContainers); |
1490 | for (; aItLC.More(); ) { |
1491 | const TopoDS_Shape& aC = aItLC.Value(); |
1492 | if (aDuplicates.Contains(aC)) { |
1493 | theContainers.Remove(aItLC); |
1494 | continue; |
1495 | } |
1496 | aItLC.Next(); |
1497 | } |
1498 | } |
1499 | |
1500 | //======================================================================= |
1501 | //function : NbCommonItemsInMap |
1502 | //purpose : Counts the items contained in both maps |
1503 | //======================================================================= |
1155d05a |
1504 | Standard_Integer NbCommonItemsInMap(const TopTools_MapOfShape& theM1, |
1505 | const TopTools_MapOfShape& theM2) |
77a11d3d |
1506 | { |
1155d05a |
1507 | const TopTools_MapOfShape* aMap1 = &theM1; |
1508 | const TopTools_MapOfShape* aMap2 = &theM2; |
77a11d3d |
1509 | // |
1510 | if (theM2.Extent() < theM1.Extent()) { |
1511 | aMap1 = &theM2; |
1512 | aMap2 = &theM1; |
1513 | } |
1514 | // |
1515 | Standard_Integer iCommon = 0; |
1155d05a |
1516 | for (TopTools_MapIteratorOfMapOfShape aIt(*aMap1); aIt.More(); aIt.Next()) { |
77a11d3d |
1517 | if (aMap2->Contains(aIt.Value())) { |
1518 | ++iCommon; |
1519 | } |
1520 | } |
1521 | return iCommon; |
1522 | } |
25dfc507 |
1523 | //======================================================================= |
1524 | //function : MapFacesToBuildSolids |
1525 | //purpose : Stores the faces of the given solid into outgoing maps: |
1526 | // <theMFS> - not internal faces with reference to solid; |
1527 | // <theMFI> - internal faces. |
1528 | //======================================================================= |
1529 | void MapFacesToBuildSolids(const TopoDS_Shape& theSol, |
1155d05a |
1530 | TopTools_IndexedDataMapOfShapeListOfShape& theMFS, |
1531 | TopTools_IndexedMapOfShape& theMFI) |
25dfc507 |
1532 | { |
1533 | TopExp_Explorer aExp(theSol, TopAbs_FACE); |
1534 | for (; aExp.More(); aExp.Next()) { |
1535 | const TopoDS_Shape& aF = aExp.Current(); |
1536 | // |
1537 | if (aF.Orientation() == TopAbs_INTERNAL) { |
1538 | theMFI.Add(aF); |
1539 | continue; |
1540 | } |
1541 | // |
1155d05a |
1542 | TopTools_ListOfShape* pLSol = theMFS.ChangeSeek(aF); |
25dfc507 |
1543 | if (!pLSol) { |
1155d05a |
1544 | pLSol = &theMFS(theMFS.Add(aF, TopTools_ListOfShape())); |
25dfc507 |
1545 | pLSol->Append(theSol); |
1546 | } |
1547 | else { |
1548 | const TopoDS_Shape& aF1 = theMFS.FindKey(theMFS.FindIndex(aF)); |
1549 | if (aF1.Orientation() != aF.Orientation()) { |
1550 | pLSol->Append(theSol); |
1551 | } |
1552 | } |
1553 | } |
1554 | } |