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() 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) 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::execute()
85 // Getting faces to create solids.
86 std::shared_ptr<ModelAPI_Feature> aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
87 reference(SKETCH_OBJECT_ID())->value());
91 ResultPtr aSketchRes = aSketchFeature->results().front();
92 ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
93 if(!aConstruction.get()) {
96 int aSketchFacesNum = aConstruction->facesNum();
97 if(aSketchFacesNum == 0) {
98 return; //TODO: set error message
100 ListOfShape aSketchFacesList;
101 for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) {
102 std::shared_ptr<GeomAPI_Shape> aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
103 aSketchFacesList.push_back(aFace);
106 // Pass faces to soldis creation function.
107 ListOfShape aBooleanTools = MakeSolids(aSketchFacesList);
108 if(aBooleanTools.empty()) {
112 // Getting objects for boolean operation.
113 ListOfShape aBooleanObjects;
114 AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID());
115 if (anObjectsSelList->size() == 0) {
118 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
119 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
120 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
121 if(!anObject.get()) {
124 aBooleanObjects.push_back(anObject);
127 // Cut from each object solids.
128 int aResultIndex = 0;
130 switch(myBooleanOperationType) {
131 case GeomAlgoAPI_Boolean::BOOL_CUT:
132 case GeomAlgoAPI_Boolean::BOOL_COMMON:{
133 // Cut each object with all tools
134 for(ListOfShape::iterator anObjectsIt = aBooleanObjects.begin(); anObjectsIt != aBooleanObjects.end(); anObjectsIt++) {
135 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
136 ListOfShape aListWithObject;
137 aListWithObject.push_back(anObject);
138 GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aBooleanTools, myBooleanOperationType);
140 // Checking that the algorithm worked properly.
141 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
142 setError("Boolean algorithm failed");
146 if(GeomAlgoAPI_ShapeProps::volume(aBoolAlgo.shape()) > 1.e-7) {
147 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
148 LoadNamingDS(aResultBody, anObject, aBooleanTools, aBoolAlgo);
149 setResult(aResultBody, aResultIndex);
155 case GeomAlgoAPI_Boolean::BOOL_FUSE: {
156 // Fuse all objects and all tools.
157 GeomAlgoAPI_Boolean aBoolAlgo(aBooleanObjects, aBooleanTools, myBooleanOperationType);
159 // Checking that the algorithm worked properly.
160 if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
161 setError("Boolean algorithm failed");
165 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
166 LoadNamingDS(aResultBody, aBooleanObjects.front(), aBooleanTools, aBoolAlgo);
167 setResult(aResultBody, aResultIndex);
172 setError("Error: wrong type of boolean operation");
177 // Remove the rest results if there were produced in the previous pass.
178 removeResults(aResultIndex);
181 //=================================================================================================
182 void FeaturesPlugin_CompositeBoolean::LoadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
183 const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
184 const ListOfShape& theTools,
185 const GeomAlgoAPI_Boolean& theAlgo)
188 if(theBaseShape->isEqual(theAlgo.shape())) {
189 theResultBody->store(theAlgo.shape());
191 theResultBody->storeModified(theBaseShape, theAlgo.shape());
193 GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
195 const int aModTag = 1;
196 const int aDeleteTag = 2;
197 const std::string aModName = "Modified";
198 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE,
199 aModTag, aModName, *theAlgo.mapOfShapes().get());
200 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, aDeleteTag);
202 for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
203 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE,
204 aModTag, aModName, *theAlgo.mapOfShapes().get());
205 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, aDeleteTag);