1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: FeaturesPlugin_CompositeBoolean.cpp
4 // Created: 11 June 2015
5 // Author: Dmitry Bobylev
7 #include <FeaturesPlugin_CompositeBoolean.h>
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_ResultBody.h>
12 #include <ModelAPI_ResultConstruction.h>
14 #include <GeomAlgoAPI_ShapeProps.h>
16 //=================================================================================================
17 void FeaturesPlugin_CompositeBoolean::initAttributes()
19 data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId());
21 // Boolean works with solids always.
22 data()->addAttribute(BOOLEAN_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
23 AttributeSelectionListPtr aSelection = data()->selectionList(BOOLEAN_OBJECTS_ID());
24 aSelection->setSelectionType("SOLID");
26 initMakeSolidsAttributes();
29 //=================================================================================================
30 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeBoolean::addFeature(std::string theID)
32 std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
34 data()->reference(SKETCH_OBJECT_ID())->setValue(aNew);
36 // set as current also after it becomes sub to set correctly enabled for other sketch subs
37 document()->setCurrentFeature(aNew, false);
41 //=================================================================================================
42 int FeaturesPlugin_CompositeBoolean::numberOfSubs(bool forTree) const
44 ObjectPtr aObj = data()->reference(SKETCH_OBJECT_ID())->value();
45 return aObj.get()? 1 : 0;
48 //=================================================================================================
49 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeBoolean::subFeature(const int theIndex, bool forTree) const
52 return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_OBJECT_ID())->value());
53 return std::shared_ptr<ModelAPI_Feature>();
56 //=================================================================================================
57 int FeaturesPlugin_CompositeBoolean::subFeatureId(const int theIndex) const
59 std::shared_ptr<ModelAPI_Feature> aFeature = subFeature(theIndex);
61 return aFeature->data()->featureId();
65 //=================================================================================================
66 bool FeaturesPlugin_CompositeBoolean::isSub(ObjectPtr theObject) const
68 // check is this feature of result
69 FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
73 ObjectPtr aSub = data()->reference(SKETCH_OBJECT_ID())->value();
74 return aSub == theObject;
77 //=================================================================================================
78 void FeaturesPlugin_CompositeBoolean::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
82 //=================================================================================================
83 void FeaturesPlugin_CompositeBoolean::erase()
86 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_OBJECT_ID())->value());
87 if (aSketch.get() && aSketch->data()->isValid()) {
88 document()->removeFeature(aSketch);
90 ModelAPI_CompositeFeature::erase();
94 //=================================================================================================
95 void FeaturesPlugin_CompositeBoolean::execute()
97 // Getting faces to create solids.
98 std::shared_ptr<ModelAPI_Feature> aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
99 reference(SKETCH_OBJECT_ID())->value());
100 if(!aSketchFeature) {
103 ResultPtr aSketchRes = aSketchFeature->results().front();
104 ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
105 if(!aConstruction.get()) {
108 int aSketchFacesNum = aConstruction->facesNum();
109 if(aSketchFacesNum == 0) {
110 return; //TODO: set error message
112 ListOfShape aSketchFacesList;
113 for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) {
114 std::shared_ptr<GeomAPI_Shape> aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
115 aSketchFacesList.push_back(aFace);
118 // Pass faces to soldis creation function.
119 ListOfShape aBooleanTools = MakeSolids(aSketchFacesList);
120 if(aBooleanTools.empty()) {
124 // Getting objects for boolean operation.
125 ListOfShape aBooleanObjects;
126 AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID());
127 if (anObjectsSelList->size() == 0) {
130 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
131 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
132 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
133 if(!anObject.get()) {
136 aBooleanObjects.push_back(anObject);
139 // Cut from each object solids.
140 int aResultIndex = 0;
142 switch(myBooleanOperationType) {
143 case GeomAlgoAPI_Boolean::BOOL_CUT:
144 case GeomAlgoAPI_Boolean::BOOL_COMMON:{
145 // Cut each object with all tools
146 for(ListOfShape::iterator anObjectsIt = aBooleanObjects.begin(); anObjectsIt != aBooleanObjects.end(); anObjectsIt++) {
147 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
148 ListOfShape aListWithObject;
149 aListWithObject.push_back(anObject);
150 GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aBooleanTools, myBooleanOperationType);
152 // Checking that the algorithm worked properly.
153 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
154 setError("Boolean algorithm failed");
158 if(GeomAlgoAPI_ShapeProps::volume(aBoolAlgo.shape()) > 1.e-7) {
159 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
160 LoadNamingDS(aResultBody, anObject, aBooleanTools, aBoolAlgo);
161 setResult(aResultBody, aResultIndex);
167 case GeomAlgoAPI_Boolean::BOOL_FUSE: {
168 // Fuse all objects and all tools.
169 GeomAlgoAPI_Boolean aBoolAlgo(aBooleanObjects, aBooleanTools, myBooleanOperationType);
171 // Checking that the algorithm worked properly.
172 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
173 setError("Boolean algorithm failed");
177 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
178 LoadNamingDS(aResultBody, aBooleanObjects.front(), aBooleanTools, aBoolAlgo);
179 setResult(aResultBody, aResultIndex);
184 setError("Error: wrong type of boolean operation");
189 // Remove the rest results if there were produced in the previous pass.
190 removeResults(aResultIndex);
193 //=================================================================================================
194 void FeaturesPlugin_CompositeBoolean::LoadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
195 const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
196 const ListOfShape& theTools,
197 const GeomAlgoAPI_Boolean& theAlgo)
200 if(theBaseShape->isEqual(theAlgo.shape())) {
201 theResultBody->store(theAlgo.shape());
203 theResultBody->storeModified(theBaseShape, theAlgo.shape());
205 GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
207 const int aModTag = 1;
208 const int aDeleteTag = 2;
209 const std::string aModName = "Modified";
210 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE,
211 aModTag, aModName, *theAlgo.mapOfShapes().get());
212 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, aDeleteTag);
214 for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
215 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE,
216 aModTag, aModName, *theAlgo.mapOfShapes().get());
217 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, aDeleteTag);