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