1 // Copyright (C) 2014-2019 CEA/DEN, EDF R&D
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11 // Lesser General Public License for more details.
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "GeomAlgoAPI_Boolean.h"
22 #include <GeomAlgoAPI_DFLoader.h>
23 #include <GeomAlgoAPI_ShapeTools.h>
25 #include <BOPAlgo_BOP.hxx>
26 #include <TopTools_ListOfShape.hxx>
27 #include <TopoDS_Iterator.hxx>
28 #include <TopExp_Explorer.hxx>
30 //=================================================================================================
31 GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(const GeomShapePtr theObject,
32 const GeomShapePtr theTool,
33 const GeomAlgoAPI_Tools::BOPType theOperationType)
35 ListOfShape aListWithObject, aListWithTool;
36 aListWithObject.push_back(theObject);
37 aListWithTool.push_back(theTool);
38 build(aListWithObject, aListWithTool, theOperationType);
41 //=================================================================================================
42 GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(const GeomShapePtr theObject,
43 const ListOfShape& theTools,
44 const GeomAlgoAPI_Tools::BOPType theOperationType)
46 ListOfShape aListWithObject;
47 aListWithObject.push_back(theObject);
48 build(aListWithObject, theTools, theOperationType);
51 //=================================================================================================
52 GeomAlgoAPI_Boolean::GeomAlgoAPI_Boolean(const ListOfShape& theObjects,
53 const ListOfShape& theTools,
54 const GeomAlgoAPI_Tools::BOPType theOperationType)
56 build(theObjects, theTools, theOperationType);
60 //=================================================================================================
61 void GeomAlgoAPI_Boolean::build(const ListOfShape& theObjects,
62 const ListOfShape& theTools,
63 const GeomAlgoAPI_Tools::BOPType theOperationType)
65 if(theObjects.empty() || theTools.empty()) {
70 TopTools_ListOfShape anObjects;
71 for(ListOfShape::const_iterator
72 anObjectsIt = theObjects.begin(); anObjectsIt != theObjects.end(); anObjectsIt++)
74 anObjects.Append((*anObjectsIt)->impl<TopoDS_Shape>());
78 TopTools_ListOfShape aTools;
79 for(ListOfShape::const_iterator
80 aToolsIt = theTools.begin(); aToolsIt != theTools.end(); aToolsIt++)
82 aTools.Append((*aToolsIt)->impl<TopoDS_Shape>());
85 // Creating boolean operation.
86 BOPAlgo_BOP* aBuilder = new BOPAlgo_BOP();
87 switch (theOperationType) {
88 case GeomAlgoAPI_Tools::BOOL_CUT: {
89 aBuilder->SetOperation(BOPAlgo_CUT);
92 case GeomAlgoAPI_Tools::BOOL_FUSE: {
93 aBuilder->SetOperation(BOPAlgo_FUSE);
96 case GeomAlgoAPI_Tools::BOOL_COMMON: {
97 aBuilder->SetOperation(BOPAlgo_COMMON);
104 this->setImpl(aBuilder);
105 this->setBuilderType(OCCT_BOPAlgo_Builder);
106 aBuilder->SetArguments(anObjects);
107 aBuilder->SetTools(aTools);
109 // Set parallel processing mode (default is false)
110 Standard_Boolean bRunParallel = Standard_True;
111 aBuilder->SetRunParallel(bRunParallel);
113 // Building and getting result.
115 if (aBuilder->HasErrors())
117 TopoDS_Shape aResult = aBuilder->Shape();
119 if(aResult.ShapeType() == TopAbs_COMPOUND) {
120 aResult = GeomAlgoAPI_DFLoader::refineResult(aResult);
122 if(aResult.ShapeType() == TopAbs_COMPOUND) {
123 std::shared_ptr<GeomAPI_Shape> aGeomShape(new GeomAPI_Shape);
124 aGeomShape->setImpl(new TopoDS_Shape(aResult));
125 ListOfShape aResults;
126 aGeomShape = GeomAlgoAPI_ShapeTools::combineShapes(aGeomShape,
127 GeomAPI_Shape::COMPSOLID,
129 aResult = aGeomShape->impl<TopoDS_Shape>();
132 std::shared_ptr<GeomAPI_Shape> aShape(new GeomAPI_Shape());
133 aShape->setImpl(new TopoDS_Shape(aResult));
134 this->setShape(aShape);
138 static bool isHistoryType(TopAbs_ShapeEnum theType) {
139 return theType == TopAbs_VERTEX || theType == TopAbs_EDGE ||
140 theType == TopAbs_FACE || theType == TopAbs_SOLID;
143 /// searches the corresponding result for theOld
144 static void searchResult(const TopoDS_Shape& theOld, const TopoDS_Shape& theResult,
145 BOPAlgo_BOP* theBuilder, TopTools_MapOfShape& theNews)
147 if (theResult.ShapeType() == theOld.ShapeType()) { // check some sub-shape produces a sub-result
148 if (theOld.IsSame(theResult)) {
149 theNews.Add(theResult);
152 // searching for new result by sub-shapes of aSubType type
153 TopAbs_ShapeEnum aSubType = TopAbs_ShapeEnum(int(theOld.ShapeType()) + 1);
154 while(aSubType < TopAbs_VERTEX && !isHistoryType(aSubType))
155 aSubType = TopAbs_ShapeEnum(int(aSubType) + 1);
156 if (aSubType == TopAbs_SHAPE)
158 TopTools_MapOfShape aResSubs;
159 for(TopExp_Explorer aResExp(theResult, aSubType); aResExp.More(); aResExp.Next())
160 aResSubs.Add(aResExp.Current());
161 for(TopExp_Explorer anExp(theOld, aSubType); anExp.More(); anExp.Next()) {
162 const TopTools_ListOfShape& aNewSubs = theBuilder->Modified(anExp.Current());
163 // searching for this new sub in theResult
164 for(TopTools_ListIteratorOfListOfShape aNewSub(aNewSubs); aNewSub.More(); aNewSub.Next()) {
165 if (aResSubs.Contains(aNewSub.Value())) {
166 theNews.Add(theResult);
171 } else if (theResult.ShapeType() < theOld.ShapeType()) { // recursive search among sub-shapes
172 for(TopoDS_Iterator aSubResults(theResult); aSubResults.More(); aSubResults.Next()) {
173 searchResult(theOld, aSubResults.Value(), theBuilder, theNews);
178 // check the shape is on the higher level of compound or compsolid
179 bool isInComp(const TopoDS_Shape& theComp, const TopoDS_Shape& theShape) {
180 if (theComp.ShapeType() == TopAbs_COMPOUND || theComp.ShapeType() == TopAbs_COMPSOLID) {
181 for(TopoDS_Iterator anIter(theComp); anIter.More(); anIter.Next()) {
182 if (isInComp(anIter.Value(), theShape))
185 } else return theShape.IsSame(theComp);
189 //=================================================================================================
190 /// make arguments of Fuse produce result shapes with "modified" evolution
191 void GeomAlgoAPI_Boolean::modified(const GeomShapePtr theOldShape, ListOfShape& theNewShapes)
193 BOPAlgo_BOP* aBuilder = this->implPtr<BOPAlgo_BOP>();
194 if (aBuilder->Operation() == BOPAlgo_FUSE) { // only for fuse and when old is and argument
195 TopoDS_Shape anOld = theOldShape->impl<TopoDS_Shape>();
196 bool isOldComp = anOld.ShapeType() == TopAbs_COMPOUND || anOld.ShapeType() == TopAbs_COMPSOLID;
198 TopTools_ListIteratorOfListOfShape anIter(aBuilder->Arguments());
199 for(; !aFound && anIter.More(); anIter.Next())
200 aFound = anOld.IsSame(anIter.Value()) || (!isOldComp && isInComp(anIter.Value(), anOld));
201 for(anIter.Initialize(aBuilder->Tools()); !aFound && anIter.More(); anIter.Next())
202 aFound = anOld.IsSame(anIter.Value()) || (!isOldComp && isInComp(anIter.Value(), anOld));
204 TopoDS_Shape aResult = aBuilder->Shape();
205 TopTools_MapOfShape aNewsMap;
206 searchResult(anOld, aResult, aBuilder, aNewsMap);
207 if (!aNewsMap.IsEmpty()) {
208 for(TopTools_MapIteratorOfMapOfShape aNewsIter(aNewsMap);
209 aNewsIter.More(); aNewsIter.Next())
211 GeomShapePtr aShape(new GeomAPI_Shape);
212 aShape->setImpl<TopoDS_Shape>(new TopoDS_Shape(aNewsIter.Value()));
213 theNewShapes.push_back(aShape);
219 GeomAlgoAPI_MakeShape::modified(theOldShape, theNewShapes); // default behavior