0030611: Coding Rules - eliminate GCC compiler warnings -Wcatch-value
[occt.git] / src / BOPAlgo / BOPAlgo_RemoveFeatures.cxx
CommitLineData
d9ca2e0c 1// Created by: Eugeny MALTCHIKOV
2// Copyright (c) 2018 OPEN CASCADE SAS
3//
4// This file is part of Open CASCADE Technology software library.
5//
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
8// by the Free Software Foundation, with special exception defined in the file
9// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
10// distribution for complete text of the license and disclaimer of any warranty.
11//
12// Alternatively, this file may be used under the terms of Open CASCADE
13// commercial license or contractual agreement.
14
15#include <BOPAlgo_RemoveFeatures.hxx>
16
17#include <BOPAlgo_Alerts.hxx>
18#include <BOPAlgo_BOP.hxx>
19#include <BOPAlgo_Builder.hxx>
20#include <BOPAlgo_BuilderSolid.hxx>
21#include <BOPAlgo_MakerVolume.hxx>
22#include <BOPAlgo_Tools.hxx>
23
24#include <BOPTools_AlgoTools.hxx>
25#include <BOPTools_Parallel.hxx>
26#include <BOPTools_Set.hxx>
27
28#include <Bnd_Box.hxx>
29
30#include <BRep_Builder.hxx>
31
32#include <BRepBndLib.hxx>
33
34#include <BRepLib.hxx>
35
36#include <NCollection_Vector.hxx>
37
38#include <ShapeUpgrade_UnifySameDomain.hxx>
39
40#include <TopAbs_ShapeEnum.hxx>
41
42#include <TopExp.hxx>
43#include <TopExp_Explorer.hxx>
44
45#include <TopoDS.hxx>
46#include <TopoDS_Compound.hxx>
47#include <TopoDS_Edge.hxx>
48#include <TopoDS_Face.hxx>
49
50#include <TopTools_IndexedDataMapOfShapeShape.hxx>
51
52
53//=======================================================================
54// static methods declaration
55//=======================================================================
56
57static void MakeRemoved(const TopTools_ListOfShape& theShapes,
58 BRepTools_History& theHistory,
59 const TopTools_IndexedMapOfShape& theKeepShapes = TopTools_IndexedMapOfShape());
60
61static void FindInternals(const TopoDS_Shape& theS,
62 TopTools_ListOfShape& theLInt);
63
64static void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
65 TopTools_ListOfShape* theRemoved = NULL);
66
67static void GetOriginalFaces(const TopoDS_Shape& theShape,
68 const TopTools_IndexedMapOfShape& theSolids,
69 const TopTools_MapOfShape& theFeatureFacesMap,
70 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
71 const Handle(BRepTools_History)& theHistory,
72 TopTools_IndexedMapOfShape& theFacesToBeKept,
73 TopTools_ListOfShape& theInternalShapes,
74 TopTools_MapOfShape& theFacesToCheckOri,
75 TopTools_IndexedMapOfShape& theSolidsToRebuild,
76 TopTools_ListOfShape& theSharedFaces,
77 TopTools_ListOfShape& theUnTouchedSolids);
78
79static void FindShape(const TopoDS_Shape& theSWhat,
80 const TopoDS_Shape& theSWhere,
81 TopoDS_Shape& theSFound);
82
83static void GetValidSolids(BOPAlgo_MakerVolume& theMV,
84 const TopTools_MapOfShape& theFacesToCheckOri,
85 const TopTools_ListOfShape& aSharedFaces,
86 const TopoDS_Shape& theOrigFaces,
87 const Standard_Integer theNbSol,
88 TopTools_ListOfShape& theLSRes,
89 TopTools_ListOfShape& theRemovedShapes);
90
91static void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
92 const TopTools_MapOfShape& theShapesToCheckOri,
93 BOPAlgo_Builder& theBuilder,
94 TopTools_MapOfShape& theShapesToAvoid,
95 TopTools_MapOfShape* theValidShapes = NULL);
96
97static void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
98 const TopTools_ListOfShape& theLFSharedToAvoid,
99 BOPAlgo_Builder& theBuilder,
100 TopTools_ListOfShape& theExtraFaces);
101
102static void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
103 TopTools_ListOfShape& theSolidsRes,
104 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
105 BOPAlgo_Builder& theBuilder,
106 BRepTools_History& theSolidsHistory);
107
108static void TakeModified(const TopoDS_Shape& theS,
109 BOPAlgo_Builder& theBuilder,
110 TopTools_ListOfShape& theList);
111
112static void TakeModified(const TopoDS_Shape& theS,
113 BOPAlgo_Builder& theBuilder,
114 TopTools_MapOfShape& theMap);
115
116static void FindSolid(const TopoDS_Shape& theSolIn,
117 const TopTools_ListOfShape& theSolidsRes,
118 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
119 BOPAlgo_Builder& theBuilder,
120 TopoDS_Shape& theSolOut);
121
122
123//=======================================================================
124// function: Perform
125// purpose: Performs the removal of the requested faces from the input shape
126//=======================================================================
127void BOPAlgo_RemoveFeatures::Perform()
128{
129 try
130 {
131 OCC_CATCH_SIGNALS
132
948fe6ca 133 if (HasHistory())
d9ca2e0c 134 myHistory = new BRepTools_History();
135
136 // Check the input data
137 CheckData();
138 if (HasErrors())
139 return;
140
141 // Prepare the faces to remove.
142 PrepareFeatures();
143 if (HasErrors())
144 return;
145
146 // Remove the features and fill the created gaps
147 RemoveFeatures();
148
149 // Update history with the removed features
150 UpdateHistory();
151
152 // Simplify the result
153 SimplifyResult();
154
155 // Post treatment
156 PostTreat();
157 }
a738b534 158 catch (Standard_Failure const&)
d9ca2e0c 159 {
160 AddError(new BOPAlgo_AlertRemoveFeaturesFailed());
161 }
162}
163
164//=======================================================================
165// function: CheckData
166// purpose: Checks the input data on validity for the algorithm
167//=======================================================================
168void BOPAlgo_RemoveFeatures::CheckData()
169{
170 // Prepare the shape to work with
171 myShape = myInputShape;
172
173 // Check the type of input shape
174 const TopAbs_ShapeEnum aType = myInputShape.ShapeType();
175
176 if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID)
177 return; // OK
178
179 if (aType == TopAbs_COMPOUND)
180 {
181 TopTools_ListOfShape aShapes;
182 TopTools_MapOfShape aMFence;
183 // Extract all shapes from the compound
184 BOPAlgo_Tools::TreatCompound(myInputShape, aMFence, aShapes);
185 if (aShapes.IsEmpty())
186 {
187 // Add error of empty input shape
188 AddError(new BOPAlgo_AlertEmptyShape(myInputShape));
189 return;
190 }
191
192 // Find all solids in the list of shapes
193 TopTools_ListOfShape aSolids;
194 TopTools_ListOfShape anOtherShapes;
195 TopTools_ListIteratorOfListOfShape aIt(aShapes);
196 for (; aIt.More(); aIt.Next())
197 {
198 const TopoDS_Shape& aS = aIt.Value();
199 if (aS.ShapeType() == TopAbs_SOLID || aS.ShapeType() == TopAbs_COMPSOLID)
200 aSolids.Append(aS);
201 else
202 anOtherShapes.Append(aS);
203 }
204
205 if (aSolids.IsEmpty())
206 {
207 // No solids have been found for processing.
208 // Add error of unsupported type of input shape
209 AddError(new BOPAlgo_AlertTooFewArguments());
210 }
211 else if (anOtherShapes.Extent() > 0)
212 {
213 // Add warning of unsupported type of input shape for all
214 // non-solid shapes, contained in the input shape
215 for (aIt.Initialize(anOtherShapes); aIt.More(); aIt.Next())
216 {
217 AddWarning(new BOPAlgo_AlertUnsupportedType(aIt.Value()));
218 }
219
220 // Collect all solids into compound and overwrite the shape to rebuild
221 TopoDS_Compound aCS;
222 BRep_Builder().MakeCompound(aCS);
223 for (aIt.Initialize(aSolids); aIt.More(); aIt.Next())
224 BRep_Builder().Add(aCS, aIt.Value());
225
226 myShape = aCS;
227
948fe6ca 228 if (HasHistory())
d9ca2e0c 229 {
230 // Make non solid shapes removed in the history
231 MakeRemoved(anOtherShapes, *myHistory.get());
232 }
233 }
234 }
235 else
236 {
237 // Add error of unsupported type of input shape
238 AddError(new BOPAlgo_AlertTooFewArguments());
239 }
240}
241
242//=======================================================================
243// function: PrepareFeatures
244// purpose: Prepares the features to remove
245//=======================================================================
246void BOPAlgo_RemoveFeatures::PrepareFeatures()
247{
248 // Map all sub-shapes of the input solids
249 TopExp::MapShapes(myInputShape, myInputsMap);
250
251 // Collect all faces of the input shape requested for removal
252 TopTools_ListOfShape aFacesToRemove;
253 TopTools_ListIteratorOfListOfShape aIt(myFacesToRemove);
254 for (; aIt.More(); aIt.Next())
255 {
256 const TopoDS_Shape& aS = aIt.Value();
257 TopExp_Explorer anExpF(aS, TopAbs_FACE);
258 for (; anExpF.More(); anExpF.Next())
259 {
260 const TopoDS_Shape& aF = anExpF.Current();
261 if (myInputsMap.Contains(aF))
262 aFacesToRemove.Append(aF);
263 }
264 }
265
266 if (aFacesToRemove.IsEmpty())
267 {
268 // Add error, that no features to remove have been found
269 AddError(new BOPAlgo_AlertNoFacesToRemove());
270 return;
271 }
272
273 // Build connexity blocks of the faces to remove
274 TopoDS_Compound aCFToRemove;
275 BRep_Builder().MakeCompound(aCFToRemove);
276 for (aIt.Initialize(aFacesToRemove); aIt.More(); aIt.Next())
277 BRep_Builder().Add(aCFToRemove, aIt.Value());
278
279 // Fill the list of features with connexity blocks of faces
280 BOPTools_AlgoTools::MakeConnexityBlocks(aCFToRemove, TopAbs_EDGE, TopAbs_FACE, myFeatures);
281}
282
283//=======================================================================
284// Adjacent faces extension block
285
286//=======================================================================
287// class: FillGaps
288// purpose: Auxiliary class for creation of the faces for filling the gap
289// created by removal of the single feature
290//=======================================================================
291class FillGap
292{
293public: //! @name Constructors
294
295 //! Empty constructor
296 FillGap() :
297 myRunParallel(Standard_False),
298 myHasAdjacentFaces(Standard_False)
299 {}
300
301public: //! @name Setters/Getters
302
303 //! Sets the feature to remove
304 void SetFeature(const TopoDS_Shape& theFeature) { myFeature = theFeature; }
305
306 //! Returns the feature
307 const TopoDS_Shape& Feature() const { return myFeature; }
308
309 //! Sets the EF connection map
310 void SetEFConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap)
311 {
312 myEFMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theEFMap;
313 }
314
315 //! Sets the FS connection map
316 void SetFSConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theFSMap)
317 {
318 myFSMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theFSMap;
319 }
320
321 //! Defines the parallel processing mode
322 void SetRunParallel(const Standard_Boolean bRunParallel) { myRunParallel = bRunParallel; }
323
324 //! Gets the History object
325 const Handle(BRepTools_History)& History()
326 {
327 return myHistory;
328 }
329
330public: //! @name Perform the operation
331
332 //! Performs the extension of the adjacent faces and
333 //! then trims the extended faces to fill the gaps
334 void Perform()
335 {
336 OCC_CATCH_SIGNALS
337
338 try
339 {
340 myHistory = new BRepTools_History();
341
342 // Find the faces adjacent to the faces of the feature
343 TopTools_IndexedMapOfShape aMFAdjacent;
344 FindAdjacentFaces(aMFAdjacent);
345
346 myHasAdjacentFaces = (aMFAdjacent.Extent() > 0);
347 if (!myHasAdjacentFaces)
348 return;
349
350 // Extend the adjacent faces keeping the connection to the original faces
351 TopTools_IndexedDataMapOfShapeShape aFaceExtFaceMap;
352 ExtendAdjacentFaces(aMFAdjacent, aFaceExtFaceMap);
353
354 // Trim the extended faces
355 TrimExtendedFaces(aFaceExtFaceMap);
356 }
a738b534 357 catch (Standard_Failure const&)
d9ca2e0c 358 {
359 // Make sure the warning will be given on the higher level
360 myHasAdjacentFaces = Standard_True;
361 myFaces.Clear();
362 }
363 }
364
365public: //! @name Obtain the result
366
367 //! Returns the map of faces of the feature
368 const TopTools_MapOfShape& FeatureFacesMap() const { return myFeatureFacesMap; }
369
370 //! Shows whether the adjacent faces have been found for the feature
371 Standard_Boolean HasAdjacentFaces() const { return myHasAdjacentFaces; }
372
373 //! Returns the Images map of the adjacent faces
374 const TopTools_IndexedDataMapOfShapeListOfShape& Faces() const { return myFaces; }
375
376 //! Returns the initial solids participating in the feature removal
377 const TopTools_IndexedMapOfShape& Solids() const { return mySolids; }
378
379
380private: //! @name Private methods performing the operation
381
382 //! Finds the faces adjacent to the feature and stores them into outgoing map.
383 void FindAdjacentFaces(TopTools_IndexedMapOfShape& theMFAdjacent)
384 {
385 // Map the faces of the feature to avoid them in the map of adjacent faces
386 TopoDS_Iterator aIt(myFeature);
387 for (; aIt.More(); aIt.Next())
388 myFeatureFacesMap.Add(aIt.Value());
389
390 // Find faces adjacent to the feature using the connection map
391 aIt.Initialize(myFeature);
392 for (; aIt.More(); aIt.Next())
393 {
394 const TopoDS_Shape& aF = aIt.Value();
395 TopExp_Explorer anExpE(aF, TopAbs_EDGE);
396 for (; anExpE.More(); anExpE.Next())
397 {
398 const TopoDS_Shape& aE = anExpE.Current();
399 const TopTools_ListOfShape* pAdjacentFaces = myEFMap->Seek(aE);
400 if (pAdjacentFaces)
401 {
402 TopTools_ListIteratorOfListOfShape itLFA(*pAdjacentFaces);
403 for (; itLFA.More(); itLFA.Next())
404 {
405 const TopoDS_Shape& anAF = itLFA.Value();
406 if (!myFeatureFacesMap.Contains(anAF))
407 theMFAdjacent.Add(anAF);
408 }
409 }
410 }
411 // Find solids containing the feature face
412 const TopTools_ListOfShape* pLS = myFSMap->Seek(aF);
413 if (pLS)
414 {
415 TopTools_ListIteratorOfListOfShape itLS(*pLS);
416 for (; itLS.More(); itLS.Next())
417 mySolids.Add(itLS.Value());
418 }
419 }
420
421 // Find solids containing the edges of adjacent faces
422 const Standard_Integer aNbFA = theMFAdjacent.Extent();
423 for (Standard_Integer i = 1; i <= aNbFA; ++i)
424 {
425 TopExp_Explorer anExpEA(theMFAdjacent(i), TopAbs_EDGE);
426 for (; anExpEA.More(); anExpEA.Next())
427 {
428 // Faces adjacent to the face adjacent to the feature
429 const TopTools_ListOfShape* pLFAA = myEFMap->Seek(anExpEA.Current());
430 if (pLFAA)
431 {
432 TopTools_ListIteratorOfListOfShape itLFAA(*pLFAA);
433 for (; itLFAA.More(); itLFAA.Next())
434 {
435 // Solids containing the faces
436 const TopTools_ListOfShape* pLS = myFSMap->Seek(itLFAA.Value());
437 if (pLS)
438 {
439 TopTools_ListIteratorOfListOfShape itLS(*pLS);
440 for (; itLS.More(); itLS.Next())
441 mySolids.Add(itLS.Value());
442 }
443 }
444 }
445 }
446 }
447 }
448
449 //! Extends the found adjacent faces and binds them to the original faces.
450 void ExtendAdjacentFaces(const TopTools_IndexedMapOfShape& theMFAdjacent,
451 TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap)
452 {
453 // Get the extension value for the faces - half of the diagonal of bounding box of the feature
454 Bnd_Box aFeatureBox;
455 BRepBndLib::Add(myFeature, aFeatureBox);
456
457 const Standard_Real anExtLength = sqrt(aFeatureBox.SquareExtent());
458
459 const Standard_Integer aNbFA = theMFAdjacent.Extent();
460 for (Standard_Integer i = 1; i <= aNbFA; ++i)
461 {
462 const TopoDS_Face& aF = TopoDS::Face(theMFAdjacent(i));
463 // Extend the face
464 TopoDS_Face aFExt;
465 BRepLib::ExtendFace(aF, anExtLength,
466 Standard_True, Standard_True,
467 Standard_True, Standard_True,
468 aFExt);
469 theFaceExtFaceMap.Add(aF, aFExt);
470 myHistory->AddModified(aF, aFExt);
471 }
472 }
473
474 //! Trims the extended adjacent faces by intersection with each other
475 //! and following intersection with the bounds of original faces.
476 void TrimExtendedFaces(const TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap)
477 {
478 // Intersect the extended faces first
479 BOPAlgo_Builder aGFInter;
480 // Add faces for intersection
481 const Standard_Integer aNbF = theFaceExtFaceMap.Extent();
482 for (Standard_Integer i = 1; i <= aNbF; ++i)
483 aGFInter.AddArgument(theFaceExtFaceMap(i));
484
485 aGFInter.SetRunParallel(myRunParallel);
486
487 // Intersection result
488 TopoDS_Shape anIntResult;
489 if (aGFInter.Arguments().Extent() > 1)
490 {
491 aGFInter.Perform();
492 if (aGFInter.HasErrors())
493 return;
494
495 anIntResult = aGFInter.Shape();
496
948fe6ca 497 myHistory->Merge(aGFInter.History());
d9ca2e0c 498 }
499 else
500 anIntResult = aGFInter.Arguments().First();
501
502 // Prepare the EF map of the extended faces after intersection
503 // to select from them only boundary edges
504 TopTools_IndexedDataMapOfShapeListOfShape anEFExtMap;
505 TopExp::MapShapesAndAncestors(anIntResult, TopAbs_EDGE, TopAbs_FACE, anEFExtMap);
506
507 // Get the splits of the extended faces after intersection
508 // and trim them by the edges of the original faces
509
510 // Map the edges of the Feature to avoid them during the trim
511 TopTools_IndexedMapOfShape aFeatureEdgesMap;
512 TopExp::MapShapes(myFeature, TopAbs_EDGE, aFeatureEdgesMap);
513
514 for (Standard_Integer i = 1; i <= aNbF; ++i)
515 {
516 const TopoDS_Face& aFOriginal = TopoDS::Face(theFaceExtFaceMap.FindKey(i));
517 const TopoDS_Face& aFExt = TopoDS::Face(theFaceExtFaceMap(i));
518 TrimFace(aFExt, aFOriginal, aFeatureEdgesMap, anEFExtMap, aGFInter);
519 }
520 }
521
522 //! Trim the extended faces by the bounds of the original face,
523 //! except those contained in the feature to remove.
524 void TrimFace(const TopoDS_Face& theFExt,
525 const TopoDS_Face& theFOriginal,
526 const TopTools_IndexedMapOfShape& theFeatureEdgesMap,
527 const TopTools_IndexedDataMapOfShapeListOfShape& theEFExtMap,
528 BOPAlgo_Builder& theGFInter)
529 {
530 // Map all edges of the extended face, to filter the result of trim
531 // from the faces containing these edges
532 TopTools_MapOfShape aMExtEdges;
533 TopExp_Explorer anExpE(theFExt, TopAbs_EDGE);
534 for (; anExpE.More(); anExpE.Next())
535 {
536 const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
537 // skip degenerated and seam edges
538 if (BRep_Tool::Degenerated(aE) || BRep_Tool::IsClosed(aE, theFExt))
539 continue;
540 TopTools_ListOfShape aLEIm;
541 TakeModified(aE, theGFInter, aLEIm);
542 TopTools_ListIteratorOfListOfShape itLEIm(aLEIm);
543 for (; itLEIm.More(); itLEIm.Next())
544 {
545 const TopoDS_Shape& aEIm = itLEIm.Value();
546 if (theEFExtMap.FindFromKey(aEIm).Extent() == 1)
547 aMExtEdges.Add(aEIm);
548 }
549 }
550
551 // Trimming tool
552 BOPAlgo_Builder aGFTrim;
553
554 // Get the splits of the face and add them for trimming
555 TopTools_ListOfShape anExtSplits;
556 TakeModified(theFExt, theGFInter, anExtSplits);
557 aGFTrim.SetArguments(anExtSplits);
558
559 // Add edges of the original faces
560 TopTools_MapOfShape aMEdgesToCheckOri;
561 anExpE.Init(theFOriginal, TopAbs_EDGE);
562 for (; anExpE.More(); anExpE.Next())
563 {
564 const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
565 if (!theFeatureEdgesMap.Contains(aE))
566 {
567 aGFTrim.AddArgument(aE);
568 if (!BRep_Tool::Degenerated(aE) &&
569 !BRep_Tool::IsClosed(aE, theFOriginal))
570 {
571 if (!aMEdgesToCheckOri.Add(aE))
572 aMEdgesToCheckOri.Remove(aE);
573 }
574 }
575 }
576
577 // Avoid faces intersection
578 aGFTrim.SetGlue(BOPAlgo_GlueShift);
579 aGFTrim.SetRunParallel(myRunParallel);
580 aGFTrim.SetNonDestructive(Standard_True);
581
582 aGFTrim.Perform();
583 if (aGFTrim.HasErrors())
584 return;
585
586 // Get all splits
587 const TopoDS_Shape& aSplits = aGFTrim.Shape();
588 // Filter the trimmed faces and save the valid ones into result map
589 TopTools_ListOfShape aLFTrimmed;
590
591 TopExp_Explorer anExpF(aSplits, TopAbs_FACE);
592 for (; anExpF.More(); anExpF.Next())
593 {
594 const TopoDS_Shape& aSp = anExpF.Current();
595 anExpE.Init(aSp, TopAbs_EDGE);
596 for (; anExpE.More(); anExpE.Next())
597 {
598 if (aMExtEdges.Contains(anExpE.Current()))
599 break;
600 }
601 if (!anExpE.More())
602 aLFTrimmed.Append(aSp);
603 }
604
605 if (aLFTrimmed.Extent() > 1)
606 {
607 // Chose the correct faces - the ones that contains edges with proper
608 // bi-normal direction
609 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
610 TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed);
611 for (; itLF.More(); itLF.Next())
612 TopExp::MapShapesAndAncestors(itLF.Value(), TopAbs_EDGE, TopAbs_FACE, anEFMap);
613
614 // Check edges orientations
615 TopTools_MapOfShape aFacesToAvoid, aValidFaces;
616 FindExtraShapes(anEFMap, aMEdgesToCheckOri, aGFTrim, aFacesToAvoid, &aValidFaces);
617
618 if (aLFTrimmed.Extent() - aFacesToAvoid.Extent() > 1)
619 {
620 // It is possible that the splits are forming the different blocks.
621 // Take only those containing the valid faces.
622 TopoDS_Compound aCF;
623 BRep_Builder().MakeCompound(aCF);
624 itLF.Initialize(aLFTrimmed);
625 for (; itLF.More(); itLF.Next())
626 {
627 if (!aFacesToAvoid.Contains(itLF.Value()))
628 BRep_Builder().Add(aCF, itLF.Value());
629 }
630
631 TopTools_ListOfShape aLCB;
632 BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
633 if (aLCB.Extent() > 1)
634 {
635 TopTools_ListIteratorOfListOfShape itLCB(aLCB);
636 for (; itLCB.More(); itLCB.Next())
637 {
638 // Check if the block contains any valid faces
639 const TopoDS_Shape& aCB = itLCB.Value();
640 TopoDS_Iterator itF(aCB);
641 for (; itF.More(); itF.Next())
642 {
643 if (aValidFaces.Contains(itF.Value()))
644 break;
645 }
646 if (!itF.More())
647 {
648 // Invalid block
649 for (itF.Initialize(aCB); itF.More(); itF.Next())
650 aFacesToAvoid.Add(itF.Value());
651 }
652 }
653 }
654 }
655
656 itLF.Initialize(aLFTrimmed);
657 for (; itLF.More();)
658 {
659 if (aFacesToAvoid.Contains(itLF.Value()))
660 aLFTrimmed.Remove(itLF);
661 else
662 itLF.Next();
663 }
664 }
665 else if (aLFTrimmed.IsEmpty())
666 {
667 // Use all splits, including those having the bounds of extended face
668 anExpF.ReInit();
669 for (; anExpF.More(); anExpF.Next())
670 aLFTrimmed.Append(anExpF.Current());
671 }
672
673 if (aLFTrimmed.Extent())
674 {
675 // Remove the internal edges and vertices from the faces
676 RemoveInternalWires(aLFTrimmed);
677
678 myFaces.Add(theFOriginal, aLFTrimmed);
679 }
680
681 // Update history after intersection of the extended face with bounds
948fe6ca 682 myHistory->Merge(aGFTrim.History());
d9ca2e0c 683
684 // Update history with all removed shapes
685 BRepTools_History aHistRem;
686
687 // Map of the result splits
688 TopTools_IndexedMapOfShape aResMap;
689 TopTools_ListIteratorOfListOfShape itLF(aLFTrimmed);
690 for (; itLF.More(); itLF.Next())
691 TopExp::MapShapes(itLF.Value(), aResMap);
692
693 TopTools_ListOfShape aLSplits;
694 aLSplits.Append(aSplits);
695
696 // Update the history with removed shapes
697 MakeRemoved(aLSplits, aHistRem, aResMap);
698 myHistory->Merge(aHistRem);
699 }
700
701private: //! @name Fields
702
703 // Inputs
704 Standard_Boolean myRunParallel; //!< Defines the mode of processing of the single feature
705 TopoDS_Shape myFeature; //!< Feature to remove
706 TopTools_IndexedDataMapOfShapeListOfShape* myEFMap; //!< EF Connection map to find adjacent faces
707 TopTools_IndexedDataMapOfShapeListOfShape* myFSMap; //!< FS Connection map to find solids participating in the feature removal
708
709 // Results
710 TopTools_MapOfShape myFeatureFacesMap; //!< Faces of the feature
711 Standard_Boolean myHasAdjacentFaces; //!< Flag to show whether the adjacent faces have been found or not
712 TopTools_IndexedMapOfShape mySolids; //!< Solids participating in the feature removal
713 TopTools_IndexedDataMapOfShapeListOfShape myFaces; //!< Reconstructed adjacent faces
714 Handle(BRepTools_History) myHistory; //!< History of the adjacent faces reconstruction
715};
716
717typedef NCollection_Vector<FillGap> VectorOfFillGap;
718
719typedef BOPTools_Functor <FillGap, VectorOfFillGap> FillGapFunctor;
720
721typedef BOPTools_Cnt <FillGapFunctor, VectorOfFillGap> FillGapCnt;
722
723//=======================================================================
724
725//=======================================================================
726// function: RemoveFeatures
727// purpose: Remove features by filling the gaps by extension of the
728// adjacent faces
729//=======================================================================
730void BOPAlgo_RemoveFeatures::RemoveFeatures()
731{
732 // For each feature:
733 // - Find the faces adjacent to the feature;
734 // - Extend the adjacent faces;
735 // - Trim the extended faces to fill the gap;
736 // - Rebuild the solids with reconstructed adjacent faces
737 // and avoiding the feature faces.
738
739 // Make Edge-Face connection map of the input
740 // shape to find faces adjacent to the feature
741 TopTools_IndexedDataMapOfShapeListOfShape anEFMap;
742 TopExp::MapShapesAndAncestors(myInputShape, TopAbs_EDGE, TopAbs_FACE, anEFMap);
743
744 // Make Face-Solid connection map to find the solids
745 // participating in the removal of each feature
746 TopTools_IndexedDataMapOfShapeListOfShape anFSMap;
747 TopExp::MapShapesAndAncestors(myInputShape, TopAbs_FACE, TopAbs_SOLID, anFSMap);
748
749 // Tool for reconstruction of the faces adjacent to the feature
750 // in parallel threads if necessary.
751 VectorOfFillGap aVFG;
752 // Fill the vector
753 TopTools_ListIteratorOfListOfShape itF(myFeatures);
754 for (; itF.More(); itF.Next())
755 {
756 const TopoDS_Shape& aFeature = itF.Value();
757 FillGap& aFG = aVFG.Appended();
758 aFG.SetFeature(aFeature);
759 aFG.SetEFConnectionMap(anEFMap);
760 aFG.SetFSConnectionMap(anFSMap);
761 aFG.SetRunParallel(myRunParallel);
762 }
763
764 // Perform the reconstruction of the adjacent faces
765 FillGapCnt::Perform(myRunParallel, aVFG);
766
767 // Even if the history is not requested, it is necessary to track:
768 // - The solids modification after each feature removal to find
769 // the necessary solids to rebuild on the next step.
770 // - The faces modification after each feature removal to find the
771 // splits of the adjacent and feature faces for the next steps.
772 if (myHistory.IsNull())
773 myHistory = new BRepTools_History();
774
775 // Remove the features one by one.
776 // It will allow removing the features even if there were
777 // some problems with removal of the previous features.
778 const Standard_Integer aNbF = aVFG.Length();
779 for (Standard_Integer i = 0; i < aNbF; ++i)
780 {
781 FillGap& aFG = aVFG(i);
782
783 // No need to fill the history for solids if the history is not
784 // requested and the current feature is the last one.
948fe6ca 785 Standard_Boolean isSolidsHistoryNeeded = HasHistory() || (i < (aNbF - 1));
d9ca2e0c 786
787 // Perform removal of the single feature
788 RemoveFeature(aFG.Feature(), aFG.Solids(), aFG.FeatureFacesMap(),
789 aFG.HasAdjacentFaces(), aFG.Faces(), aFG.History(),
790 isSolidsHistoryNeeded);
791 }
792}
793
794//=======================================================================
795// function: RemoveFeature
796// purpose: Remove the single feature
797//=======================================================================
798void BOPAlgo_RemoveFeatures::RemoveFeature
799 (const TopoDS_Shape& theFeature,
800 const TopTools_IndexedMapOfShape& theSolids,
801 const TopTools_MapOfShape& theFeatureFacesMap,
802 const Standard_Boolean theHasAdjacentFaces,
803 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
804 const Handle(BRepTools_History)& theAdjFacesHistory,
805 const Standard_Boolean theSolidsHistoryNeeded)
806{
807 Standard_Boolean bFuseShapes = Standard_True;
808 const Standard_Integer aNbAF = theAdjFaces.Extent();
809 if (aNbAF == 0)
810 {
811 if (theHasAdjacentFaces)
812 {
813 // The adjacent faces have been found for the feature,
814 // but something went wrong during their rebuilding.
815 // Add error
816 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
817 return;
818 }
819
820 // No adjacent faces have been found for the feature.
821 // Most likely, the intention is to remove some internal part of the shape.
822 // We just have to rebuild the shape without the feature, no fuse is necessary.
823 bFuseShapes = Standard_False;
824 }
825
826 // Rebuild the shape using MakerVolume algorithm avoiding the faces of the
827 // feature and replacing the adjacent faces with their images
828
829 BRep_Builder aBB;
830
831 // From the faces of input shape build map of faces with which the result will be validated:
832 // - all non-internal faces of the input shape (except for adjacent and feature faces)
833 // must have some trace in the result solids;
834 // - all adjacent faces (if any) must have some trace in the result solids.
835 TopTools_IndexedMapOfShape aFacesToBeKept;
836 // Build also the map of faces to compare orientation of the original and result faces
837 TopTools_MapOfShape aFacesToCheckOri;
838
839 // Collect list of internal entities of the input shape to be avoided in result
840 // and to make them removed in the history.
841 TopTools_ListOfShape anInternalShapes;
842
843 // In the feature removal will participate only the solids connected to the feature
844 // or the faces adjacent to the feature.
845
846 // Solids to be rebuilt after the feature removal
847 TopTools_IndexedMapOfShape aSolidsToRebuild;
848 // Find faces shared between solids
849 TopTools_ListOfShape aSharedFaces;
850 // Solids to be avoided in the feature removal and added into result directly
851 TopTools_ListOfShape anUnTouchedSolids;
852
853 // Prepare to the feature removal - fill all necessary containers
854 GetOriginalFaces(myShape, theSolids, theFeatureFacesMap, theAdjFaces, myHistory,
855 aFacesToBeKept, anInternalShapes, aFacesToCheckOri,
856 aSolidsToRebuild, aSharedFaces, anUnTouchedSolids);
857
858 // To avoid excessive intersection of the faces collect the faces
859 // of the input shape into a compound
860 TopoDS_Compound anOrigF;
861 aBB.MakeCompound(anOrigF);
862 Standard_Integer aNbFK = aFacesToBeKept.Extent();
863 for (Standard_Integer i = 1; i <= aNbFK; ++i)
864 aBB.Add(anOrigF, aFacesToBeKept(i));
865
866 // Tool for solids reconstruction
867 BOPAlgo_MakerVolume aMV;
868 aMV.SetRunParallel(myRunParallel);
869 aMV.SetAvoidInternalShapes(Standard_True);
870 aMV.SetIntersect(bFuseShapes);
871 aMV.SetNonDestructive(Standard_True);
872 // Add faces of the input shape
873 aMV.AddArgument(anOrigF);
874
875 // Add reconstructed adjacent faces
876 for (Standard_Integer i = 1; i <= aNbAF; ++i)
877 {
878 const TopTools_ListOfShape& aLFA = theAdjFaces(i);
879 if (aLFA.Extent() == 1)
880 {
881 const TopoDS_Shape& aFA = aLFA.First();
882 aMV.AddArgument(aFA);
883 aFacesToBeKept.Add(aFA);
884 }
885 else
886 {
887 // To avoid intersection among the images, collect them into compound
888 TopoDS_Compound anAdjF;
889 aBB.MakeCompound(anAdjF);
890 TopTools_ListIteratorOfListOfShape itLFA(aLFA);
891 for (; itLFA.More(); itLFA.Next())
892 aBB.Add(anAdjF, itLFA.Value());
893
894 aMV.AddArgument(anAdjF);
895 aFacesToBeKept.Add(anAdjF);
896 }
897
948fe6ca 898 if (HasHistory())
d9ca2e0c 899 {
900 // Look for internal edges in the original adjacent faces
901 const TopoDS_Shape& aFOr = theAdjFaces.FindKey(i);
902 FindInternals(aFOr, anInternalShapes);
903 }
904 }
905
906 // Build solids
907 aMV.Perform();
908 if (aMV.HasErrors())
909 {
910 // Add warning for the feature
911 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
912 return;
913 }
914
915 // Result of MV operation
916 const TopoDS_Shape& aSolids = aMV.Shape();
917 TopExp_Explorer anExpS(aSolids, TopAbs_SOLID);
918 if (!anExpS.More())
919 {
920 // No solids have been built - add warning for the feature
921 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
922 return;
923 }
924
925 // Now, it is necessary to:
926 // - Validate the result by checking faces of the map <aFacesToBeKept>
927 // to have some parts kept in the resulting solids;
928 // - Remove the solids possibly filling the holes in the original shapes;
929 // - Update history with the history of MakerVolume algorithm.
930
931 // Splits of adjacent faces from previous runs
932 TopTools_MapOfShape anAdjFacesSplits;
933 for (Standard_Integer i = 1; i <= aNbAF; ++i)
934 {
935 const TopoDS_Shape& aF = theAdjFaces.FindKey(i);
936 const TopTools_ListOfShape& aLFIm = myHistory->Modified(aF);
937 if (aLFIm.IsEmpty())
938 anAdjFacesSplits.Add(aF);
939 else
940 {
941 TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
942 for (; itLFIm.More(); itLFIm.Next())
943 anAdjFacesSplits.Add(itLFIm.Value());
944 }
945 }
946
947 // Validate the result
948 Standard_Boolean bValid = Standard_True;
949 aNbFK = aFacesToBeKept.Extent();
950 for (Standard_Integer i = 1; i <= aNbFK && bValid; ++i)
951 {
952 const TopoDS_Shape& aS = aFacesToBeKept(i);
953 if (anAdjFacesSplits.Contains(aS))
954 continue;
955 TopExp_Explorer anExpF(aS, TopAbs_FACE);
956 for (; anExpF.More(); anExpF.Next())
957 {
958 const TopoDS_Shape& aF = anExpF.Current();
959 if (!aMV.IsDeleted(aF))
960 break;
961 }
962 bValid = anExpF.More();
963 }
964
965 if (!bValid)
966 {
967 // Add warning for the feature
968 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
969 return;
970 }
971
972 // It is possible that the result of MakerVolume operation contains
973 // some extra solids. Get only correct solids.
974 TopTools_ListOfShape aLSRes;
975 // Remember the removed shapes
976 TopTools_ListOfShape aRemovedShapes;
977 GetValidSolids(aMV, aFacesToCheckOri, aSharedFaces, anOrigF, theSolids.Extent(), aLSRes, aRemovedShapes);
978
979 if (aLSRes.Extent() != theSolids.Extent())
980 {
981 // Add warning for the feature
982 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
983 return;
984 }
985
986 // Remove internal wires from the faces, possibly appeared after intersection
987 RemoveInternalWires(aLSRes, &anInternalShapes);
988
989 // Update history with:
990 // History of adjacent faces reconstruction
991 myHistory->Merge(theAdjFacesHistory);
992 // History of intersection
948fe6ca 993 myHistory->Merge(aMV.History());
d9ca2e0c 994
948fe6ca 995 if (HasHistory())
d9ca2e0c 996 {
997 // Map the result to check if the shape is removed
998 TopTools_IndexedMapOfShape aMSRes;
999 TopTools_ListIteratorOfListOfShape itLS(aLSRes);
1000 for (; itLS.More(); itLS.Next())
1001 TopExp::MapShapes(itLS.Value(), aMSRes);
1002
1003 // Remove internal shapes and extra faces
1004 BRepTools_History aRemHist;
1005 anInternalShapes.Append(aRemovedShapes);
1006 MakeRemoved(anInternalShapes, aRemHist, aMSRes);
1007 myHistory->Merge(aRemHist);
1008 }
1009
1010 // Fill the history for the solids
1011 if (theSolidsHistoryNeeded)
1012 {
1013 BRepTools_History aSolidsHistory;
1014 FillSolidsHistory(aSolidsToRebuild, aLSRes, theAdjFaces, aMV, aSolidsHistory);
1015 myHistory->Merge(aSolidsHistory);
1016 }
1017
1018 TopoDS_Compound aCRes;
1019 aBB.MakeCompound(aCRes);
1020 // Add reconstructed solids
1021 TopTools_ListIteratorOfListOfShape itLS(aLSRes);
1022 for (; itLS.More(); itLS.Next())
1023 aBB.Add(aCRes, itLS.Value());
1024
1025 // Add unmodified solids
1026 itLS.Initialize(anUnTouchedSolids);
1027 for (; itLS.More(); itLS.Next())
1028 aBB.Add(aCRes, itLS.Value());
1029
1030 // Save the result
1031 myShape = aCRes;
1032}
1033
1034//=======================================================================
1035// function: UpdateHistory
1036// purpose: Update history with the removed features
1037//=======================================================================
1038void BOPAlgo_RemoveFeatures::UpdateHistory()
1039{
948fe6ca 1040 if (!HasHistory())
d9ca2e0c 1041 return;
1042
1043 // Map the result
948fe6ca 1044 myMapShape.Clear();
1045 TopExp::MapShapes(myShape, myMapShape);
d9ca2e0c 1046
1047 // Update the history
1048 BRepTools_History aHistory;
1049
1050 const Standard_Integer aNbS = myInputsMap.Extent();
1051 for (Standard_Integer i = 1; i <= aNbS; ++i)
1052 {
1053 const TopoDS_Shape& aS = myInputsMap(i);
1054 if (!BRepTools_History::IsSupportedType(aS))
1055 continue;
1056
1057 if (myHistory->IsRemoved(aS))
1058 continue;
1059
1060 // Check if the shape has any trace in the result
1061 const TopTools_ListOfShape& aLSIm = myHistory->Modified(aS);
1062 if (aLSIm.IsEmpty())
1063 {
948fe6ca 1064 if (!myMapShape.Contains(aS))
d9ca2e0c 1065 aHistory.Remove(aS);
1066 }
1067
1068 TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
1069 for (; itLSIm.More(); itLSIm.Next())
1070 {
948fe6ca 1071 if (!myMapShape.Contains(itLSIm.Value()))
d9ca2e0c 1072 aHistory.Remove(itLSIm.Value());
1073 }
1074 }
1075
1076 myHistory->Merge(aHistory);
1077}
1078
1079//=======================================================================
1080// function: SimplifyResult
1081// purpose: Simplifies the result by removing extra edges and vertices
1082// created during operation
1083//=======================================================================
1084void BOPAlgo_RemoveFeatures::SimplifyResult()
1085{
1086 if (myShape.IsSame(myInputShape))
1087 return;
1088 ShapeUpgrade_UnifySameDomain aSDTool;
1089 aSDTool.Initialize(myShape, Standard_True, Standard_True);
1090 // Do not allow producing internal edges
1091 aSDTool.AllowInternalEdges(Standard_False);
1092 // Avoid removal of the input edges and vertices
948fe6ca 1093 if (myMapShape.IsEmpty())
1094 TopExp::MapShapes(myShape, myMapShape);
d9ca2e0c 1095
1096 const Standard_Integer aNbS = myInputsMap.Extent();
1097 for (Standard_Integer i = 1; i <= aNbS; ++i)
1098 {
948fe6ca 1099 if (myMapShape.Contains(myInputsMap(i)))
d9ca2e0c 1100 aSDTool.KeepShape(myInputsMap(i));
1101 }
1102
1103 // Perform unification
1104 aSDTool.Build();
1105 myShape = aSDTool.Shape();
948fe6ca 1106 if (HasHistory())
d9ca2e0c 1107 myHistory->Merge(aSDTool.History());
1108}
1109
1110//=======================================================================
1111// function: PostTreat
1112// purpose: Restore the type of the initial shape
1113//=======================================================================
1114void BOPAlgo_RemoveFeatures::PostTreat()
1115{
1116 const TopAbs_ShapeEnum anInputType = myInputShape.ShapeType();
1117 const TopAbs_ShapeEnum aResType = myShape.ShapeType();
1118 if (aResType == anInputType)
1119 return;
1120
1121 TopExp_Explorer anExpS(myShape, TopAbs_SOLID);
1122
1123 if (anInputType == TopAbs_SOLID)
1124 {
1125 myShape = anExpS.Current();
1126 return;
1127 }
1128
1129 TopoDS_Shape aRes;
1130 if (anInputType == TopAbs_COMPOUND)
1131 BRep_Builder().MakeCompound(TopoDS::Compound(aRes));
1132 else
1133 BRep_Builder().MakeCompSolid(TopoDS::CompSolid(aRes));
1134
1135 for (; anExpS.More(); anExpS.Next())
1136 BRep_Builder().Add(aRes, anExpS.Current());
1137
1138 myShape = aRes;
1139}
1140
1141//=======================================================================
1142// static methods definition
1143//=======================================================================
1144
1145//=======================================================================
1146// function: MakeRemoved
1147// purpose: Makes the shapes in the list removed in the history.
1148// Keeps the shapes contained in the map.
1149//=======================================================================
1150void MakeRemoved(const TopTools_ListOfShape& theShapes,
1151 BRepTools_History& theHistory,
1152 const TopTools_IndexedMapOfShape& theKeepShapes)
1153{
1154 TopTools_IndexedMapOfShape aShapesMap;
1155 TopTools_ListIteratorOfListOfShape it(theShapes);
1156 for (; it.More(); it.Next())
1157 TopExp::MapShapes(it.Value(), aShapesMap);
1158
1159 const Standard_Integer aNbS = aShapesMap.Extent();
1160 for (Standard_Integer i = 1; i <= aNbS; ++i)
1161 {
1162 const TopoDS_Shape& aS = aShapesMap(i);
1163 if (!theKeepShapes.Contains(aS) &&
1164 BRepTools_History::IsSupportedType(aS))
1165 {
1166 theHistory.Remove(aS);
1167 }
1168 }
1169}
1170
1171//=======================================================================
1172// function: FindInternals
1173// purpose: Looks for internal shapes inside the face or solid
1174//=======================================================================
1175void FindInternals(const TopoDS_Shape& theS,
1176 TopTools_ListOfShape& theLInt)
1177{
1178 TopoDS_Iterator itS(theS);
1179 for (; itS.More(); itS.Next())
1180 {
1181 const TopoDS_Shape& aSS = itS.Value();
1182 if (aSS.Orientation() == TopAbs_INTERNAL)
1183 theLInt.Append(aSS);
1184 else
1185 {
1186 TopoDS_Iterator itSS(aSS);
1187 for (; itSS.More(); itSS.Next())
1188 {
1189 if (itSS.Value().Orientation() == TopAbs_INTERNAL)
1190 {
1191 theLInt.Append(aSS);
1192 break;
1193 }
1194 }
1195 }
1196 }
1197}
1198
1199//=======================================================================
1200// function: RemoveInternalWires
1201// purpose: Removes internal wires from the faces
1202//=======================================================================
1203void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
1204 TopTools_ListOfShape *theRemoved)
1205{
1206 TopTools_ListIteratorOfListOfShape itLS(theShapes);
1207 for (; itLS.More(); itLS.Next())
1208 {
1209 const TopoDS_Shape& aShape = itLS.Value();
1210 TopExp_Explorer anExpF(aShape, TopAbs_FACE);
1211 for (; anExpF.More(); anExpF.Next())
1212 {
1213 TopoDS_Face& aF = *(TopoDS_Face*)&anExpF.Current();
1214 TopTools_ListOfShape aLWToRemove;
1215 FindInternals(aF, aLWToRemove);
1216 if (aLWToRemove.Extent())
1217 {
1218 aF.Free(Standard_True);
1219 TopTools_ListIteratorOfListOfShape itR(aLWToRemove);
1220 for (; itR.More(); itR.Next())
1221 {
1222 if (theRemoved)
1223 theRemoved->Append(itR.Value());
1224 BRep_Builder().Remove(aF, itR.Value());
1225 }
1226 aF.Free(Standard_False);
1227 }
1228 }
1229 }
1230}
1231
1232//=======================================================================
1233// function: GetOriginalFaces
1234// purpose: Get original faces from my face
1235//=======================================================================
1236void GetOriginalFaces(const TopoDS_Shape& theShape,
1237 const TopTools_IndexedMapOfShape& theSolids,
1238 const TopTools_MapOfShape& theFeatureFacesMap,
1239 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
1240 const Handle(BRepTools_History)& theHistory,
1241 TopTools_IndexedMapOfShape& theFacesToBeKept,
1242 TopTools_ListOfShape& theInternalShapes,
1243 TopTools_MapOfShape& theFacesToCheckOri,
1244 TopTools_IndexedMapOfShape& theSolidsToRebuild,
1245 TopTools_ListOfShape& theSharedFaces,
1246 TopTools_ListOfShape& theUnTouchedSolids)
1247{
1248 // Use only solids which has to be reconstructed by the feature.
1249 // All other solids should be avoided in the feature removal and added
1250 // into result directly.
1251
1252 // Update solids after removal of previous features
1253 const Standard_Integer aNbSols = theSolids.Extent();
1254 for (Standard_Integer i = 1; i <= aNbSols; ++i)
1255 {
1256 const TopoDS_Shape& aSol = theSolids(i);
1257 const TopTools_ListOfShape& aLFIm = theHistory->Modified(aSol);
1258 if (aLFIm.IsEmpty())
1259 theSolidsToRebuild.Add(aSol);
1260 else
1261 theSolidsToRebuild.Add(aLFIm.First());
1262 }
1263
1264 // Splits of the feature faces
1265 TopTools_MapOfShape aFeatureFacesSplits;
1266 TopTools_MapIteratorOfMapOfShape itM(theFeatureFacesMap);
1267 for (; itM.More(); itM.Next())
1268 {
1269 const TopoDS_Shape& aF = itM.Value();
1270 const TopTools_ListOfShape& aLFIm = theHistory->Modified(aF);
1271 if (aLFIm.IsEmpty())
1272 aFeatureFacesSplits.Add(aF);
1273 else
1274 {
1275 TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
1276 for (; itLFIm.More(); itLFIm.Next())
1277 aFeatureFacesSplits.Add(itLFIm.Value());
1278 }
1279 }
1280
1281 TopExp_Explorer anExpS(theShape, TopAbs_SOLID);
1282 for (; anExpS.More(); anExpS.Next())
1283 {
1284 const TopoDS_Shape& aSol = anExpS.Current();
1285
1286 // Check if the solid has to be reconstructed
1287 if (!theSolidsToRebuild.Contains(aSol))
1288 {
1289 // untouched solid
1290 theUnTouchedSolids.Append(aSol);
1291 continue;
1292 }
1293
1294 TopoDS_Iterator itSh(aSol);
1295 for (; itSh.More(); itSh.Next())
1296 {
1297 const TopoDS_Shape& aSh = itSh.Value();
1298 if (aSh.ShapeType() != TopAbs_SHELL)
1299 {
1300 theInternalShapes.Append(aSh);
1301 continue;
1302 }
1303
1304 TopoDS_Iterator itF(aSh);
1305 for (; itF.More(); itF.Next())
1306 {
1307 const TopoDS_Shape& aF = itF.Value();
1308 // Avoid the feature faces
1309 if (aFeatureFacesSplits.Contains(aF))
1310 continue;
1311
1312 // Avoid the adjacent faces
1313 if (theAdjFaces.Contains(aF))
1314 continue;
1315
1316 if (aF.Orientation() != TopAbs_INTERNAL)
1317 {
1318 theFacesToBeKept.Add(aF);
1319
1320 if (!theFacesToCheckOri.Add(aF))
1321 {
1322 theFacesToCheckOri.Remove(aF);
1323 theSharedFaces.Append(aF);
1324 }
1325 }
1326 else
1327 theInternalShapes.Append(aSh);
1328 }
1329 }
1330 }
1331}
1332
1333//=======================================================================
1334// function: FindShape
1335// purpose: Find the shape in the other shape
1336//=======================================================================
1337void FindShape(const TopoDS_Shape& theSWhat,
1338 const TopoDS_Shape& theSWhere,
1339 TopoDS_Shape& theSFound)
1340{
1341 TopExp_Explorer anExp(theSWhere, theSWhat.ShapeType());
1342 for (; anExp.More(); anExp.Next())
1343 {
1344 const TopoDS_Shape& aS = anExp.Current();
1345 if (aS.IsSame(theSWhat))
1346 {
1347 theSFound = aS;
1348 break;
1349 }
1350 }
1351}
1352
1353//=======================================================================
1354// function: GetValidSolids
1355// purpose: Checks the validity of the solids and keeps only valid ones
1356//=======================================================================
1357void GetValidSolids(BOPAlgo_MakerVolume& theMV,
1358 const TopTools_MapOfShape& theFacesToCheckOri,
1359 const TopTools_ListOfShape& aSharedFaces,
1360 const TopoDS_Shape& theOrigFaces,
1361 const Standard_Integer theNbSol,
1362 TopTools_ListOfShape& theLSRes,
1363 TopTools_ListOfShape& theRemovedShapes)
1364{
1365 TopExp_Explorer anExpS(theMV.Shape(), TopAbs_SOLID);
1366 for (; anExpS.More(); anExpS.Next())
1367 theLSRes.Append(anExpS.Current());
1368
1369 if (theLSRes.Extent() > theNbSol)
1370 {
1371 // Find Solids filling the holes in the initial shape
1372 TopTools_MapOfShape aSolidsToAvoid;
1373 TopTools_IndexedDataMapOfShapeListOfShape aFSMap;
1374 TopExp::MapShapesAndAncestors(theMV.Shape(), TopAbs_FACE, TopAbs_SOLID, aFSMap);
1375 FindExtraShapes(aFSMap, theFacesToCheckOri, theMV, aSolidsToAvoid);
1376
1377 TopTools_ListIteratorOfListOfShape itLS(theLSRes);
1378 for (; itLS.More(); )
1379 {
1380 if (aSolidsToAvoid.Contains(itLS.Value()))
1381 theLSRes.Remove(itLS);
1382 else
1383 itLS.Next();
1384 }
1385 }
1386
1387 if (theLSRes.Extent() > theNbSol)
1388 {
1389 // Check if the splits of the adjacent faces split the solids
1390 AvoidExtraSharedFaces(theLSRes, aSharedFaces, theMV, theRemovedShapes);
1391 }
1392
1393 if (theLSRes.Extent() > theNbSol)
1394 {
1395 // Remove solids containing only the adjacent faces
1396 TopTools_MapOfShape anOrigFacesRes;
1397 TopExp_Explorer anExpF(theOrigFaces, TopAbs_FACE);
1398 for (; anExpF.More(); anExpF.Next())
1399 TakeModified(anExpF.Current(), theMV, anOrigFacesRes);
1400
1401 TopTools_ListIteratorOfListOfShape itLS(theLSRes);
1402 for (; itLS.More(); )
1403 {
1404 anExpF.Init(itLS.Value(), TopAbs_FACE);
1405 for (; anExpF.More(); anExpF.Next())
1406 {
1407 if (anOrigFacesRes.Contains(anExpF.Current()))
1408 break;
1409 }
1410 if (!anExpF.More())
1411 {
1412 theRemovedShapes.Append(itLS.Value());
1413 theLSRes.Remove(itLS);
1414 }
1415 else
1416 itLS.Next();
1417 }
1418 }
1419}
1420
1421//=======================================================================
1422// function: FindExtraShape
1423// purpose: Find shapes possibly filling the holes in the original shape
1424//=======================================================================
1425void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
1426 const TopTools_MapOfShape& theShapesToCheckOri,
1427 BOPAlgo_Builder& theBuilder,
1428 TopTools_MapOfShape& theShapesToAvoid,
1429 TopTools_MapOfShape* theValidShapes)
1430{
1431 Handle(IntTools_Context) aCtx = theBuilder.Context();
1432 TopTools_MapOfShape aValidShapes;
1433 TopTools_MapOfShape* pValidShapes = theValidShapes ? theValidShapes : &aValidShapes;
1434 TopTools_MapIteratorOfMapOfShape itM(theShapesToCheckOri);
1435 for (; itM.More(); itM.Next())
1436 {
1437 const TopoDS_Shape& aSToCheckOri = itM.Value();
1438 // Check modification of the shape during intersection
1439 TopTools_ListOfShape aLSIm;
1440 TakeModified(aSToCheckOri, theBuilder, aLSIm);
1441
1442 TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
1443 for (; itLSIm.More(); itLSIm.Next())
1444 {
1445 const TopoDS_Shape& aSIm = itLSIm.Value();
1446
1447 const TopTools_ListOfShape* pShapesToValidate = theConnectionMap.Seek(aSIm);
1448 if (!pShapesToValidate)
1449 continue;
1450
1451 TopTools_ListIteratorOfListOfShape itSV(*pShapesToValidate);
1452 for (; itSV.More(); itSV.Next())
1453 {
1454 const TopoDS_Shape& aShapeToValidate = itSV.Value();
1455 if (pValidShapes->Contains(aShapeToValidate))
1456 continue;
1457
1458 TopoDS_Face aSInShape;
1459 FindShape(aSIm, aShapeToValidate, aSInShape);
1460
1461 Standard_Boolean bSameOri =
1462 !BOPTools_AlgoTools::IsSplitToReverse(aSInShape, aSToCheckOri, aCtx);
1463
1464 if (bSameOri)
1465 pValidShapes->Add(aShapeToValidate);
1466 else
1467 theShapesToAvoid.Add(aShapeToValidate);
1468 }
1469 }
1470 }
1471
1472 itM.Initialize(*pValidShapes);
1473 for (; itM.More(); itM.Next())
1474 theShapesToAvoid.Remove(itM.Value());
1475}
1476
1477//=======================================================================
1478// function: AvoidExtraSharedFaces
1479// purpose: Looks for the extra faces splitting the solids
1480//=======================================================================
1481void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
1482 const TopTools_ListOfShape& theLFSharedToAvoid,
1483 BOPAlgo_Builder& theBuilder,
1484 TopTools_ListOfShape& theExtraFaces)
1485{
1486 // Get all splits of shared faces to avoid in the check
1487 TopTools_MapOfShape aMFSharedSp;
1488 {
1489 TopTools_ListOfShape aLFSharedSp;
1490 TopTools_ListIteratorOfListOfShape itLFS(theLFSharedToAvoid);
1491 for (; itLFS.More(); itLFS.Next())
1492 TakeModified(itLFS.Value(), theBuilder, aMFSharedSp);
1493 }
1494
1495 TopTools_IndexedDataMapOfShapeListOfShape aFSMap;
1496 TopTools_ListIteratorOfListOfShape itLS(theLSolids);
1497 for (; itLS.More(); itLS.Next())
1498 TopExp::MapShapesAndAncestors(itLS.Value(), TopAbs_FACE, TopAbs_SOLID, aFSMap);
1499
1500 TopTools_ListOfShape anExtraFaces;
1501 TopTools_ListOfShape aLFArguments;
1502 itLS.Initialize(theLSolids);
1503 for (; itLS.More(); itLS.Next())
1504 {
1505 const TopoDS_Shape& aSol = itLS.Value();
1506 TopExp_Explorer anExpF(aSol, TopAbs_FACE);
1507 for (; anExpF.More(); anExpF.Next())
1508 {
1509 const TopoDS_Shape& aF = anExpF.Current();
1510 const TopTools_ListOfShape& aLSol = aFSMap.FindFromKey(aF);
1511 if (aLSol.Extent() != 2 || aMFSharedSp.Contains(aF))
1512 aLFArguments.Append(aF);
1513 else
1514 anExtraFaces.Append(aF);
1515 }
1516 }
1517
1518 if (anExtraFaces.IsEmpty())
1519 return;
1520
1521 // Rebuild the solids avoiding the extra faces
1522 BOPAlgo_BuilderSolid aBS;
1523 aBS.SetAvoidInternalShapes(Standard_True);
1524 aBS.SetShapes(aLFArguments);
1525 aBS.Perform();
1526 if (aBS.HasErrors())
1527 return;
1528
1529 theLSolids = aBS.Areas();
1530 theExtraFaces.Append(anExtraFaces);
1531}
1532
1533//=======================================================================
1534// function: FillSolidsHistory
1535// purpose: Fills the history of solids modifications
1536//=======================================================================
1537void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
1538 TopTools_ListOfShape& theSolidsOut,
1539 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
1540 BOPAlgo_Builder& theBuilder,
1541 BRepTools_History& theSolidsHistory)
1542{
1543 const Standard_Integer aNbS = theSolIn.Extent();
1544 for (Standard_Integer i = 1; i <= aNbS; ++i)
1545 {
1546 const TopoDS_Shape& aSolIn = theSolIn(i);
1547
1548 TopoDS_Shape aSolOut;
1549 FindSolid(aSolIn, theSolidsOut, theAdjFaces, theBuilder, aSolOut);
1550
1551 if (aSolOut.IsNull())
1552 {
1553 theSolidsHistory.Remove(aSolIn);
1554 continue;
1555 }
1556
1557 // Check if the solid has really been modified
1558 BOPTools_Set aSTIn, aSTOut;
1559 aSTIn.Add(aSolIn, TopAbs_FACE);
1560 aSTOut.Add(aSolOut, TopAbs_FACE);
1561 if (aSTIn.IsEqual(aSTOut))
1562 {
1563 // The solids are the same. Replace the resulting solid in the result list
1564 // with the initial solid.
1565 TopTools_ListIteratorOfListOfShape itLS(theSolidsOut);
1566 for (; itLS.More(); itLS.Next())
1567 {
1568 if (itLS.Value().IsSame(aSolOut))
1569 {
1570 theSolidsOut.InsertBefore(aSolIn, itLS);
1571 theSolidsOut.Remove(itLS);
1572 break;
1573 }
1574 }
1575 }
1576 else
1577 {
1578 theSolidsHistory.AddModified(aSolIn, aSolOut);
1579 }
1580 }
1581}
1582
1583//=======================================================================
1584// function: TakeModified
1585// purpose: Stores the modified object into the list
1586//=======================================================================
1587void TakeModified(const TopoDS_Shape& theS,
1588 BOPAlgo_Builder& theBuilder,
1589 TopTools_ListOfShape& theList)
1590{
1591 const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
1592 if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
1593 theList.Append(theS);
1594 else
1595 {
1596 TopTools_ListIteratorOfListOfShape itM(aModified);
1597 for (; itM.More(); itM.Next())
1598 theList.Append(itM.Value());
1599 }
1600}
1601//=======================================================================
1602// function: TakeModified
1603// purpose: Stores the modified object into the map
1604//=======================================================================
1605void TakeModified(const TopoDS_Shape& theS,
1606 BOPAlgo_Builder& theBuilder,
1607 TopTools_MapOfShape& theMap)
1608{
1609 const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
1610 if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
1611 theMap.Add(theS);
1612 else
1613 {
1614 TopTools_ListIteratorOfListOfShape itM(aModified);
1615 for (; itM.More(); itM.Next())
1616 theMap.Add(itM.Value());
1617 }
1618}
1619
1620//=======================================================================
1621// function: FindSolid
1622// purpose: Looks for the image of the solid in the list of resulting solids
1623//=======================================================================
1624void FindSolid(const TopoDS_Shape& theSolIn,
1625 const TopTools_ListOfShape& theSolidsRes,
1626 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
1627 BOPAlgo_Builder& theBuilder,
1628 TopoDS_Shape& theSolOut)
1629{
1630 Handle(IntTools_Context) aCtx = theBuilder.Context();
1631
1632 // Take the face in the IN solid, and find it in the OUT list
1633 TopExp_Explorer anExpF(theSolIn, TopAbs_FACE);
1634 for (; anExpF.More(); anExpF.Next())
1635 {
1636 const TopoDS_Shape& aFS = anExpF.Current();
1637 // Images of the face
1638 TopTools_MapOfShape aMFSIm;
1639 const TopTools_ListOfShape* pLFA = theAdjFaces.Seek(aFS);
1640 if (pLFA)
1641 {
1642 TopTools_ListIteratorOfListOfShape itLFA(*pLFA);
1643 for (; itLFA.More(); itLFA.Next())
1644 TakeModified(itLFA.Value(), theBuilder, aMFSIm);
1645 }
1646 else
1647 {
1648 TakeModified(aFS, theBuilder, aMFSIm);
1649 }
1650
1651 // Find any of these faces in the list of solids
1652 TopTools_ListIteratorOfListOfShape itLS(theSolidsRes);
1653 for (; itLS.More(); itLS.Next())
1654 {
1655 const TopoDS_Shape& aSol = itLS.Value();
1656 TopExp_Explorer anExpFOut(aSol, TopAbs_FACE);
1657 for (; anExpFOut.More(); anExpFOut.Next())
1658 {
1659 const TopoDS_Shape& aF = anExpFOut.Current();
1660 if (aMFSIm.Contains(aF))
1661 {
1662 // check orientations
1663 if (!BOPTools_AlgoTools::IsSplitToReverse(aF, aFS, aCtx))
1664 {
1665 theSolOut = aSol;
1666 return;
1667 }
1668 }
1669 }
1670 }
1671 }
1672}