4e57c75e |
1 | // Created by: Peter KURNEV |
973c2be1 |
2 | // Copyright (c) 2010-2014 OPEN CASCADE SAS |
4e57c75e |
3 | // Copyright (c) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE |
4 | // Copyright (c) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, CEDRAT, |
5 | // EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS |
6 | // |
973c2be1 |
7 | // This file is part of Open CASCADE Technology software library. |
4e57c75e |
8 | // |
d5f74e42 |
9 | // This library is free software; you can redistribute it and/or modify it under |
10 | // the terms of the GNU Lesser General Public License version 2.1 as published |
973c2be1 |
11 | // by the Free Software Foundation, with special exception defined in the file |
12 | // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT |
13 | // distribution for complete text of the license and disclaimer of any warranty. |
4e57c75e |
14 | // |
973c2be1 |
15 | // Alternatively, this file may be used under the terms of Open CASCADE |
16 | // commercial license or contractual agreement. |
4e57c75e |
17 | |
4e57c75e |
18 | |
42cf5bc1 |
19 | #include <BOPAlgo_Builder.hxx> |
33ba8565 |
20 | #include <BOPAlgo_Alerts.hxx> |
13c0e402 |
21 | #include <BOPAlgo_BuilderSolid.hxx> |
22 | #include <BOPAlgo_PaveFiller.hxx> |
23 | #include <BOPAlgo_Tools.hxx> |
24 | #include <BOPDS_DS.hxx> |
25 | #include <BOPDS_ShapeInfo.hxx> |
42cf5bc1 |
26 | #include <BOPTools_AlgoTools.hxx> |
27 | #include <BRep_Builder.hxx> |
28 | #include <IntTools_Context.hxx> |
36f4947b |
29 | #include <Standard_ErrorHandler.hxx> |
30 | #include <Standard_Failure.hxx> |
13c0e402 |
31 | #include <TopExp.hxx> |
32 | #include <TopExp_Explorer.hxx> |
33 | #include <TopoDS.hxx> |
4e57c75e |
34 | #include <TopoDS_Compound.hxx> |
13c0e402 |
35 | #include <TopoDS_Solid.hxx> |
1155d05a |
36 | #include <TopTools_IndexedMapOfShape.hxx> |
13c0e402 |
37 | #include <TopTools_MapOfOrientedShape.hxx> |
4e57c75e |
38 | |
3510db62 |
39 | |
4e57c75e |
40 | //======================================================================= |
41 | //function : |
42 | //purpose : |
43 | //======================================================================= |
796a784d |
44 | BOPAlgo_Builder::BOPAlgo_Builder() |
4e57c75e |
45 | : |
46 | BOPAlgo_BuilderShape(), |
47 | myArguments(myAllocator), |
48 | myMapFence(100, myAllocator), |
49 | myPaveFiller(NULL), |
50 | myDS(NULL), |
4e57c75e |
51 | myEntryPoint(0), |
52 | myImages(100, myAllocator), |
53 | myShapesSD(100, myAllocator), |
b1d15f53 |
54 | myOrigins(100, myAllocator), |
13c0e402 |
55 | myInParts(100, myAllocator), |
483ce1bd |
56 | myNonDestructive(Standard_False), |
81a55a69 |
57 | myGlue(BOPAlgo_GlueOff), |
58 | myCheckInverted(Standard_True) |
4e57c75e |
59 | { |
60 | } |
61 | //======================================================================= |
62 | //function : |
63 | //purpose : |
64 | //======================================================================= |
796a784d |
65 | BOPAlgo_Builder::BOPAlgo_Builder |
66 | (const Handle(NCollection_BaseAllocator)& theAllocator) |
4e57c75e |
67 | : |
68 | BOPAlgo_BuilderShape(theAllocator), |
69 | myArguments(myAllocator), |
70 | myMapFence(100, myAllocator), |
71 | myPaveFiller(NULL), |
72 | myDS(NULL), |
4e57c75e |
73 | myEntryPoint(0), |
74 | myImages(100, myAllocator), |
75 | myShapesSD(100, myAllocator), |
b1d15f53 |
76 | myOrigins(100, myAllocator), |
13c0e402 |
77 | myInParts(100, myAllocator), |
483ce1bd |
78 | myNonDestructive(Standard_False), |
81a55a69 |
79 | myGlue(BOPAlgo_GlueOff), |
80 | myCheckInverted(Standard_True) |
4e57c75e |
81 | { |
82 | } |
83 | //======================================================================= |
84 | //function : ~ |
85 | //purpose : |
86 | //======================================================================= |
796a784d |
87 | BOPAlgo_Builder::~BOPAlgo_Builder() |
4e57c75e |
88 | { |
89 | if (myEntryPoint==1) { |
90 | if (myPaveFiller) { |
91 | delete myPaveFiller; |
92 | myPaveFiller=NULL; |
93 | } |
94 | } |
95 | } |
96 | //======================================================================= |
97 | //function : Clear |
98 | //purpose : |
99 | //======================================================================= |
796a784d |
100 | void BOPAlgo_Builder::Clear() |
4e57c75e |
101 | { |
948fe6ca |
102 | BOPAlgo_BuilderShape::Clear(); |
4e57c75e |
103 | myArguments.Clear(); |
104 | myMapFence.Clear(); |
105 | myImages.Clear(); |
106 | myShapesSD.Clear(); |
4e57c75e |
107 | myOrigins.Clear(); |
13c0e402 |
108 | myInParts.Clear(); |
4e57c75e |
109 | } |
110 | //======================================================================= |
111 | //function : AddArgument |
112 | //purpose : |
113 | //======================================================================= |
796a784d |
114 | void BOPAlgo_Builder::AddArgument(const TopoDS_Shape& theShape) |
4e57c75e |
115 | { |
116 | if (myMapFence.Add(theShape)) { |
117 | myArguments.Append(theShape); |
118 | } |
119 | } |
120 | //======================================================================= |
92ae0f2f |
121 | //function : SetArguments |
122 | //purpose : |
123 | //======================================================================= |
1155d05a |
124 | void BOPAlgo_Builder::SetArguments(const TopTools_ListOfShape& theShapes) |
92ae0f2f |
125 | { |
1155d05a |
126 | TopTools_ListIteratorOfListOfShape aIt; |
92ae0f2f |
127 | // |
49b0c452 |
128 | myArguments.Clear(); |
129 | // |
92ae0f2f |
130 | aIt.Initialize(theShapes); |
131 | for (; aIt.More(); aIt.Next()) { |
132 | const TopoDS_Shape& aS = aIt.Value(); |
133 | AddArgument(aS); |
134 | } |
135 | } |
136 | //======================================================================= |
4e57c75e |
137 | // function: CheckData |
138 | // purpose: |
139 | //======================================================================= |
796a784d |
140 | void BOPAlgo_Builder::CheckData() |
4e57c75e |
141 | { |
33ba8565 |
142 | Standard_Integer aNb = myArguments.Extent(); |
4e57c75e |
143 | if (aNb<2) { |
33ba8565 |
144 | AddError (new BOPAlgo_AlertTooFewArguments); // too few arguments to process |
4e57c75e |
145 | return; |
146 | } |
147 | // |
33ba8565 |
148 | CheckFiller(); |
149 | } |
150 | //======================================================================= |
151 | // function: CheckFiller |
152 | // purpose: |
153 | //======================================================================= |
154 | void BOPAlgo_Builder::CheckFiller() |
155 | { |
4e57c75e |
156 | if (!myPaveFiller) { |
33ba8565 |
157 | AddError (new BOPAlgo_AlertNoFiller); |
4e57c75e |
158 | return; |
159 | } |
33ba8565 |
160 | GetReport()->Merge (myPaveFiller->GetReport()); |
4e57c75e |
161 | } |
33ba8565 |
162 | |
4e57c75e |
163 | //======================================================================= |
164 | //function : Prepare |
165 | //purpose : |
166 | //======================================================================= |
796a784d |
167 | void BOPAlgo_Builder::Prepare() |
4e57c75e |
168 | { |
4e57c75e |
169 | BRep_Builder aBB; |
170 | TopoDS_Compound aC; |
171 | // |
172 | // 1. myShape is empty compound |
173 | aBB.MakeCompound(aC); |
174 | myShape=aC; |
4e57c75e |
175 | } |
176 | //======================================================================= |
177 | //function : Perform |
178 | //purpose : |
179 | //======================================================================= |
796a784d |
180 | void BOPAlgo_Builder::Perform() |
4e57c75e |
181 | { |
33ba8565 |
182 | GetReport()->Clear(); |
4e57c75e |
183 | // |
184 | if (myEntryPoint==1) { |
185 | if (myPaveFiller) { |
186 | delete myPaveFiller; |
187 | myPaveFiller=NULL; |
188 | } |
189 | } |
190 | // |
488e5b9d |
191 | Handle(NCollection_BaseAllocator) aAllocator= |
192 | NCollection_BaseAllocator::CommonBaseAllocator(); |
4e57c75e |
193 | // |
194 | BOPAlgo_PaveFiller* pPF=new BOPAlgo_PaveFiller(aAllocator); |
195 | // |
196 | pPF->SetArguments(myArguments); |
92ae0f2f |
197 | pPF->SetRunParallel(myRunParallel); |
b1d15f53 |
198 | pPF->SetProgressIndicator(myProgressIndicator); |
199 | pPF->SetFuzzyValue(myFuzzyValue); |
3510db62 |
200 | pPF->SetNonDestructive(myNonDestructive); |
483ce1bd |
201 | pPF->SetGlue(myGlue); |
944768d2 |
202 | pPF->SetUseOBB(myUseOBB); |
4e57c75e |
203 | // |
204 | pPF->Perform(); |
205 | // |
206 | myEntryPoint=1; |
207 | PerformInternal(*pPF); |
208 | } |
209 | //======================================================================= |
210 | //function : PerformWithFiller |
211 | //purpose : |
212 | //======================================================================= |
796a784d |
213 | void BOPAlgo_Builder::PerformWithFiller(const BOPAlgo_PaveFiller& theFiller) |
4e57c75e |
214 | { |
33ba8565 |
215 | GetReport()->Clear(); |
4e57c75e |
216 | myEntryPoint=0; |
3510db62 |
217 | myNonDestructive = theFiller.NonDestructive(); |
218 | myFuzzyValue = theFiller.FuzzyValue(); |
483ce1bd |
219 | myGlue = theFiller.Glue(); |
944768d2 |
220 | myUseOBB = theFiller.UseOBB(); |
4e57c75e |
221 | PerformInternal(theFiller); |
222 | } |
223 | //======================================================================= |
224 | //function : PerformInternal |
225 | //purpose : |
226 | //======================================================================= |
796a784d |
227 | void BOPAlgo_Builder::PerformInternal(const BOPAlgo_PaveFiller& theFiller) |
36f4947b |
228 | { |
33ba8565 |
229 | GetReport()->Clear(); |
230 | // |
231 | try { |
36f4947b |
232 | OCC_CATCH_SIGNALS |
233 | PerformInternal1(theFiller); |
234 | } |
235 | // |
236 | catch (Standard_Failure) { |
33ba8565 |
237 | AddError (new BOPAlgo_AlertBuilderFailed); |
238 | } |
36f4947b |
239 | } |
240 | //======================================================================= |
241 | //function : PerformInternal1 |
242 | //purpose : |
243 | //======================================================================= |
244 | void BOPAlgo_Builder::PerformInternal1(const BOPAlgo_PaveFiller& theFiller) |
4e57c75e |
245 | { |
4e57c75e |
246 | myPaveFiller=(BOPAlgo_PaveFiller*)&theFiller; |
247 | myDS=myPaveFiller->PDS(); |
248 | myContext=myPaveFiller->Context(); |
0d0481c7 |
249 | myFuzzyValue = myPaveFiller->FuzzyValue(); |
250 | myNonDestructive = myPaveFiller->NonDestructive(); |
4e57c75e |
251 | // |
252 | // 1. CheckData |
253 | CheckData(); |
33ba8565 |
254 | if (HasErrors()) { |
4e57c75e |
255 | return; |
256 | } |
257 | // |
258 | // 2. Prepare |
259 | Prepare(); |
33ba8565 |
260 | if (HasErrors()) { |
4e57c75e |
261 | return; |
262 | } |
263 | // |
264 | // 3. Fill Images |
265 | // 3.1 Vertice |
266 | FillImagesVertices(); |
33ba8565 |
267 | if (HasErrors()) { |
4e57c75e |
268 | return; |
269 | } |
270 | // |
271 | BuildResult(TopAbs_VERTEX); |
33ba8565 |
272 | if (HasErrors()) { |
4e57c75e |
273 | return; |
274 | } |
275 | // 3.2 Edges |
276 | FillImagesEdges(); |
33ba8565 |
277 | if (HasErrors()) { |
4e57c75e |
278 | return; |
279 | } |
280 | // |
281 | BuildResult(TopAbs_EDGE); |
33ba8565 |
282 | if (HasErrors()) { |
4e57c75e |
283 | return; |
284 | } |
285 | // |
286 | // 3.3 Wires |
287 | FillImagesContainers(TopAbs_WIRE); |
33ba8565 |
288 | if (HasErrors()) { |
4e57c75e |
289 | return; |
290 | } |
291 | // |
292 | BuildResult(TopAbs_WIRE); |
33ba8565 |
293 | if (HasErrors()) { |
4e57c75e |
294 | return; |
295 | } |
296 | |
297 | // 3.4 Faces |
298 | FillImagesFaces(); |
33ba8565 |
299 | if (HasErrors()) { |
4e57c75e |
300 | return; |
301 | } |
302 | // |
303 | BuildResult(TopAbs_FACE); |
33ba8565 |
304 | if (HasErrors()) { |
4e57c75e |
305 | return; |
306 | } |
307 | // 3.5 Shells |
308 | FillImagesContainers(TopAbs_SHELL); |
33ba8565 |
309 | if (HasErrors()) { |
4e57c75e |
310 | return; |
311 | } |
312 | |
313 | BuildResult(TopAbs_SHELL); |
33ba8565 |
314 | if (HasErrors()) { |
4e57c75e |
315 | return; |
316 | } |
317 | // 3.6 Solids |
318 | FillImagesSolids(); |
33ba8565 |
319 | if (HasErrors()) { |
4e57c75e |
320 | return; |
321 | } |
322 | |
323 | BuildResult(TopAbs_SOLID); |
33ba8565 |
324 | if (HasErrors()) { |
4e57c75e |
325 | return; |
326 | } |
327 | // 3.7 CompSolids |
328 | FillImagesContainers(TopAbs_COMPSOLID); |
33ba8565 |
329 | if (HasErrors()) { |
4e57c75e |
330 | return; |
331 | } |
332 | |
333 | BuildResult(TopAbs_COMPSOLID); |
33ba8565 |
334 | if (HasErrors()) { |
4e57c75e |
335 | return; |
336 | } |
337 | |
338 | // 3.8 Compounds |
339 | FillImagesCompounds(); |
33ba8565 |
340 | if (HasErrors()) { |
4e57c75e |
341 | return; |
342 | } |
343 | |
344 | BuildResult(TopAbs_COMPOUND); |
33ba8565 |
345 | if (HasErrors()) { |
4e57c75e |
346 | return; |
347 | } |
348 | // |
349 | // 4.History |
350 | PrepareHistory(); |
351 | // |
352 | // |
353 | // 5 Post-treatment |
354 | PostTreat(); |
355 | |
356 | } |
4e57c75e |
357 | //======================================================================= |
358 | //function : PostTreat |
359 | //purpose : |
360 | //======================================================================= |
796a784d |
361 | void BOPAlgo_Builder::PostTreat() |
4e57c75e |
362 | { |
3510db62 |
363 | Standard_Integer i, aNbS; |
364 | TopAbs_ShapeEnum aType; |
1155d05a |
365 | TopTools_IndexedMapOfShape aMA; |
3510db62 |
366 | if (myPaveFiller->NonDestructive()) { |
367 | // MapToAvoid |
368 | aNbS=myDS->NbSourceShapes(); |
369 | for (i=0; i<aNbS; ++i) { |
370 | const BOPDS_ShapeInfo& aSI=myDS->ShapeInfo(i); |
371 | aType=aSI.ShapeType(); |
372 | if (aType==TopAbs_VERTEX || |
373 | aType==TopAbs_EDGE|| |
374 | aType==TopAbs_FACE) { |
375 | const TopoDS_Shape& aS=aSI.Shape(); |
376 | aMA.Add(aS); |
377 | } |
378 | } |
379 | } |
380 | // |
381 | BOPTools_AlgoTools::CorrectTolerances(myShape, aMA, 0.05, myRunParallel); |
382 | BOPTools_AlgoTools::CorrectShapeTolerances(myShape, aMA, myRunParallel); |
4e57c75e |
383 | } |
13c0e402 |
384 | |
385 | //======================================================================= |
386 | //function : BuildBOP |
387 | //purpose : |
388 | //======================================================================= |
389 | void BOPAlgo_Builder::BuildBOP(const TopTools_ListOfShape& theObjects, |
390 | const TopAbs_State theObjState, |
391 | const TopTools_ListOfShape& theTools, |
392 | const TopAbs_State theToolsState, |
393 | Handle(Message_Report) theReport) |
394 | { |
395 | if (HasErrors()) |
396 | return; |
397 | |
398 | // Report for the method |
399 | Handle(Message_Report) aReport = theReport.IsNull() ? myReport : theReport; |
400 | |
401 | if (myArguments.IsEmpty() || myShape.IsNull()) |
402 | { |
403 | aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBuilderFailed()); |
404 | return; |
405 | } |
406 | |
407 | // Check the input data |
408 | if ((theObjState != TopAbs_IN && theObjState != TopAbs_OUT) || |
409 | (theToolsState != TopAbs_IN && theToolsState != TopAbs_OUT)) |
410 | { |
411 | aReport->AddAlert(Message_Fail, new BOPAlgo_AlertBOPNotSet()); |
412 | return; |
413 | } |
414 | |
415 | // Check input shapes |
416 | Standard_Boolean hasObjects = !theObjects.IsEmpty(); |
417 | Standard_Boolean hasTools = !theTools .IsEmpty(); |
418 | if (!hasObjects && !hasTools) |
419 | { |
420 | aReport->AddAlert(Message_Fail, new BOPAlgo_AlertTooFewArguments()); |
421 | return; |
422 | } |
423 | |
424 | // Check that all input solids are from the arguments |
425 | for (Standard_Integer i = 0; i < 2; ++i) |
426 | { |
427 | const TopTools_ListOfShape& aList = !i ? theObjects : theTools; |
428 | TopTools_ListOfShape::Iterator itLS(aList); |
429 | for (; itLS.More(); itLS.Next()) |
430 | { |
431 | const TopoDS_Shape& aS = itLS.Value(); |
432 | // Check if the shape belongs to the arguments of operation |
433 | if (myDS->Index(aS) < 0) |
434 | { |
435 | aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnknownShape(aS)); |
436 | return; |
437 | } |
438 | |
439 | // Check if the shape is a solid or collection of them |
440 | if (aS.ShapeType() != TopAbs_SOLID) |
441 | { |
442 | TopTools_ListOfShape aLS; |
443 | TopTools_MapOfShape aMFence; |
444 | BOPAlgo_Tools::TreatCompound(aS, aMFence, aLS); |
445 | |
446 | TopTools_ListOfShape::Iterator it(aLS); |
447 | for (; it.More(); it.Next()) |
448 | { |
449 | const TopoDS_Shape& aSx = it.Value(); |
450 | if (aSx.ShapeType() != TopAbs_SOLID && |
451 | aSx.ShapeType() != TopAbs_COMPSOLID) |
452 | { |
453 | aReport->AddAlert(Message_Fail, new BOPAlgo_AlertUnsupportedType(aS)); |
454 | return; |
455 | } |
456 | } |
457 | } |
458 | } |
459 | } |
460 | |
461 | // Classification of the faces relatively solids has been made |
462 | // on the stage of Solids splitting. All results are saved into |
463 | // myInParts map, which connects the solids with its IN faces from |
464 | // other arguments. All faces not contained in the list of IN faces |
465 | // will be considered as OUT. |
466 | |
467 | // Prepare the maps of splits of solids faces with orientations |
468 | TopTools_IndexedMapOfOrientedShape aMObjFacesOri, aMToolFacesOri; |
469 | // Prepare the maps of splits of solids faces |
470 | TopTools_IndexedMapOfShape aMObjFaces, aMToolFaces; |
471 | // Copy the list of IN faces of the solids into map |
472 | TopTools_MapOfShape anINObjects, anINTools; |
473 | |
474 | for (Standard_Integer i = 0; i < 2; ++i) |
475 | { |
476 | const TopTools_ListOfShape& aList = !i ? theObjects : theTools; |
477 | TopTools_IndexedMapOfOrientedShape& aMapOri = !i ? aMObjFacesOri : aMToolFacesOri; |
478 | TopTools_IndexedMapOfShape& aMap = !i ? aMObjFaces : aMToolFaces; |
479 | TopTools_ListOfShape::Iterator itLS(aList); |
480 | for (; itLS.More(); itLS.Next()) |
481 | { |
482 | const TopoDS_Shape& aShape = itLS.Value(); |
483 | TopExp_Explorer expS(aShape, TopAbs_SOLID); |
484 | for (; expS.More(); expS.Next()) |
485 | { |
486 | const TopoDS_Shape& aS = expS.Current(); |
487 | TopExp_Explorer expF(aS, TopAbs_FACE); |
488 | for (; expF.More(); expF.Next()) |
489 | { |
490 | const TopoDS_Shape& aF = expF.Current(); |
491 | if (aF.Orientation() != TopAbs_FORWARD && |
492 | aF.Orientation() != TopAbs_REVERSED) |
493 | continue; |
494 | const TopTools_ListOfShape* pLFIm = myImages.Seek(aF); |
495 | if (pLFIm) |
496 | { |
497 | TopTools_ListOfShape::Iterator itLFIm(*pLFIm); |
498 | for (; itLFIm.More(); itLFIm.Next()) |
499 | { |
500 | TopoDS_Face aFIm = TopoDS::Face(itLFIm.Value()); |
501 | if (BOPTools_AlgoTools::IsSplitToReverse(aFIm, aF, myContext)) |
502 | aFIm.Reverse(); |
503 | aMapOri.Add(aFIm); |
504 | aMap.Add(aFIm); |
505 | } |
506 | } |
507 | else |
508 | { |
509 | aMapOri.Add(aF); |
510 | aMap.Add(aF); |
511 | } |
512 | } |
513 | |
514 | // Copy the list of IN faces into a map |
515 | const TopTools_ListOfShape* pLFIN = myInParts.Seek(aS); |
516 | if (pLFIN) |
517 | { |
518 | TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools; |
519 | TopTools_ListOfShape::Iterator itLFIn(*pLFIN); |
520 | for (; itLFIn.More(); itLFIn.Next()) |
521 | anINMap.Add(itLFIn.Value()); |
522 | } |
523 | } |
524 | } |
525 | } |
526 | |
527 | // Now we need to select all faces which will participate in |
528 | // building of the resulting solids. The final set of faces |
529 | // depends on the given states for the groups. |
530 | Standard_Boolean isObjectsIN = (theObjState == TopAbs_IN), |
531 | isToolsIN = (theToolsState == TopAbs_IN); |
532 | |
533 | // Shortcuts |
534 | Standard_Boolean bAvoidIN = (!isObjectsIN && !isToolsIN), // avoid all in faces |
535 | bAvoidINforBoth = (isObjectsIN != isToolsIN); // avoid faces IN for both groups |
536 | |
537 | // Choose which SD faces are needed to be taken - equally or differently oriented faces |
538 | Standard_Boolean isSameOriNeeded = (theObjState == theToolsState); |
539 | // Resulting faces |
540 | TopTools_IndexedMapOfOrientedShape aMResFacesOri; |
541 | TopTools_MapOfShape aMResFacesFence; |
542 | // Fence map |
543 | TopTools_MapOfShape aMFence, aMFToAvoid; |
544 | // Oriented fence map |
545 | TopTools_MapOfOrientedShape aMFenceOri; |
546 | |
547 | for (Standard_Integer i = 0; i < 2; ++i) |
548 | { |
549 | const TopTools_IndexedMapOfOrientedShape& aMap = !i ? aMObjFacesOri : aMToolFacesOri; |
550 | const TopTools_IndexedMapOfShape& anOppositeMap = !i ? aMToolFaces : aMObjFaces; |
551 | const TopTools_MapOfShape& anINMap = !i ? anINObjects : anINTools; |
552 | const TopTools_MapOfShape& anOppositeINMap = !i ? anINTools : anINObjects; |
553 | const Standard_Boolean bTakeIN = !i ? isObjectsIN : isToolsIN; |
554 | |
555 | const Standard_Integer aNbF = aMap.Extent(); |
556 | for (Standard_Integer j = 1; j <= aNbF; ++j) |
557 | { |
558 | TopoDS_Shape aFIm = aMap(j); |
559 | |
560 | Standard_Boolean isIN = anINMap.Contains(aFIm); |
561 | Standard_Boolean isINOpposite = anOppositeINMap.Contains(aFIm); |
562 | |
563 | // Filtering for FUSE - avoid any IN faces |
564 | if (bAvoidIN && (isIN || isINOpposite)) |
565 | continue; |
566 | |
567 | // Filtering for CUT - avoid faces IN for both groups |
568 | if (bAvoidINforBoth && isIN && isINOpposite) |
569 | continue; |
570 | |
571 | // Treatment of SD faces |
572 | if (!aMFence.Add(aFIm)) |
573 | { |
574 | if (!anOppositeMap.Contains(aFIm)) |
575 | { |
576 | // The face belongs to only one group |
577 | if (bTakeIN != isSameOriNeeded) |
578 | aMFToAvoid.Add(aFIm); |
579 | } |
580 | else |
581 | { |
582 | // The face belongs to both groups. |
583 | // Using its orientation decide if it is needed in the result or not. |
584 | Standard_Boolean isSameOri = !aMFenceOri.Add(aFIm); |
585 | if (isSameOriNeeded == isSameOri) |
586 | { |
587 | // Take the shape without classification |
588 | if (aMResFacesFence.Add(aFIm)) |
589 | aMResFacesOri.Add(aFIm); |
590 | } |
591 | else |
592 | // Remove the face |
593 | aMFToAvoid.Add(aFIm); |
594 | |
595 | continue; |
596 | } |
597 | } |
598 | if (!aMFenceOri.Add(aFIm)) |
599 | continue; |
600 | |
601 | if (bTakeIN == isINOpposite) |
602 | { |
603 | if (isIN) |
604 | { |
605 | aMResFacesOri.Add(aFIm); |
606 | aMResFacesOri.Add(aFIm.Reversed()); |
607 | } |
608 | else if (bTakeIN && !isSameOriNeeded) |
609 | aMResFacesOri.Add(aFIm.Reversed()); |
610 | else |
611 | aMResFacesOri.Add(aFIm); |
612 | aMResFacesFence.Add(aFIm); |
613 | } |
614 | } |
615 | } |
616 | |
617 | // Remove the faces which has to be avoided |
618 | TopTools_ListOfShape aResFaces; |
619 | const Standard_Integer aNbRF = aMResFacesOri.Extent(); |
620 | for (Standard_Integer i = 1; i <= aNbRF; ++i) |
621 | { |
622 | const TopoDS_Shape& aRF = aMResFacesOri(i); |
623 | if (!aMFToAvoid.Contains(aRF)) |
624 | aResFaces.Append(aRF); |
625 | } |
626 | |
627 | BRep_Builder aBB; |
628 | |
629 | // Try to build closed solids from the faces |
630 | BOPAlgo_BuilderSolid aBS; |
631 | aBS.SetShapes(aResFaces); |
632 | aBS.SetRunParallel(myRunParallel); |
633 | aBS.SetContext(myContext); |
634 | aBS.SetFuzzyValue(myFuzzyValue); |
635 | aBS.SetProgressIndicator(myProgressIndicator); |
636 | aBS.Perform(); |
637 | |
638 | // Resulting solids |
639 | TopTools_ListOfShape aResSolids; |
640 | |
641 | aMFence.Clear(); |
642 | if (!aBS.HasErrors()) |
643 | { |
644 | // If any, add solids into resulting compound |
645 | TopTools_ListIteratorOfListOfShape itA(aBS.Areas()); |
646 | for (; itA.More(); itA.Next()) |
647 | { |
648 | const TopoDS_Shape& aSolid = itA.Value(); |
649 | // The solid must contain at least one face |
650 | // from either of objects or tools |
651 | TopExp_Explorer expF(aSolid, TopAbs_FACE); |
652 | for (; expF.More(); expF.Next()) |
653 | { |
654 | const TopoDS_Shape& aF = expF.Current(); |
655 | if (aMObjFacesOri.Contains(aF) || aMToolFacesOri.Contains(aF)) |
656 | break; |
657 | } |
658 | if (expF.More()) |
659 | { |
660 | aResSolids.Append(aSolid); |
661 | TopExp::MapShapes(aSolid, aMFence); |
662 | } |
663 | } |
664 | } |
665 | |
666 | // Collect unused faces |
667 | TopoDS_Compound anUnUsedFaces; |
668 | aBB.MakeCompound(anUnUsedFaces); |
669 | |
670 | TopTools_ListOfShape::Iterator itLF(aResFaces); |
671 | for (; itLF.More(); itLF.Next()) |
672 | { |
673 | if (aMFence.Add(itLF.Value())) |
674 | aBB.Add(anUnUsedFaces, itLF.Value()); |
675 | } |
676 | |
677 | // Build blocks from the unused faces |
678 | TopTools_ListOfShape aLCB; |
679 | BOPTools_AlgoTools::MakeConnexityBlocks(anUnUsedFaces, TopAbs_EDGE, TopAbs_FACE, aLCB); |
680 | |
681 | // Build solid from each block |
682 | TopTools_ListIteratorOfListOfShape itCB(aLCB); |
683 | for (; itCB.More(); itCB.Next()) |
684 | { |
685 | const TopoDS_Shape& aCB = itCB.Value(); |
686 | TopoDS_Shell aShell; |
687 | aBB.MakeShell(aShell); |
688 | // Add faces of the block to the shell |
689 | TopExp_Explorer anExpF(aCB, TopAbs_FACE); |
690 | for (; anExpF.More(); anExpF.Next()) |
691 | aBB.Add(aShell, TopoDS::Face(anExpF.Current())); |
692 | |
693 | BOPTools_AlgoTools::OrientFacesOnShell(aShell); |
694 | // Make solid out of the shell |
695 | TopoDS_Solid aSolid; |
696 | aBB.MakeSolid(aSolid); |
697 | aBB.Add(aSolid, aShell); |
698 | // Add new solid to result |
699 | aResSolids.Append(aSolid); |
700 | } |
701 | |
702 | if (!bAvoidIN) |
703 | { |
704 | // Fill solids with internal parts coming with the solids |
705 | TopTools_ListOfShape anInParts; |
706 | for (Standard_Integer i = 0; i < 2; ++i) |
707 | { |
708 | const TopTools_ListOfShape& aList = !i ? theObjects : theTools; |
709 | TopTools_ListOfShape::Iterator itLS(aList); |
710 | for (; itLS.More(); itLS.Next()) |
711 | { |
712 | TopExp_Explorer expS(itLS.Value(), TopAbs_SOLID); |
713 | for (; expS.More(); expS.Next()) |
714 | { |
715 | const TopoDS_Shape& aS = expS.Current(); // Solid |
716 | for (TopoDS_Iterator it(aS); it.More(); it.Next()) |
717 | { |
718 | const TopoDS_Shape& aSInt = it.Value(); |
719 | if (aSInt.Orientation() == TopAbs_INTERNAL) |
720 | anInParts.Append(aSInt); // vertex or edge |
721 | else |
722 | { |
723 | // shell treatment |
724 | TopoDS_Iterator itInt(aSInt); |
725 | if (itInt.More() && itInt.Value().Orientation() == TopAbs_INTERNAL) |
726 | anInParts.Append(aSInt); |
727 | } |
728 | } |
729 | } |
730 | } |
731 | } |
732 | |
733 | BOPAlgo_Tools::FillInternals(aResSolids, anInParts, myImages, myContext); |
734 | } |
735 | |
736 | // Combine solids into compound |
737 | TopoDS_Shape aResult; |
738 | aBB.MakeCompound(TopoDS::Compound(aResult)); |
739 | |
740 | TopTools_ListOfShape::Iterator itLS(aResSolids); |
741 | for (; itLS.More(); itLS.Next()) |
742 | aBB.Add(aResult, itLS.Value()); |
743 | |
744 | myShape = aResult; |
745 | PrepareHistory(); |
746 | } |