0029322: Unify faces classification procedures in Boolean Operations
[occt.git] / src / BOPAlgo / BOPAlgo_BuilderSolid.cxx
CommitLineData
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.
465d1fba 17//
42cf5bc1 18#include <BOPAlgo_BuilderSolid.hxx>
19#include <BOPAlgo_ShellSplitter.hxx>
33ba8565 20#include <BOPAlgo_Alerts.hxx>
b7cd7c2b 21#include <BOPAlgo_Tools.hxx>
42cf5bc1 22#include <BOPCol_BoxBndTree.hxx>
23#include <BOPCol_DataMapOfShapeListOfShape.hxx>
24#include <BOPCol_DataMapOfShapeShape.hxx>
25#include <BOPCol_IndexedDataMapOfShapeListOfShape.hxx>
319da2e4 26#include <BOPCol_IndexedDataMapOfShapeShape.hxx>
42cf5bc1 27#include <BOPCol_ListOfInteger.hxx>
28#include <BOPCol_ListOfShape.hxx>
29#include <BOPCol_MapOfOrientedShape.hxx>
30#include <BOPCol_MapOfShape.hxx>
31#include <BOPCol_NCVector.hxx>
32#include <BOPCol_Parallel.hxx>
33#include <BOPTools.hxx>
34#include <BOPTools_AlgoTools.hxx>
35#include <BOPTools_AlgoTools3D.hxx>
36#include <BOPTools_CoupleOfShape.hxx>
37#include <BRep_Builder.hxx>
38#include <BRep_Tool.hxx>
39#include <BRepBndLib.hxx>
40#include <BRepClass3d_SolidClassifier.hxx>
41#include <Geom2d_Curve.hxx>
42#include <Geom_Curve.hxx>
43#include <Geom_Surface.hxx>
4e57c75e 44#include <gp_Dir.hxx>
42cf5bc1 45#include <gp_Pln.hxx>
4e57c75e 46#include <gp_Pnt.hxx>
42cf5bc1 47#include <gp_Pnt2d.hxx>
48#include <gp_Vec.hxx>
49#include <IntTools_Context.hxx>
50#include <NCollection_DataMap.hxx>
42cf5bc1 51#include <NCollection_List.hxx>
52#include <NCollection_UBTreeFiller.hxx>
682c9d06 53#include <TColStd_MapIntegerHasher.hxx>
4e57c75e 54#include <TopAbs.hxx>
42cf5bc1 55#include <TopExp.hxx>
56#include <TopExp_Explorer.hxx>
b7cd7c2b 57#include <TopoDS.hxx>
42cf5bc1 58#include <TopoDS_Compound.hxx>
59#include <TopoDS_Edge.hxx>
4e57c75e 60#include <TopoDS_Face.hxx>
42cf5bc1 61#include <TopoDS_Iterator.hxx>
4e57c75e 62#include <TopoDS_Shape.hxx>
63#include <TopoDS_Shell.hxx>
4e57c75e 64#include <TopoDS_Solid.hxx>
65#include <TopoDS_Vertex.hxx>
4e57c75e 66
42cf5bc1 67//
4e57c75e 68static
69 Standard_Boolean IsGrowthShell(const TopoDS_Shape& ,
70 const BOPCol_IndexedMapOfShape& );
71static
72 Standard_Boolean IsHole(const TopoDS_Shape& ,
1e143abb 73 Handle(IntTools_Context)& );
4e57c75e 74static
75 Standard_Boolean IsInside(const TopoDS_Shape& ,
76 const TopoDS_Shape& ,
1e143abb 77 Handle(IntTools_Context)& );
4e57c75e 78static
319da2e4 79 void MakeInternalShells(const BOPCol_IndexedMapOfShape& ,
4e57c75e 80 BOPCol_ListOfShape& );
81
465d1fba 82//=======================================================================
4e57c75e 83//function :
84//purpose :
85//=======================================================================
682c9d06 86BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid()
4e57c75e 87:
88 BOPAlgo_BuilderArea()
89{
90}
91//=======================================================================
92//function :
93//purpose :
94//=======================================================================
682c9d06 95BOPAlgo_BuilderSolid::BOPAlgo_BuilderSolid
96 (const Handle(NCollection_BaseAllocator)& theAllocator)
4e57c75e 97:
98 BOPAlgo_BuilderArea(theAllocator)
99{
100}
101//=======================================================================
102//function : ~
103//purpose :
104//=======================================================================
30ecd5f8 105BOPAlgo_BuilderSolid::~BOPAlgo_BuilderSolid()
4e57c75e 106{
107}
108//=======================================================================
30ecd5f8 109//function : SetSolid
110//purpose :
111//=======================================================================
112void BOPAlgo_BuilderSolid::SetSolid(const TopoDS_Solid& aS)
113{
114 mySolid=aS;
115}
116//=======================================================================
117//function : Solid
118//purpose :
119//=======================================================================
120const TopoDS_Solid& BOPAlgo_BuilderSolid::Solid()const
121{
122 return mySolid;
123}
124//=======================================================================
4e57c75e 125//function : Perform
126//purpose :
127//=======================================================================
30ecd5f8 128void BOPAlgo_BuilderSolid::Perform()
4e57c75e 129{
33ba8565 130 GetReport()->Clear();
4e57c75e 131 //
98b37659 132 if (myShapes.IsEmpty())
133 return;
134
4e57c75e 135 if (myContext.IsNull()) {
1e143abb 136 myContext=new IntTools_Context;
4e57c75e 137 }
b7cd7c2b 138
139 myBoxes.Clear();
140
4e57c75e 141 TopoDS_Compound aC;
142 BRep_Builder aBB;
143 BOPCol_ListIteratorOfListOfShape aIt;
144 //
145 aBB.MakeCompound(aC);
146 aIt.Initialize(myShapes);
147 for(; aIt.More(); aIt.Next()) {
148 const TopoDS_Shape& aF=aIt.Value();
149 aBB.Add(aC, aF);
150 }
151 //
36f4947b 152 UserBreak();
4e57c75e 153 //
154 PerformShapesToAvoid();
33ba8565 155 if (HasErrors()) {
4e57c75e 156 return;
157 }
158 //
36f4947b 159 UserBreak();
160 //
4e57c75e 161 PerformLoops();
33ba8565 162 if (HasErrors()) {
4e57c75e 163 return;
164 }
36f4947b 165 //
166 UserBreak();
167 //
4e57c75e 168 PerformAreas();
33ba8565 169 if (HasErrors()) {
4e57c75e 170 return;
171 }
36f4947b 172 //
173 UserBreak();
174 //
4e57c75e 175 PerformInternalShapes();
33ba8565 176 if (HasErrors()) {
4e57c75e 177 return;
178 }
179}
180//=======================================================================
181//function :PerformShapesToAvoid
182//purpose :
183//=======================================================================
30ecd5f8 184void BOPAlgo_BuilderSolid::PerformShapesToAvoid()
4e57c75e 185{
186 Standard_Boolean bFound;
187 Standard_Integer i, iCnt, aNbE, aNbF;
188 TopAbs_Orientation aOrE;
189 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
190 BOPCol_ListIteratorOfListOfShape aIt;
191 //
192 myShapesToAvoid.Clear();
193 //
194 iCnt=0;
302f96fb 195 for(;;) {
4e57c75e 196 ++iCnt;
197 bFound=Standard_False;
198 //
199 // 1. MEF
200 aMEF.Clear();
201 aIt.Initialize (myShapes);
202 for (; aIt.More(); aIt.Next()) {
203 const TopoDS_Shape& aF=aIt.Value();
204 if (!myShapesToAvoid.Contains(aF)) {
465d1fba 205 BOPTools::MapShapesAndAncestors(aF,
206 TopAbs_EDGE,
207 TopAbs_FACE,
208 aMEF);
4e57c75e 209 }
4e57c75e 210 }
211 aNbE=aMEF.Extent();
212 //
213 // 2. myFacesToAvoid
214 for (i=1; i<=aNbE; ++i) {
215 const TopoDS_Edge& aE=(*(TopoDS_Edge*)(&aMEF.FindKey(i)));
216 if (BRep_Tool::Degenerated(aE)) {
217 continue;
218 }
219 //
220 BOPCol_ListOfShape& aLF=aMEF.ChangeFromKey(aE);
221 aNbF=aLF.Extent();
222 if (!aNbF) {
223 continue;
224 }
225 //
226 aOrE=aE.Orientation();
227 //
228 const TopoDS_Face& aF1=(*(TopoDS_Face*)(&aLF.First()));
229 if (aNbF==1) {
230 if (aOrE==TopAbs_INTERNAL) {
231 continue;
232 }
233 bFound=Standard_True;
234 myShapesToAvoid.Add(aF1);
235 }
236 else if (aNbF==2) {
237 const TopoDS_Face& aF2=(*(TopoDS_Face*)(&aLF.Last()));
238 if (aF2.IsSame(aF1)) {
239 if (BRep_Tool::IsClosed(aE, aF1)) {
240 continue;
241 }
242 //
243 if (aOrE==TopAbs_INTERNAL) {
244 continue;
245 }
246 //
247 bFound=Standard_True;
248 myShapesToAvoid.Add(aF1);
249 myShapesToAvoid.Add(aF2);
250 }
251 }
252 }// for (i=1; i<=aNbE; ++i) {
253 //
254 if (!bFound) {
255 break;
256 }
257 //
682c9d06 258 }//for(;;) {
4e57c75e 259}
260//=======================================================================
261//function : PerformLoops
262//purpose :
263//=======================================================================
30ecd5f8 264void BOPAlgo_BuilderSolid::PerformLoops()
4e57c75e 265{
33ba8565 266 Standard_Integer i, aNbSh;
682c9d06 267 BOPCol_ListIteratorOfListOfShape aIt;
4e57c75e 268 TopoDS_Iterator aItS;
0090ae85 269 Handle(NCollection_BaseAllocator) aAlr;
682c9d06 270 //
682c9d06 271 myLoops.Clear();
4e57c75e 272 //
488e5b9d 273 aAlr=
274 NCollection_BaseAllocator::CommonBaseAllocator();
0090ae85 275 BOPAlgo_ShellSplitter aSSp(aAlr);
276 //
4e57c75e 277 // 1. Shells Usual
682c9d06 278 aIt.Initialize (myShapes);
279 for (; aIt.More(); aIt.Next()) {
f47b8d2b 280 const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value());
281 if (myContext->IsInfiniteFace(aF)) {
282 TopoDS_Shell aSh;
283 BRep_Builder aBB;
284 //
285 aBB.MakeShell(aSh);
286 aBB.Add(aSh, aF);
287 myLoops.Append(aSh);
288 continue;
289 }
290 //
682c9d06 291 if (!myShapesToAvoid.Contains(aF)) {
292 aSSp.AddStartElement(aF);
293 }
294 }
4e57c75e 295 //
682c9d06 296 aSSp.SetRunParallel(myRunParallel);
297 aSSp.Perform();
33ba8565 298 if (aSSp.HasErrors()) {
299 // add warning status
300 {
301 TopoDS_Compound aFacesSp;
302 BRep_Builder().MakeCompound(aFacesSp);
303 BOPCol_ListIteratorOfListOfShape aItLF(aSSp.StartElements());
304 for (; aItLF.More(); aItLF.Next()) {
305 BRep_Builder().Add(aFacesSp, aItLF.Value());
306 }
307 AddWarning (new BOPAlgo_AlertShellSplitterFailed (aFacesSp));
308 }
682c9d06 309 return;
4e57c75e 310 }
311 //
682c9d06 312 const BOPCol_ListOfShape& aLSh=aSSp.Shells();
313 aIt.Initialize (aLSh);
314 for (; aIt.More(); aIt.Next()) {
315 const TopoDS_Shape& aSh=aIt.Value();
316 myLoops.Append(aSh);
317 }
318 //=================================================
4e57c75e 319 //
682c9d06 320 // 2. Post Treatment
682c9d06 321 BRep_Builder aBB;
322 BOPCol_MapOfOrientedShape AddedFacesMap;
323 BOPCol_IndexedDataMapOfShapeListOfShape aEFMap;
4e57c75e 324 BOPCol_MapOfOrientedShape aMP;
682c9d06 325 //
4e57c75e 326 // a. collect all edges that are in loops
327 aIt.Initialize (myLoops);
328 for (; aIt.More(); aIt.Next()) {
329 const TopoDS_Shape& aS=aIt.Value();
330 aItS.Initialize(aS);
331 for (; aItS.More(); aItS.Next()) {
332 const TopoDS_Shape& aF=aItS.Value();
333 aMP.Add(aF);
334 }
335 }
336 //
337 // b. collect all edges that are to avoid
319da2e4 338 aNbSh = myShapesToAvoid.Extent();
339 for (i = 1; i <= aNbSh; ++i) {
340 const TopoDS_Shape& aF = myShapesToAvoid(i);
4e57c75e 341 aMP.Add(aF);
342 }
343 //
344 // c. add all edges that are not processed to myShapesToAvoid
345 aIt.Initialize (myShapes);
346 for (; aIt.More(); aIt.Next()) {
f47b8d2b 347 const TopoDS_Face& aF=*((TopoDS_Face*)&aIt.Value());
348 if (!myContext->IsInfiniteFace(aF)) {
349 if (!aMP.Contains(aF)) {
350 myShapesToAvoid.Add(aF);
351 }
4e57c75e 352 }
353 }
354 //=================================================
355 //
682c9d06 356 // 3.Internal Shells
4e57c75e 357 myLoopsInternal.Clear();
358 //
359 aEFMap.Clear();
360 AddedFacesMap.Clear();
361 //
319da2e4 362 aNbSh = myShapesToAvoid.Extent();
363 for (i = 1; i <= aNbSh; ++i) {
364 const TopoDS_Shape& aFF = myShapesToAvoid(i);
682c9d06 365 BOPTools::MapShapesAndAncestors(aFF,
1e143abb 366 TopAbs_EDGE, TopAbs_FACE,
367 aEFMap);
4e57c75e 368 }
369 //
319da2e4 370 for (i = 1; i <= aNbSh; ++i) {
371 const TopoDS_Shape& aFF = myShapesToAvoid(i);
4e57c75e 372 if (!AddedFacesMap.Add(aFF)) {
373 continue;
374 }
375 //
376 // make a new shell
0090ae85 377 TopExp_Explorer aExp;
4e57c75e 378 TopoDS_Shell aShell;
379 aBB.MakeShell(aShell);
380 aBB.Add(aShell, aFF);
381 //
0090ae85 382 aItS.Initialize(aShell);
383 for (; aItS.More(); aItS.Next()) {
384 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aItS.Value()));
4e57c75e 385 //
0090ae85 386 aExp.Init(aF, TopAbs_EDGE);
387 for (; aExp.More(); aExp.Next()) {
388 const TopoDS_Edge& aE = (*(TopoDS_Edge*)(&aExp.Current()));
4e57c75e 389 const BOPCol_ListOfShape& aLF=aEFMap.FindFromKey(aE);
682c9d06 390 aIt.Initialize(aLF);
391 for (; aIt.More(); aIt.Next()) {
392 const TopoDS_Face& aFL=(*(TopoDS_Face*)(&aIt.Value()));
4e57c75e 393 if (AddedFacesMap.Add(aFL)){
394 aBB.Add(aShell, aFL);
395 }
396 }
397 }
398 }
ab860031 399 aShell.Closed (BRep_Tool::IsClosed (aShell));
4e57c75e 400 myLoopsInternal.Append(aShell);
401 }
402}
403//=======================================================================
404//function : PerformAreas
405//purpose :
406//=======================================================================
30ecd5f8 407void BOPAlgo_BuilderSolid::PerformAreas()
4e57c75e 408{
4e57c75e 409 myAreas.Clear();
98b37659 410 BRep_Builder aBB;
411 // The new solids
412 BOPCol_ListOfShape aNewSolids;
413 // The hole shells which has to be classified relatively new solids
414 BOPCol_IndexedMapOfShape aHoleShells;
415 // Map of the faces of the hole shells for quick check of the growths.
416 // If the analyzed shell contains any of the hole faces, it is considered as growth.
417 BOPCol_IndexedMapOfShape aMHF;
418
419 // Analyze the shells
420 BOPCol_ListIteratorOfListOfShape aItLL(myLoops);
421 for (; aItLL.More(); aItLL.Next())
422 {
423 const TopoDS_Shape& aShell = aItLL.Value();
424
425 Standard_Boolean bIsGrowth = IsGrowthShell(aShell, aMHF);
426 if (!bIsGrowth)
427 {
428 // Fast check did not give the result, run classification
429 bIsGrowth = !IsHole(aShell, myContext);
430 }
431
432 // Save the solid
433 if (bIsGrowth)
434 {
435 TopoDS_Solid aSolid;
682c9d06 436 aBB.MakeSolid(aSolid);
437 aBB.Add (aSolid, aShell);
682c9d06 438 aNewSolids.Append (aSolid);
4e57c75e 439 }
98b37659 440 else
441 {
442 aHoleShells.Add(aShell);
443 BOPTools::MapShapes(aShell, TopAbs_FACE, aMHF);
4e57c75e 444 }
98b37659 445 }
446
447 if (aHoleShells.IsEmpty())
448 {
449 // No holes, stop the analysis
b7cd7c2b 450 BOPCol_ListIteratorOfListOfShape aItLS(aNewSolids);
451 for (; aItLS.More(); aItLS.Next())
452 {
453 const TopoDS_Shape& aSol = aItLS.Value();
454 myAreas.Append(aSol);
455 // Build box
456 Bnd_Box aBox;
457 BRepBndLib::Add(aSol, aBox);
458 myBoxes.Bind(aSol, aBox);
459 }
98b37659 460 return;
461 }
462
463 // Classify holes relatively solids
464
465 // Prepare tree filler with the boxes of the hole shells
466 BOPCol_BoxBndTree aBBTree;
467 NCollection_UBTreeFiller <Standard_Integer, Bnd_Box> aTreeFiller(aBBTree);
468
469 Standard_Integer i, aNbH = aHoleShells.Extent();
470 for (i = 1; i <= aNbH; ++i)
471 {
472 const TopoDS_Shape& aHShell = aHoleShells(i);
682c9d06 473 //
98b37659 474 Bnd_Box aBox;
475 BRepBndLib::Add(aHShell, aBox);
476 aTreeFiller.Add(i, aBox);
b7cd7c2b 477
478 myBoxes.Bind(aHShell, aBox);
4e57c75e 479 }
98b37659 480
481 // Shake TreeFiller
682c9d06 482 aTreeFiller.Fill();
98b37659 483
484 // Find outer growth shell that is most close to each hole shell
485 BOPCol_IndexedDataMapOfShapeShape aHoleSolidMap;
486
487 BOPCol_ListIteratorOfListOfShape aItLS(aNewSolids);
488 for (; aItLS.More(); aItLS.Next())
489 {
490 const TopoDS_Shape& aSolid = aItLS.Value();
491
492 // Build box
493 Bnd_Box aBox;
494 BRepBndLib::Add(aSolid, aBox);
495
b7cd7c2b 496 myBoxes.Bind(aSolid, aBox);
497
98b37659 498 BOPCol_BoxBndTreeSelector aSelector;
499 aSelector.SetBox(aBox);
bcf50875 500 aBBTree.Select(aSelector);
98b37659 501
502 const BOPCol_ListOfInteger& aLI = aSelector.Indices();
503 BOPCol_ListIteratorOfListOfInteger aItLI(aLI);
504 for (; aItLI.More(); aItLI.Next())
505 {
506 Standard_Integer k = aItLI.Value();
507 const TopoDS_Shape& aHole = aHoleShells(k);
508 // Check if it is inside
509 if (!IsInside(aHole, aSolid, myContext))
4e57c75e 510 continue;
98b37659 511
512 // Save the relation
513 TopoDS_Shape* pSolidWas = aHoleSolidMap.ChangeSeek(aHole);
514 if (pSolidWas)
515 {
516 if (IsInside(aSolid, *pSolidWas, myContext))
517 {
518 *pSolidWas = aSolid;
4e57c75e 519 }
520 }
98b37659 521 else
522 {
523 aHoleSolidMap.Add(aHole, aSolid);
4e57c75e 524 }
525 }
682c9d06 526 }
98b37659 527
528 // Make the back map from solids to holes
529 BOPCol_IndexedDataMapOfShapeListOfShape aSolidHolesMap;
530
531 aNbH = aHoleSolidMap.Extent();
532 for (i = 1; i <= aNbH; ++i)
533 {
534 const TopoDS_Shape& aHole = aHoleSolidMap.FindKey(i);
535 const TopoDS_Shape& aSolid = aHoleSolidMap(i);
4e57c75e 536 //
98b37659 537 BOPCol_ListOfShape* pLHoles = aSolidHolesMap.ChangeSeek(aSolid);
538 if (!pLHoles)
539 pLHoles = &aSolidHolesMap(aSolidHolesMap.Add(aSolid, BOPCol_ListOfShape()));
540 pLHoles->Append(aHole);
4e57c75e 541 }
98b37659 542
543 // Add Holes to Solids and add them to myAreas
682c9d06 544 aItLS.Initialize(aNewSolids);
98b37659 545 for ( ; aItLS.More(); aItLS.Next())
546 {
547 TopoDS_Solid& aSolid = *(TopoDS_Solid*)&aItLS.Value();
548 const BOPCol_ListOfShape* pLHoles = aSolidHolesMap.Seek(aSolid);
549 if (pLHoles)
550 {
551 // update solid
552 BOPCol_ListIteratorOfListOfShape aItLH(*pLHoles);
553 for (; aItLH.More(); aItLH.Next())
554 {
555 const TopoDS_Shape& aHole = aItLH.Value();
556 aBB.Add(aSolid, aHole);
557 }
558
559 // update classifier
560 myContext->SolidClassifier(aSolid).Load(aSolid);
561 }
562
563 myAreas.Append(aSolid);
4e57c75e 564 }
98b37659 565
4e57c75e 566 // Add holes that outside the solids to myAreas
98b37659 567 aNbH = aHoleShells.Extent();
568 for (i = 1; i <= aNbH; ++i)
569 {
570 const TopoDS_Shape& aHole = aHoleShells(i);
571 if (!aHoleSolidMap.Contains(aHole))
572 {
4e57c75e 573 TopoDS_Solid aSolid;
574 aBB.MakeSolid(aSolid);
575 aBB.Add (aSolid, aHole);
576 //
577 myAreas.Append(aSolid);
b7cd7c2b 578 // Make an infinite box for the hole
579 Bnd_Box aBox;
580 aBox.SetWhole();
581 myBoxes.Bind(aSolid, aBox);
4e57c75e 582 }
b7cd7c2b 583
584 myBoxes.UnBind(aHole);
4e57c75e 585 }
586}
587//=======================================================================
588//function : PerformInternalShapes
589//purpose :
590//=======================================================================
30ecd5f8 591void BOPAlgo_BuilderSolid::PerformInternalShapes()
4e57c75e 592{
b7cd7c2b 593 if (myAvoidInternalShapes)
594 // user-defined option to avoid internal parts is in force
291fced1 595 return;
b7cd7c2b 596
597 if (myLoopsInternal.IsEmpty())
598 // no internal parts
4e57c75e 599 return;
b7cd7c2b 600
601 // Get all faces to classify
319da2e4 602 BOPCol_IndexedMapOfShape aMFs;
b7cd7c2b 603 BOPCol_ListIteratorOfListOfShape aItLS(myLoopsInternal);
604 for (; aItLS.More(); aItLS.Next())
605 {
606 const TopoDS_Shape& aShell = aItLS.Value();
607 TopoDS_Iterator aIt(aShell);
608 for (; aIt.More(); aIt.Next())
609 aMFs.Add(aIt.Value());
4e57c75e 610 }
b7cd7c2b 611
612 BRep_Builder aBB;
613 // Check existence of the growths solids
614 if (myAreas.IsEmpty())
615 {
616 // No areas.
617 // Just make solid of the faces
465d1fba 618 TopoDS_Solid aSolid;
619 aBB.MakeSolid(aSolid);
4e57c75e 620 //
b7cd7c2b 621 BOPCol_ListOfShape aLSI;
465d1fba 622 MakeInternalShells(aMFs, aLSI);
623 //
624 aItLS.Initialize(aLSI);
b7cd7c2b 625 for (; aItLS.More(); aItLS.Next())
626 aBB.Add(aSolid, aItLS.Value());
627
465d1fba 628 myAreas.Append(aSolid);
465d1fba 629 return;
630 }
b7cd7c2b 631
632 // Classify faces relatively solids
633
634 // Prepare list of faces to classify
635 BOPCol_ListOfShape aLFaces;
636 Standard_Integer i, aNbF = aMFs.Extent();
637 for (i = 1; i <= aNbF; ++i)
638 aLFaces.Append(aMFs(i));
639
640 // Map of solids with IN faces
465d1fba 641 BOPCol_IndexedDataMapOfShapeListOfShape aMSLF;
b7cd7c2b 642
643 // Perform classification
644 BOPAlgo_Tools::ClassifyFaces(aLFaces, myAreas, myRunParallel, myContext, aMSLF, myBoxes);
645
646 // Update Solids by internal Faces
647
648 BOPCol_MapOfShape aMFDone;
649
650 Standard_Integer aNbS = aMSLF.Extent();
651 for (i = 1; i <= aNbS; ++i)
652 {
653 const TopoDS_Shape& aSolid = aMSLF.FindKey(i);
654 TopoDS_Shape *pSolid = (TopoDS_Shape*)&aSolid;
655
656 const BOPCol_ListOfShape& aLF = aMSLF(i);
657 if (aLF.IsEmpty())
465d1fba 658 continue;
b7cd7c2b 659
660 BOPCol_IndexedMapOfShape aMF;
465d1fba 661 aItLS.Initialize(aLF);
b7cd7c2b 662 for (; aItLS.More(); aItLS.Next())
663 {
664 const TopoDS_Shape& aF = aItLS.Value();
665 aMF.Add(aF);
666 aMFDone.Add(aF);
4e57c75e 667 }
465d1fba 668 //
b7cd7c2b 669 BOPCol_ListOfShape aLSI;
670 MakeInternalShells(aMF, aLSI);
465d1fba 671 //
672 aItLS.Initialize(aLSI);
b7cd7c2b 673 for (; aItLS.More(); aItLS.Next())
674 {
675 const TopoDS_Shape& aSI = aItLS.Value();
465d1fba 676 aBB.Add (*pSolid, aSI);
677 }
678 }
b7cd7c2b 679
680 // Make solid from the unused faces (if any)
681 BOPCol_IndexedMapOfShape aMFUnUsed;
682 for (i = 1; i <= aNbF; ++i)
683 {
684 const TopoDS_Shape& aF = aMFs(i);
685 if (!aMFDone.Contains(aF))
686 aMFUnUsed.Add(aF);
465d1fba 687 }
b7cd7c2b 688
689 if (aMFUnUsed.Extent())
690 {
4e57c75e 691 TopoDS_Solid aSolid;
692 aBB.MakeSolid(aSolid);
693 //
b7cd7c2b 694 BOPCol_ListOfShape aLSI;
695 MakeInternalShells(aMFUnUsed, aLSI);
465d1fba 696 //
697 aItLS.Initialize(aLSI);
b7cd7c2b 698 for (; aItLS.More(); aItLS.Next())
699 {
700 const TopoDS_Shape& aSI = aItLS.Value();
4e57c75e 701 aBB.Add (aSolid, aSI);
b7cd7c2b 702
703 Bnd_Box aBox;
704 BRepBndLib::Add(aSolid, aBox);
705 myBoxes.Bind(aSolid, aBox);
4e57c75e 706 }
707 myAreas.Append(aSolid);
708 }
709}
4e57c75e 710//=======================================================================
711//function : MakeInternalShells
712//purpose :
713//=======================================================================
319da2e4 714void MakeInternalShells(const BOPCol_IndexedMapOfShape& theMF,
4e57c75e 715 BOPCol_ListOfShape& theShells)
716{
319da2e4 717 Standard_Integer i, aNbF;
4e57c75e 718 BRep_Builder aBB;
319da2e4 719 BOPCol_ListIteratorOfListOfShape aItF;
4e57c75e 720 BOPCol_IndexedDataMapOfShapeListOfShape aMEF;
4e57c75e 721 BOPCol_MapOfShape aAddedFacesMap;
722 //
319da2e4 723 aNbF = theMF.Extent();
724 for (i = 1; i <= aNbF; ++i) {
725 TopoDS_Shape aF = theMF(i);
682c9d06 726 BOPTools::MapShapesAndAncestors(aF,
1e143abb 727 TopAbs_EDGE, TopAbs_FACE,
728 aMEF);
4e57c75e 729 }
730 //
319da2e4 731 for (i = 1; i <= aNbF; ++i) {
732 TopoDS_Shape aFF = theMF(i);
4e57c75e 733 if (!aAddedFacesMap.Add(aFF)) {
734 continue;
735 }
736 //
737 // make a new shell
738 TopoDS_Shell aShell;
739 aBB.MakeShell(aShell);
740 aFF.Orientation(TopAbs_INTERNAL);
741 aBB.Add(aShell, aFF);
742 //
743 TopoDS_Iterator aItAddedF (aShell);
744 for (; aItAddedF.More(); aItAddedF.Next()) {
745 const TopoDS_Shape& aF =aItAddedF.Value();
746 //
747 TopExp_Explorer aEdgeExp(aF, TopAbs_EDGE);
748 for (; aEdgeExp.More(); aEdgeExp.Next()) {
749 const TopoDS_Shape& aE =aEdgeExp.Current();
750 const BOPCol_ListOfShape& aLF=aMEF.FindFromKey(aE);
751 aItF.Initialize(aLF);
752 for (; aItF.More(); aItF.Next()) {
753 TopoDS_Shape aFL=aItF.Value();
754 if (aAddedFacesMap.Add(aFL)){
755 aFL.Orientation(TopAbs_INTERNAL);
756 aBB.Add(aShell, aFL);
757 }
758 }
759 }
760 }
ab860031 761 aShell.Closed (BRep_Tool::IsClosed (aShell));
4e57c75e 762 theShells.Append(aShell);
763 }
764}
765//=======================================================================
766//function : IsHole
767//purpose :
768//=======================================================================
769Standard_Boolean IsHole(const TopoDS_Shape& theS2,
1e143abb 770 Handle(IntTools_Context)& theContext)
4e57c75e 771{
772 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
773 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
774 //
775 aClsf.PerformInfinitePoint(::RealSmall());
776 //
777 return (aClsf.State()==TopAbs_IN);
778}
779//=======================================================================
780//function : IsInside
781//purpose :
782//=======================================================================
783Standard_Boolean IsInside(const TopoDS_Shape& theS1,
784 const TopoDS_Shape& theS2,
1e143abb 785 Handle(IntTools_Context)& theContext)
4e57c75e 786{
787 TopExp_Explorer aExp;
788 TopAbs_State aState;
789 //
790 TopoDS_Solid *pS2=(TopoDS_Solid *)&theS2;
791 //
792 aExp.Init(theS1, TopAbs_FACE);
793 if (!aExp.More()){
794 BRepClass3d_SolidClassifier& aClsf=theContext->SolidClassifier(*pS2);
795 aClsf.PerformInfinitePoint(::RealSmall());
796 aState=aClsf.State();
797 }
798 else {
799 BOPCol_IndexedMapOfShape aBounds;
800 BOPTools::MapShapes(*pS2, TopAbs_EDGE, aBounds);
801 const TopoDS_Face& aF = (*(TopoDS_Face*)(&aExp.Current()));
92ae0f2f 802 aState=BOPTools_AlgoTools::ComputeState(aF, *pS2,
803 Precision::Confusion(),
1e143abb 804 aBounds, theContext);
4e57c75e 805 }
806 return (aState==TopAbs_IN);
807}
808//=======================================================================
809//function : IsGrowthShell
810//purpose :
811//=======================================================================
812Standard_Boolean IsGrowthShell(const TopoDS_Shape& theShell,
813 const BOPCol_IndexedMapOfShape& theMHF)
814{
98b37659 815 if (theMHF.Extent())
816 {
817 TopoDS_Iterator aIt(theShell);
818 for(; aIt.More(); aIt.Next())
819 {
820 if (theMHF.Contains(aIt.Value()))
821 return Standard_True;
4e57c75e 822 }
823 }
98b37659 824 return Standard_False;
4e57c75e 825}