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()
85 if (data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
87 std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_OBJECT_ID())->value());
88 if (aSketch.get() && aSketch->data()->isValid()) {
89 document()->removeFeature(aSketch);
92 ModelAPI_CompositeFeature::erase();
96 //=================================================================================================
97 void FeaturesPlugin_CompositeBoolean::execute()
99 // Getting faces to create solids.
100 std::shared_ptr<ModelAPI_Feature> aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
101 reference(SKETCH_OBJECT_ID())->value());
102 if(!aSketchFeature) {
105 ResultPtr aSketchRes = aSketchFeature->results().front();
106 ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
107 if(!aConstruction.get()) {
110 int aSketchFacesNum = aConstruction->facesNum();
111 if(aSketchFacesNum == 0) {
112 return; //TODO: set error message
114 ListOfShape aSketchFacesList;
115 for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) {
116 std::shared_ptr<GeomAPI_Shape> aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
117 aSketchFacesList.push_back(aFace);
120 // Pass faces to soldis creation function.
121 ListOfShape aBooleanTools = MakeSolids(aSketchFacesList);
122 if(aBooleanTools.empty()) {
126 // Getting objects for boolean operation.
127 ListOfShape aBooleanObjects;
128 AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID());
129 if (anObjectsSelList->size() == 0) {
132 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
133 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
134 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
135 if(!anObject.get()) {
138 aBooleanObjects.push_back(anObject);
141 // Cut from each object solids.
142 int aResultIndex = 0;
144 switch(myBooleanOperationType) {
145 case GeomAlgoAPI_Boolean::BOOL_CUT:
146 case GeomAlgoAPI_Boolean::BOOL_COMMON:{
147 // Cut each object with all tools
148 for(ListOfShape::iterator anObjectsIt = aBooleanObjects.begin(); anObjectsIt != aBooleanObjects.end(); anObjectsIt++) {
149 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
150 ListOfShape aListWithObject;
151 aListWithObject.push_back(anObject);
152 GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aBooleanTools, myBooleanOperationType);
154 // Checking that the algorithm worked properly.
155 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
156 setError("Boolean algorithm failed");
160 if(GeomAlgoAPI_ShapeProps::volume(aBoolAlgo.shape()) > 1.e-7) {
161 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
162 LoadNamingDS(aResultBody, anObject, aBooleanTools, aBoolAlgo);
163 setResult(aResultBody, aResultIndex);
169 case GeomAlgoAPI_Boolean::BOOL_FUSE: {
170 // Fuse all objects and all tools.
171 GeomAlgoAPI_Boolean aBoolAlgo(aBooleanObjects, aBooleanTools, myBooleanOperationType);
173 // Checking that the algorithm worked properly.
174 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
175 setError("Boolean algorithm failed");
179 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
180 LoadNamingDS(aResultBody, aBooleanObjects.front(), aBooleanTools, aBoolAlgo);
181 setResult(aResultBody, aResultIndex);
186 setError("Error: wrong type of boolean operation");
191 // Remove the rest results if there were produced in the previous pass.
192 removeResults(aResultIndex);
195 //=================================================================================================
196 void FeaturesPlugin_CompositeBoolean::LoadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
197 const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
198 const ListOfShape& theTools,
199 const GeomAlgoAPI_Boolean& theAlgo)
202 if(theBaseShape->isEqual(theAlgo.shape())) {
203 theResultBody->store(theAlgo.shape());
205 const int aModTag = 1;
206 const int aDeleteTag = 2;
207 const int aSubsolidsTag=3; /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
209 theResultBody->storeModified(theBaseShape, theAlgo.shape(), aSubsolidsTag);
211 GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
213 const std::string aModName = "Modified";
214 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE,
215 aModTag, aModName, *theAlgo.mapOfShapes().get());
216 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, aDeleteTag);
218 for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
219 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE,
220 aModTag, aModName, *theAlgo.mapOfShapes().get());
221 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, aDeleteTag);