1 // Created by: Eugeny MALTCHIKOV
2 // Copyright (c) 2018 OPEN CASCADE SAS
4 // This file is part of Open CASCADE Technology software library.
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.
12 // Alternatively, this file may be used under the terms of Open CASCADE
13 // commercial license or contractual agreement.
15 #include <BOPAlgo_RemoveFeatures.hxx>
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>
24 #include <BOPTools_AlgoTools.hxx>
25 #include <BOPTools_Parallel.hxx>
26 #include <BOPTools_Set.hxx>
28 #include <Bnd_Box.hxx>
30 #include <BRep_Builder.hxx>
32 #include <BRepBndLib.hxx>
34 #include <BRepLib.hxx>
36 #include <NCollection_Vector.hxx>
38 #include <ShapeUpgrade_UnifySameDomain.hxx>
40 #include <TopAbs_ShapeEnum.hxx>
43 #include <TopExp_Explorer.hxx>
46 #include <TopoDS_Compound.hxx>
47 #include <TopoDS_Edge.hxx>
48 #include <TopoDS_Face.hxx>
50 #include <TopTools_IndexedDataMapOfShapeShape.hxx>
53 //=======================================================================
54 // static methods declaration
55 //=======================================================================
57 static void MakeRemoved(const TopTools_ListOfShape& theShapes,
58 BRepTools_History& theHistory,
59 const TopTools_IndexedMapOfShape& theKeepShapes = TopTools_IndexedMapOfShape());
61 static void FindInternals(const TopoDS_Shape& theS,
62 TopTools_ListOfShape& theLInt);
64 static void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
65 TopTools_ListOfShape* theRemoved = NULL);
67 static 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);
79 static void FindShape(const TopoDS_Shape& theSWhat,
80 const TopoDS_Shape& theSWhere,
81 TopoDS_Shape& theSFound);
83 static 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);
91 static void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
92 const TopTools_MapOfShape& theShapesToCheckOri,
93 BOPAlgo_Builder& theBuilder,
94 TopTools_MapOfShape& theShapesToAvoid,
95 TopTools_MapOfShape* theValidShapes = NULL);
97 static void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
98 const TopTools_ListOfShape& theLFSharedToAvoid,
99 BOPAlgo_Builder& theBuilder,
100 TopTools_ListOfShape& theExtraFaces);
102 static void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
103 TopTools_ListOfShape& theSolidsRes,
104 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
105 BOPAlgo_Builder& theBuilder,
106 BRepTools_History& theSolidsHistory);
108 static void TakeModified(const TopoDS_Shape& theS,
109 BOPAlgo_Builder& theBuilder,
110 TopTools_ListOfShape& theList);
112 static void TakeModified(const TopoDS_Shape& theS,
113 BOPAlgo_Builder& theBuilder,
114 TopTools_MapOfShape& theMap);
116 static void FindSolid(const TopoDS_Shape& theSolIn,
117 const TopTools_ListOfShape& theSolidsRes,
118 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
119 BOPAlgo_Builder& theBuilder,
120 TopoDS_Shape& theSolOut);
123 //=======================================================================
125 // purpose: Performs the removal of the requested faces from the input shape
126 //=======================================================================
127 void BOPAlgo_RemoveFeatures::Perform()
134 myHistory = new BRepTools_History();
136 // Check the input data
141 // Prepare the faces to remove.
146 // Remove the features and fill the created gaps
149 // Update history with the removed features
152 // Simplify the result
158 catch (Standard_Failure const&)
160 AddError(new BOPAlgo_AlertRemoveFeaturesFailed());
164 //=======================================================================
165 // function: CheckData
166 // purpose: Checks the input data on validity for the algorithm
167 //=======================================================================
168 void BOPAlgo_RemoveFeatures::CheckData()
170 // Prepare the shape to work with
171 myShape = myInputShape;
173 // Check the type of input shape
174 const TopAbs_ShapeEnum aType = myInputShape.ShapeType();
176 if (aType == TopAbs_SOLID || aType == TopAbs_COMPSOLID)
179 if (aType == TopAbs_COMPOUND)
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())
187 // Add error of empty input shape
188 AddError(new BOPAlgo_AlertEmptyShape(myInputShape));
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())
198 const TopoDS_Shape& aS = aIt.Value();
199 if (aS.ShapeType() == TopAbs_SOLID || aS.ShapeType() == TopAbs_COMPSOLID)
202 anOtherShapes.Append(aS);
205 if (aSolids.IsEmpty())
207 // No solids have been found for processing.
208 // Add error of unsupported type of input shape
209 AddError(new BOPAlgo_AlertTooFewArguments());
211 else if (anOtherShapes.Extent() > 0)
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())
217 AddWarning(new BOPAlgo_AlertUnsupportedType(aIt.Value()));
220 // Collect all solids into compound and overwrite the shape to rebuild
222 BRep_Builder().MakeCompound(aCS);
223 for (aIt.Initialize(aSolids); aIt.More(); aIt.Next())
224 BRep_Builder().Add(aCS, aIt.Value());
230 // Make non solid shapes removed in the history
231 MakeRemoved(anOtherShapes, *myHistory.get());
237 // Add error of unsupported type of input shape
238 AddError(new BOPAlgo_AlertTooFewArguments());
242 //=======================================================================
243 // function: PrepareFeatures
244 // purpose: Prepares the features to remove
245 //=======================================================================
246 void BOPAlgo_RemoveFeatures::PrepareFeatures()
248 // Map all sub-shapes of the input solids
249 TopExp::MapShapes(myInputShape, myInputsMap);
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())
256 const TopoDS_Shape& aS = aIt.Value();
257 TopExp_Explorer anExpF(aS, TopAbs_FACE);
258 for (; anExpF.More(); anExpF.Next())
260 const TopoDS_Shape& aF = anExpF.Current();
261 if (myInputsMap.Contains(aF))
262 aFacesToRemove.Append(aF);
266 if (aFacesToRemove.IsEmpty())
268 // Add error, that no features to remove have been found
269 AddError(new BOPAlgo_AlertNoFacesToRemove());
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());
279 // Fill the list of features with connexity blocks of faces
280 BOPTools_AlgoTools::MakeConnexityBlocks(aCFToRemove, TopAbs_EDGE, TopAbs_FACE, myFeatures);
283 //=======================================================================
284 // Adjacent faces extension block
286 //=======================================================================
288 // purpose: Auxiliary class for creation of the faces for filling the gap
289 // created by removal of the single feature
290 //=======================================================================
293 public: //! @name Constructors
295 //! Empty constructor
297 myRunParallel(Standard_False),
298 myHasAdjacentFaces(Standard_False)
301 public: //! @name Setters/Getters
303 //! Sets the feature to remove
304 void SetFeature(const TopoDS_Shape& theFeature) { myFeature = theFeature; }
306 //! Returns the feature
307 const TopoDS_Shape& Feature() const { return myFeature; }
309 //! Sets the EF connection map
310 void SetEFConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theEFMap)
312 myEFMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theEFMap;
315 //! Sets the FS connection map
316 void SetFSConnectionMap(const TopTools_IndexedDataMapOfShapeListOfShape& theFSMap)
318 myFSMap = (TopTools_IndexedDataMapOfShapeListOfShape*)&theFSMap;
321 //! Defines the parallel processing mode
322 void SetRunParallel(const Standard_Boolean bRunParallel) { myRunParallel = bRunParallel; }
324 //! Gets the History object
325 const Handle(BRepTools_History)& History()
330 public: //! @name Perform the operation
332 //! Performs the extension of the adjacent faces and
333 //! then trims the extended faces to fill the gaps
340 myHistory = new BRepTools_History();
342 // Find the faces adjacent to the faces of the feature
343 TopTools_IndexedMapOfShape aMFAdjacent;
344 FindAdjacentFaces(aMFAdjacent);
346 myHasAdjacentFaces = (aMFAdjacent.Extent() > 0);
347 if (!myHasAdjacentFaces)
350 // Extend the adjacent faces keeping the connection to the original faces
351 TopTools_IndexedDataMapOfShapeShape aFaceExtFaceMap;
352 ExtendAdjacentFaces(aMFAdjacent, aFaceExtFaceMap);
354 // Trim the extended faces
355 TrimExtendedFaces(aFaceExtFaceMap);
357 catch (Standard_Failure const&)
359 // Make sure the warning will be given on the higher level
360 myHasAdjacentFaces = Standard_True;
365 public: //! @name Obtain the result
367 //! Returns the map of faces of the feature
368 const TopTools_MapOfShape& FeatureFacesMap() const { return myFeatureFacesMap; }
370 //! Shows whether the adjacent faces have been found for the feature
371 Standard_Boolean HasAdjacentFaces() const { return myHasAdjacentFaces; }
373 //! Returns the Images map of the adjacent faces
374 const TopTools_IndexedDataMapOfShapeListOfShape& Faces() const { return myFaces; }
376 //! Returns the initial solids participating in the feature removal
377 const TopTools_IndexedMapOfShape& Solids() const { return mySolids; }
380 private: //! @name Private methods performing the operation
382 //! Finds the faces adjacent to the feature and stores them into outgoing map.
383 void FindAdjacentFaces(TopTools_IndexedMapOfShape& theMFAdjacent)
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());
390 // Find faces adjacent to the feature using the connection map
391 aIt.Initialize(myFeature);
392 for (; aIt.More(); aIt.Next())
394 const TopoDS_Shape& aF = aIt.Value();
395 TopExp_Explorer anExpE(aF, TopAbs_EDGE);
396 for (; anExpE.More(); anExpE.Next())
398 const TopoDS_Shape& aE = anExpE.Current();
399 const TopTools_ListOfShape* pAdjacentFaces = myEFMap->Seek(aE);
402 TopTools_ListIteratorOfListOfShape itLFA(*pAdjacentFaces);
403 for (; itLFA.More(); itLFA.Next())
405 const TopoDS_Shape& anAF = itLFA.Value();
406 if (!myFeatureFacesMap.Contains(anAF))
407 theMFAdjacent.Add(anAF);
411 // Find solids containing the feature face
412 const TopTools_ListOfShape* pLS = myFSMap->Seek(aF);
415 TopTools_ListIteratorOfListOfShape itLS(*pLS);
416 for (; itLS.More(); itLS.Next())
417 mySolids.Add(itLS.Value());
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)
425 TopExp_Explorer anExpEA(theMFAdjacent(i), TopAbs_EDGE);
426 for (; anExpEA.More(); anExpEA.Next())
428 // Faces adjacent to the face adjacent to the feature
429 const TopTools_ListOfShape* pLFAA = myEFMap->Seek(anExpEA.Current());
432 TopTools_ListIteratorOfListOfShape itLFAA(*pLFAA);
433 for (; itLFAA.More(); itLFAA.Next())
435 // Solids containing the faces
436 const TopTools_ListOfShape* pLS = myFSMap->Seek(itLFAA.Value());
439 TopTools_ListIteratorOfListOfShape itLS(*pLS);
440 for (; itLS.More(); itLS.Next())
441 mySolids.Add(itLS.Value());
449 //! Extends the found adjacent faces and binds them to the original faces.
450 void ExtendAdjacentFaces(const TopTools_IndexedMapOfShape& theMFAdjacent,
451 TopTools_IndexedDataMapOfShapeShape& theFaceExtFaceMap)
453 // Get the extension value for the faces - half of the diagonal of bounding box of the feature
455 BRepBndLib::Add(myFeature, aFeatureBox);
457 const Standard_Real anExtLength = sqrt(aFeatureBox.SquareExtent());
459 const Standard_Integer aNbFA = theMFAdjacent.Extent();
460 for (Standard_Integer i = 1; i <= aNbFA; ++i)
462 const TopoDS_Face& aF = TopoDS::Face(theMFAdjacent(i));
465 BRepLib::ExtendFace(aF, anExtLength,
466 Standard_True, Standard_True,
467 Standard_True, Standard_True,
469 theFaceExtFaceMap.Add(aF, aFExt);
470 myHistory->AddModified(aF, aFExt);
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)
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));
485 aGFInter.SetRunParallel(myRunParallel);
487 // Intersection result
488 TopoDS_Shape anIntResult;
489 if (aGFInter.Arguments().Extent() > 1)
492 if (aGFInter.HasErrors())
495 anIntResult = aGFInter.Shape();
497 myHistory->Merge(aGFInter.History());
500 anIntResult = aGFInter.Arguments().First();
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);
507 // Get the splits of the extended faces after intersection
508 // and trim them by the edges of the original faces
510 // Map the edges of the Feature to avoid them during the trim
511 TopTools_IndexedMapOfShape aFeatureEdgesMap;
512 TopExp::MapShapes(myFeature, TopAbs_EDGE, aFeatureEdgesMap);
514 for (Standard_Integer i = 1; i <= aNbF; ++i)
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);
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)
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())
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))
540 TopTools_ListOfShape aLEIm;
541 TakeModified(aE, theGFInter, aLEIm);
542 TopTools_ListIteratorOfListOfShape itLEIm(aLEIm);
543 for (; itLEIm.More(); itLEIm.Next())
545 const TopoDS_Shape& aEIm = itLEIm.Value();
546 if (theEFExtMap.FindFromKey(aEIm).Extent() == 1)
547 aMExtEdges.Add(aEIm);
552 BOPAlgo_Builder aGFTrim;
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);
559 // Add edges of the original faces
560 TopTools_MapOfShape aMEdgesToCheckOri;
561 anExpE.Init(theFOriginal, TopAbs_EDGE);
562 for (; anExpE.More(); anExpE.Next())
564 const TopoDS_Edge& aE = TopoDS::Edge(anExpE.Current());
565 if (!theFeatureEdgesMap.Contains(aE))
567 aGFTrim.AddArgument(aE);
568 if (!BRep_Tool::Degenerated(aE) &&
569 !BRep_Tool::IsClosed(aE, theFOriginal))
571 if (!aMEdgesToCheckOri.Add(aE))
572 aMEdgesToCheckOri.Remove(aE);
577 // Avoid faces intersection
578 aGFTrim.SetGlue(BOPAlgo_GlueShift);
579 aGFTrim.SetRunParallel(myRunParallel);
580 aGFTrim.SetNonDestructive(Standard_True);
583 if (aGFTrim.HasErrors())
587 const TopoDS_Shape& aSplits = aGFTrim.Shape();
588 // Filter the trimmed faces and save the valid ones into result map
589 TopTools_ListOfShape aLFTrimmed;
591 TopExp_Explorer anExpF(aSplits, TopAbs_FACE);
592 for (; anExpF.More(); anExpF.Next())
594 const TopoDS_Shape& aSp = anExpF.Current();
595 anExpE.Init(aSp, TopAbs_EDGE);
596 for (; anExpE.More(); anExpE.Next())
598 if (aMExtEdges.Contains(anExpE.Current()))
602 aLFTrimmed.Append(aSp);
605 if (aLFTrimmed.Extent() > 1)
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);
614 // Check edges orientations
615 TopTools_MapOfShape aFacesToAvoid, aValidFaces;
616 FindExtraShapes(anEFMap, aMEdgesToCheckOri, aGFTrim, aFacesToAvoid, &aValidFaces);
618 if (aLFTrimmed.Extent() - aFacesToAvoid.Extent() > 1)
620 // It is possible that the splits are forming the different blocks.
621 // Take only those containing the valid faces.
623 BRep_Builder().MakeCompound(aCF);
624 itLF.Initialize(aLFTrimmed);
625 for (; itLF.More(); itLF.Next())
627 if (!aFacesToAvoid.Contains(itLF.Value()))
628 BRep_Builder().Add(aCF, itLF.Value());
631 TopTools_ListOfShape aLCB;
632 BOPTools_AlgoTools::MakeConnexityBlocks(aCF, TopAbs_EDGE, TopAbs_FACE, aLCB);
633 if (aLCB.Extent() > 1)
635 TopTools_ListIteratorOfListOfShape itLCB(aLCB);
636 for (; itLCB.More(); itLCB.Next())
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())
643 if (aValidFaces.Contains(itF.Value()))
649 for (itF.Initialize(aCB); itF.More(); itF.Next())
650 aFacesToAvoid.Add(itF.Value());
656 itLF.Initialize(aLFTrimmed);
659 if (aFacesToAvoid.Contains(itLF.Value()))
660 aLFTrimmed.Remove(itLF);
665 else if (aLFTrimmed.IsEmpty())
667 // Use all splits, including those having the bounds of extended face
669 for (; anExpF.More(); anExpF.Next())
670 aLFTrimmed.Append(anExpF.Current());
673 if (aLFTrimmed.Extent())
675 // Remove the internal edges and vertices from the faces
676 RemoveInternalWires(aLFTrimmed);
678 myFaces.Add(theFOriginal, aLFTrimmed);
681 // Update history after intersection of the extended face with bounds
682 myHistory->Merge(aGFTrim.History());
684 // Update history with all removed shapes
685 BRepTools_History aHistRem;
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);
693 TopTools_ListOfShape aLSplits;
694 aLSplits.Append(aSplits);
696 // Update the history with removed shapes
697 MakeRemoved(aLSplits, aHistRem, aResMap);
698 myHistory->Merge(aHistRem);
701 private: //! @name Fields
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
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
717 typedef NCollection_Vector<FillGap> VectorOfFillGap;
719 typedef BOPTools_Functor <FillGap, VectorOfFillGap> FillGapFunctor;
721 typedef BOPTools_Cnt <FillGapFunctor, VectorOfFillGap> FillGapCnt;
723 //=======================================================================
725 //=======================================================================
726 // function: RemoveFeatures
727 // purpose: Remove features by filling the gaps by extension of the
729 //=======================================================================
730 void BOPAlgo_RemoveFeatures::RemoveFeatures()
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.
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);
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);
749 // Tool for reconstruction of the faces adjacent to the feature
750 // in parallel threads if necessary.
751 VectorOfFillGap aVFG;
753 TopTools_ListIteratorOfListOfShape itF(myFeatures);
754 for (; itF.More(); itF.Next())
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);
764 // Perform the reconstruction of the adjacent faces
765 FillGapCnt::Perform(myRunParallel, aVFG);
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();
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)
781 FillGap& aFG = aVFG(i);
783 // No need to fill the history for solids if the history is not
784 // requested and the current feature is the last one.
785 Standard_Boolean isSolidsHistoryNeeded = HasHistory() || (i < (aNbF - 1));
787 // Perform removal of the single feature
788 RemoveFeature(aFG.Feature(), aFG.Solids(), aFG.FeatureFacesMap(),
789 aFG.HasAdjacentFaces(), aFG.Faces(), aFG.History(),
790 isSolidsHistoryNeeded);
794 //=======================================================================
795 // function: RemoveFeature
796 // purpose: Remove the single feature
797 //=======================================================================
798 void 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)
807 Standard_Boolean bFuseShapes = Standard_True;
808 const Standard_Integer aNbAF = theAdjFaces.Extent();
811 if (theHasAdjacentFaces)
813 // The adjacent faces have been found for the feature,
814 // but something went wrong during their rebuilding.
816 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
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;
826 // Rebuild the shape using MakerVolume algorithm avoiding the faces of the
827 // feature and replacing the adjacent faces with their images
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;
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;
843 // In the feature removal will participate only the solids connected to the feature
844 // or the faces adjacent to the feature.
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;
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);
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));
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);
875 // Add reconstructed adjacent faces
876 for (Standard_Integer i = 1; i <= aNbAF; ++i)
878 const TopTools_ListOfShape& aLFA = theAdjFaces(i);
879 if (aLFA.Extent() == 1)
881 const TopoDS_Shape& aFA = aLFA.First();
882 aMV.AddArgument(aFA);
883 aFacesToBeKept.Add(aFA);
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());
894 aMV.AddArgument(anAdjF);
895 aFacesToBeKept.Add(anAdjF);
900 // Look for internal edges in the original adjacent faces
901 const TopoDS_Shape& aFOr = theAdjFaces.FindKey(i);
902 FindInternals(aFOr, anInternalShapes);
910 // Add warning for the feature
911 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
915 // Result of MV operation
916 const TopoDS_Shape& aSolids = aMV.Shape();
917 TopExp_Explorer anExpS(aSolids, TopAbs_SOLID);
920 // No solids have been built - add warning for the feature
921 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
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.
931 // Splits of adjacent faces from previous runs
932 TopTools_MapOfShape anAdjFacesSplits;
933 for (Standard_Integer i = 1; i <= aNbAF; ++i)
935 const TopoDS_Shape& aF = theAdjFaces.FindKey(i);
936 const TopTools_ListOfShape& aLFIm = myHistory->Modified(aF);
938 anAdjFacesSplits.Add(aF);
941 TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
942 for (; itLFIm.More(); itLFIm.Next())
943 anAdjFacesSplits.Add(itLFIm.Value());
947 // Validate the result
948 Standard_Boolean bValid = Standard_True;
949 aNbFK = aFacesToBeKept.Extent();
950 for (Standard_Integer i = 1; i <= aNbFK && bValid; ++i)
952 const TopoDS_Shape& aS = aFacesToBeKept(i);
953 if (anAdjFacesSplits.Contains(aS))
955 TopExp_Explorer anExpF(aS, TopAbs_FACE);
956 for (; anExpF.More(); anExpF.Next())
958 const TopoDS_Shape& aF = anExpF.Current();
959 if (!aMV.IsDeleted(aF))
962 bValid = anExpF.More();
967 // Add warning for the feature
968 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
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);
979 if (aLSRes.Extent() != theSolids.Extent())
981 // Add warning for the feature
982 AddWarning(new BOPAlgo_AlertUnableToRemoveTheFeature(theFeature));
986 // Remove internal wires from the faces, possibly appeared after intersection
987 RemoveInternalWires(aLSRes, &anInternalShapes);
989 // Update history with:
990 // History of adjacent faces reconstruction
991 myHistory->Merge(theAdjFacesHistory);
992 // History of intersection
993 myHistory->Merge(aMV.History());
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);
1003 // Remove internal shapes and extra faces
1004 BRepTools_History aRemHist;
1005 anInternalShapes.Append(aRemovedShapes);
1006 MakeRemoved(anInternalShapes, aRemHist, aMSRes);
1007 myHistory->Merge(aRemHist);
1010 // Fill the history for the solids
1011 if (theSolidsHistoryNeeded)
1013 BRepTools_History aSolidsHistory;
1014 FillSolidsHistory(aSolidsToRebuild, aLSRes, theAdjFaces, aMV, aSolidsHistory);
1015 myHistory->Merge(aSolidsHistory);
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());
1025 // Add unmodified solids
1026 itLS.Initialize(anUnTouchedSolids);
1027 for (; itLS.More(); itLS.Next())
1028 aBB.Add(aCRes, itLS.Value());
1034 //=======================================================================
1035 // function: UpdateHistory
1036 // purpose: Update history with the removed features
1037 //=======================================================================
1038 void BOPAlgo_RemoveFeatures::UpdateHistory()
1045 TopExp::MapShapes(myShape, myMapShape);
1047 // Update the history
1048 BRepTools_History aHistory;
1050 const Standard_Integer aNbS = myInputsMap.Extent();
1051 for (Standard_Integer i = 1; i <= aNbS; ++i)
1053 const TopoDS_Shape& aS = myInputsMap(i);
1054 if (!BRepTools_History::IsSupportedType(aS))
1057 if (myHistory->IsRemoved(aS))
1060 // Check if the shape has any trace in the result
1061 const TopTools_ListOfShape& aLSIm = myHistory->Modified(aS);
1062 if (aLSIm.IsEmpty())
1064 if (!myMapShape.Contains(aS))
1065 aHistory.Remove(aS);
1068 TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
1069 for (; itLSIm.More(); itLSIm.Next())
1071 if (!myMapShape.Contains(itLSIm.Value()))
1072 aHistory.Remove(itLSIm.Value());
1076 myHistory->Merge(aHistory);
1079 //=======================================================================
1080 // function: SimplifyResult
1081 // purpose: Simplifies the result by removing extra edges and vertices
1082 // created during operation
1083 //=======================================================================
1084 void BOPAlgo_RemoveFeatures::SimplifyResult()
1086 if (myShape.IsSame(myInputShape))
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
1093 if (myMapShape.IsEmpty())
1094 TopExp::MapShapes(myShape, myMapShape);
1096 const Standard_Integer aNbS = myInputsMap.Extent();
1097 for (Standard_Integer i = 1; i <= aNbS; ++i)
1099 if (myMapShape.Contains(myInputsMap(i)))
1100 aSDTool.KeepShape(myInputsMap(i));
1103 // Perform unification
1105 myShape = aSDTool.Shape();
1107 myHistory->Merge(aSDTool.History());
1110 //=======================================================================
1111 // function: PostTreat
1112 // purpose: Restore the type of the initial shape
1113 //=======================================================================
1114 void BOPAlgo_RemoveFeatures::PostTreat()
1116 const TopAbs_ShapeEnum anInputType = myInputShape.ShapeType();
1117 const TopAbs_ShapeEnum aResType = myShape.ShapeType();
1118 if (aResType == anInputType)
1121 TopExp_Explorer anExpS(myShape, TopAbs_SOLID);
1123 if (anInputType == TopAbs_SOLID)
1125 myShape = anExpS.Current();
1130 if (anInputType == TopAbs_COMPOUND)
1131 BRep_Builder().MakeCompound(TopoDS::Compound(aRes));
1133 BRep_Builder().MakeCompSolid(TopoDS::CompSolid(aRes));
1135 for (; anExpS.More(); anExpS.Next())
1136 BRep_Builder().Add(aRes, anExpS.Current());
1141 //=======================================================================
1142 // static methods definition
1143 //=======================================================================
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 //=======================================================================
1150 void MakeRemoved(const TopTools_ListOfShape& theShapes,
1151 BRepTools_History& theHistory,
1152 const TopTools_IndexedMapOfShape& theKeepShapes)
1154 TopTools_IndexedMapOfShape aShapesMap;
1155 TopTools_ListIteratorOfListOfShape it(theShapes);
1156 for (; it.More(); it.Next())
1157 TopExp::MapShapes(it.Value(), aShapesMap);
1159 const Standard_Integer aNbS = aShapesMap.Extent();
1160 for (Standard_Integer i = 1; i <= aNbS; ++i)
1162 const TopoDS_Shape& aS = aShapesMap(i);
1163 if (!theKeepShapes.Contains(aS) &&
1164 BRepTools_History::IsSupportedType(aS))
1166 theHistory.Remove(aS);
1171 //=======================================================================
1172 // function: FindInternals
1173 // purpose: Looks for internal shapes inside the face or solid
1174 //=======================================================================
1175 void FindInternals(const TopoDS_Shape& theS,
1176 TopTools_ListOfShape& theLInt)
1178 TopoDS_Iterator itS(theS);
1179 for (; itS.More(); itS.Next())
1181 const TopoDS_Shape& aSS = itS.Value();
1182 if (aSS.Orientation() == TopAbs_INTERNAL)
1183 theLInt.Append(aSS);
1186 TopoDS_Iterator itSS(aSS);
1187 for (; itSS.More(); itSS.Next())
1189 if (itSS.Value().Orientation() == TopAbs_INTERNAL)
1191 theLInt.Append(aSS);
1199 //=======================================================================
1200 // function: RemoveInternalWires
1201 // purpose: Removes internal wires from the faces
1202 //=======================================================================
1203 void RemoveInternalWires(const TopTools_ListOfShape& theShapes,
1204 TopTools_ListOfShape *theRemoved)
1206 TopTools_ListIteratorOfListOfShape itLS(theShapes);
1207 for (; itLS.More(); itLS.Next())
1209 const TopoDS_Shape& aShape = itLS.Value();
1210 TopExp_Explorer anExpF(aShape, TopAbs_FACE);
1211 for (; anExpF.More(); anExpF.Next())
1213 TopoDS_Face& aF = *(TopoDS_Face*)&anExpF.Current();
1214 TopTools_ListOfShape aLWToRemove;
1215 FindInternals(aF, aLWToRemove);
1216 if (aLWToRemove.Extent())
1218 aF.Free(Standard_True);
1219 TopTools_ListIteratorOfListOfShape itR(aLWToRemove);
1220 for (; itR.More(); itR.Next())
1223 theRemoved->Append(itR.Value());
1224 BRep_Builder().Remove(aF, itR.Value());
1226 aF.Free(Standard_False);
1232 //=======================================================================
1233 // function: GetOriginalFaces
1234 // purpose: Get original faces from my face
1235 //=======================================================================
1236 void 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)
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.
1252 // Update solids after removal of previous features
1253 const Standard_Integer aNbSols = theSolids.Extent();
1254 for (Standard_Integer i = 1; i <= aNbSols; ++i)
1256 const TopoDS_Shape& aSol = theSolids(i);
1257 const TopTools_ListOfShape& aLFIm = theHistory->Modified(aSol);
1258 if (aLFIm.IsEmpty())
1259 theSolidsToRebuild.Add(aSol);
1261 theSolidsToRebuild.Add(aLFIm.First());
1264 // Splits of the feature faces
1265 TopTools_MapOfShape aFeatureFacesSplits;
1266 TopTools_MapIteratorOfMapOfShape itM(theFeatureFacesMap);
1267 for (; itM.More(); itM.Next())
1269 const TopoDS_Shape& aF = itM.Value();
1270 const TopTools_ListOfShape& aLFIm = theHistory->Modified(aF);
1271 if (aLFIm.IsEmpty())
1272 aFeatureFacesSplits.Add(aF);
1275 TopTools_ListIteratorOfListOfShape itLFIm(aLFIm);
1276 for (; itLFIm.More(); itLFIm.Next())
1277 aFeatureFacesSplits.Add(itLFIm.Value());
1281 TopExp_Explorer anExpS(theShape, TopAbs_SOLID);
1282 for (; anExpS.More(); anExpS.Next())
1284 const TopoDS_Shape& aSol = anExpS.Current();
1286 // Check if the solid has to be reconstructed
1287 if (!theSolidsToRebuild.Contains(aSol))
1290 theUnTouchedSolids.Append(aSol);
1294 TopoDS_Iterator itSh(aSol);
1295 for (; itSh.More(); itSh.Next())
1297 const TopoDS_Shape& aSh = itSh.Value();
1298 if (aSh.ShapeType() != TopAbs_SHELL)
1300 theInternalShapes.Append(aSh);
1304 TopoDS_Iterator itF(aSh);
1305 for (; itF.More(); itF.Next())
1307 const TopoDS_Shape& aF = itF.Value();
1308 // Avoid the feature faces
1309 if (aFeatureFacesSplits.Contains(aF))
1312 // Avoid the adjacent faces
1313 if (theAdjFaces.Contains(aF))
1316 if (aF.Orientation() != TopAbs_INTERNAL)
1318 theFacesToBeKept.Add(aF);
1320 if (!theFacesToCheckOri.Add(aF))
1322 theFacesToCheckOri.Remove(aF);
1323 theSharedFaces.Append(aF);
1327 theInternalShapes.Append(aSh);
1333 //=======================================================================
1334 // function: FindShape
1335 // purpose: Find the shape in the other shape
1336 //=======================================================================
1337 void FindShape(const TopoDS_Shape& theSWhat,
1338 const TopoDS_Shape& theSWhere,
1339 TopoDS_Shape& theSFound)
1341 TopExp_Explorer anExp(theSWhere, theSWhat.ShapeType());
1342 for (; anExp.More(); anExp.Next())
1344 const TopoDS_Shape& aS = anExp.Current();
1345 if (aS.IsSame(theSWhat))
1353 //=======================================================================
1354 // function: GetValidSolids
1355 // purpose: Checks the validity of the solids and keeps only valid ones
1356 //=======================================================================
1357 void 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)
1365 TopExp_Explorer anExpS(theMV.Shape(), TopAbs_SOLID);
1366 for (; anExpS.More(); anExpS.Next())
1367 theLSRes.Append(anExpS.Current());
1369 if (theLSRes.Extent() > theNbSol)
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);
1377 TopTools_ListIteratorOfListOfShape itLS(theLSRes);
1378 for (; itLS.More(); )
1380 if (aSolidsToAvoid.Contains(itLS.Value()))
1381 theLSRes.Remove(itLS);
1387 if (theLSRes.Extent() > theNbSol)
1389 // Check if the splits of the adjacent faces split the solids
1390 AvoidExtraSharedFaces(theLSRes, aSharedFaces, theMV, theRemovedShapes);
1393 if (theLSRes.Extent() > theNbSol)
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);
1401 TopTools_ListIteratorOfListOfShape itLS(theLSRes);
1402 for (; itLS.More(); )
1404 anExpF.Init(itLS.Value(), TopAbs_FACE);
1405 for (; anExpF.More(); anExpF.Next())
1407 if (anOrigFacesRes.Contains(anExpF.Current()))
1412 theRemovedShapes.Append(itLS.Value());
1413 theLSRes.Remove(itLS);
1421 //=======================================================================
1422 // function: FindExtraShape
1423 // purpose: Find shapes possibly filling the holes in the original shape
1424 //=======================================================================
1425 void FindExtraShapes(const TopTools_IndexedDataMapOfShapeListOfShape& theConnectionMap,
1426 const TopTools_MapOfShape& theShapesToCheckOri,
1427 BOPAlgo_Builder& theBuilder,
1428 TopTools_MapOfShape& theShapesToAvoid,
1429 TopTools_MapOfShape* theValidShapes)
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())
1437 const TopoDS_Shape& aSToCheckOri = itM.Value();
1438 // Check modification of the shape during intersection
1439 TopTools_ListOfShape aLSIm;
1440 TakeModified(aSToCheckOri, theBuilder, aLSIm);
1442 TopTools_ListIteratorOfListOfShape itLSIm(aLSIm);
1443 for (; itLSIm.More(); itLSIm.Next())
1445 const TopoDS_Shape& aSIm = itLSIm.Value();
1447 const TopTools_ListOfShape* pShapesToValidate = theConnectionMap.Seek(aSIm);
1448 if (!pShapesToValidate)
1451 TopTools_ListIteratorOfListOfShape itSV(*pShapesToValidate);
1452 for (; itSV.More(); itSV.Next())
1454 const TopoDS_Shape& aShapeToValidate = itSV.Value();
1455 if (pValidShapes->Contains(aShapeToValidate))
1458 TopoDS_Face aSInShape;
1459 FindShape(aSIm, aShapeToValidate, aSInShape);
1461 Standard_Boolean bSameOri =
1462 !BOPTools_AlgoTools::IsSplitToReverse(aSInShape, aSToCheckOri, aCtx);
1465 pValidShapes->Add(aShapeToValidate);
1467 theShapesToAvoid.Add(aShapeToValidate);
1472 itM.Initialize(*pValidShapes);
1473 for (; itM.More(); itM.Next())
1474 theShapesToAvoid.Remove(itM.Value());
1477 //=======================================================================
1478 // function: AvoidExtraSharedFaces
1479 // purpose: Looks for the extra faces splitting the solids
1480 //=======================================================================
1481 void AvoidExtraSharedFaces(TopTools_ListOfShape& theLSolids,
1482 const TopTools_ListOfShape& theLFSharedToAvoid,
1483 BOPAlgo_Builder& theBuilder,
1484 TopTools_ListOfShape& theExtraFaces)
1486 // Get all splits of shared faces to avoid in the check
1487 TopTools_MapOfShape aMFSharedSp;
1489 TopTools_ListOfShape aLFSharedSp;
1490 TopTools_ListIteratorOfListOfShape itLFS(theLFSharedToAvoid);
1491 for (; itLFS.More(); itLFS.Next())
1492 TakeModified(itLFS.Value(), theBuilder, aMFSharedSp);
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);
1500 TopTools_ListOfShape anExtraFaces;
1501 TopTools_ListOfShape aLFArguments;
1502 itLS.Initialize(theLSolids);
1503 for (; itLS.More(); itLS.Next())
1505 const TopoDS_Shape& aSol = itLS.Value();
1506 TopExp_Explorer anExpF(aSol, TopAbs_FACE);
1507 for (; anExpF.More(); anExpF.Next())
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);
1514 anExtraFaces.Append(aF);
1518 if (anExtraFaces.IsEmpty())
1521 // Rebuild the solids avoiding the extra faces
1522 BOPAlgo_BuilderSolid aBS;
1523 aBS.SetAvoidInternalShapes(Standard_True);
1524 aBS.SetShapes(aLFArguments);
1526 if (aBS.HasErrors())
1529 theLSolids = aBS.Areas();
1530 theExtraFaces.Append(anExtraFaces);
1533 //=======================================================================
1534 // function: FillSolidsHistory
1535 // purpose: Fills the history of solids modifications
1536 //=======================================================================
1537 void FillSolidsHistory(const TopTools_IndexedMapOfShape& theSolIn,
1538 TopTools_ListOfShape& theSolidsOut,
1539 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
1540 BOPAlgo_Builder& theBuilder,
1541 BRepTools_History& theSolidsHistory)
1543 const Standard_Integer aNbS = theSolIn.Extent();
1544 for (Standard_Integer i = 1; i <= aNbS; ++i)
1546 const TopoDS_Shape& aSolIn = theSolIn(i);
1548 TopoDS_Shape aSolOut;
1549 FindSolid(aSolIn, theSolidsOut, theAdjFaces, theBuilder, aSolOut);
1551 if (aSolOut.IsNull())
1553 theSolidsHistory.Remove(aSolIn);
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))
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())
1568 if (itLS.Value().IsSame(aSolOut))
1570 theSolidsOut.InsertBefore(aSolIn, itLS);
1571 theSolidsOut.Remove(itLS);
1578 theSolidsHistory.AddModified(aSolIn, aSolOut);
1583 //=======================================================================
1584 // function: TakeModified
1585 // purpose: Stores the modified object into the list
1586 //=======================================================================
1587 void TakeModified(const TopoDS_Shape& theS,
1588 BOPAlgo_Builder& theBuilder,
1589 TopTools_ListOfShape& theList)
1591 const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
1592 if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
1593 theList.Append(theS);
1596 TopTools_ListIteratorOfListOfShape itM(aModified);
1597 for (; itM.More(); itM.Next())
1598 theList.Append(itM.Value());
1601 //=======================================================================
1602 // function: TakeModified
1603 // purpose: Stores the modified object into the map
1604 //=======================================================================
1605 void TakeModified(const TopoDS_Shape& theS,
1606 BOPAlgo_Builder& theBuilder,
1607 TopTools_MapOfShape& theMap)
1609 const TopTools_ListOfShape& aModified = theBuilder.Modified(theS);
1610 if (aModified.IsEmpty() && !theBuilder.IsDeleted(theS))
1614 TopTools_ListIteratorOfListOfShape itM(aModified);
1615 for (; itM.More(); itM.Next())
1616 theMap.Add(itM.Value());
1620 //=======================================================================
1621 // function: FindSolid
1622 // purpose: Looks for the image of the solid in the list of resulting solids
1623 //=======================================================================
1624 void FindSolid(const TopoDS_Shape& theSolIn,
1625 const TopTools_ListOfShape& theSolidsRes,
1626 const TopTools_IndexedDataMapOfShapeListOfShape& theAdjFaces,
1627 BOPAlgo_Builder& theBuilder,
1628 TopoDS_Shape& theSolOut)
1630 Handle(IntTools_Context) aCtx = theBuilder.Context();
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())
1636 const TopoDS_Shape& aFS = anExpF.Current();
1637 // Images of the face
1638 TopTools_MapOfShape aMFSIm;
1639 const TopTools_ListOfShape* pLFA = theAdjFaces.Seek(aFS);
1642 TopTools_ListIteratorOfListOfShape itLFA(*pLFA);
1643 for (; itLFA.More(); itLFA.Next())
1644 TakeModified(itLFA.Value(), theBuilder, aMFSIm);
1648 TakeModified(aFS, theBuilder, aMFSIm);
1651 // Find any of these faces in the list of solids
1652 TopTools_ListIteratorOfListOfShape itLS(theSolidsRes);
1653 for (; itLS.More(); itLS.Next())
1655 const TopoDS_Shape& aSol = itLS.Value();
1656 TopExp_Explorer anExpFOut(aSol, TopAbs_FACE);
1657 for (; anExpFOut.More(); anExpFOut.Next())
1659 const TopoDS_Shape& aF = anExpFOut.Current();
1660 if (aMFSIm.Contains(aF))
1662 // check orientations
1663 if (!BOPTools_AlgoTools::IsSplitToReverse(aF, aFS, aCtx))