1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: FeaturesPlugin_Boolean.cpp
4 // Created: 02 Sept 2014
5 // Author: Vitaly SMETANNIKOV
7 #include "FeaturesPlugin_Boolean.h"
9 #include <ModelAPI_Data.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_AttributeReference.h>
12 #include <ModelAPI_AttributeInteger.h>
13 #include <ModelAPI_ResultBody.h>
14 #include <ModelAPI_AttributeSelectionList.h>
15 #include <ModelAPI_Session.h>
16 #include <ModelAPI_Validator.h>
18 #include <GeomAlgoAPI_Boolean.h>
19 #include <GeomAlgoAPI_MakeShapeList.h>
20 #include <GeomAlgoAPI_ShapeProps.h>
24 #define _DELETED_TAG 2
25 #define _SUBSOLIDS_TAG 3 /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
27 //=================================================================================================
28 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean()
32 //=================================================================================================
33 void FeaturesPlugin_Boolean::initAttributes()
35 data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
37 AttributeSelectionListPtr aSelection =
38 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
39 FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
40 // extrusion works with faces always
41 aSelection->setSelectionType("SOLID");
43 aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
44 FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
45 // extrusion works with faces always
46 aSelection->setSelectionType("SOLID");
48 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
49 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
52 //=================================================================================================
53 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
55 std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
56 ModelAPI_AttributeReference>(data()->attribute(theAttrName));
58 std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
59 ModelAPI_ResultBody>(aObjRef->value());
61 return aConstr->shape();
63 return std::shared_ptr<GeomAPI_Shape>();
66 //=================================================================================================
67 void FeaturesPlugin_Boolean::execute()
69 // Getting operation type.
70 std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
71 ModelAPI_AttributeInteger>(data()->attribute(FeaturesPlugin_Boolean::TYPE_ID()));
74 GeomAlgoAPI_Boolean::OperationType aType = (GeomAlgoAPI_Boolean::OperationType)aTypeAttr->value();
76 ListOfShape anObjects, aTools;
79 AttributeSelectionListPtr anObjectsSelList = selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
80 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
81 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
82 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
86 anObjects.push_back(anObject);
90 AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
91 for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
92 std::shared_ptr<ModelAPI_AttributeSelection> aToolAttr = aToolsSelList->value(aToolsIndex);
93 std::shared_ptr<GeomAPI_Shape> aTool = aToolAttr->value();
97 aTools.push_back(aTool);
100 int aResultIndex = 0;
103 case GeomAlgoAPI_Boolean::BOOL_CUT:
104 case GeomAlgoAPI_Boolean::BOOL_COMMON:{
105 if(anObjects.empty() || aTools.empty()) {
106 std::string aFeatureError = "Not enough objects for boolean operation";
107 setError(aFeatureError);
111 // Cut each object with all tools
112 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
113 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
114 ListOfShape aListWithObject;
115 aListWithObject.push_back(anObject);
116 GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, aType);
118 // Checking that the algorithm worked properly.
119 if(!aBoolAlgo.isDone()) {
120 static const std::string aFeatureError = "Boolean algorithm failed";
121 setError(aFeatureError);
124 if(aBoolAlgo.shape()->isNull()) {
125 static const std::string aShapeError = "Resulting shape is Null";
126 setError(aShapeError);
129 if(!aBoolAlgo.isValid()) {
130 std::string aFeatureError = "Warning: resulting shape is not valid";
131 setError(aFeatureError);
135 if(GeomAlgoAPI_ShapeProps::volume(aBoolAlgo.shape()) > 1.e-7) {
136 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
137 LoadNamingDS(aResultBody, anObject, aTools, aBoolAlgo);
138 setResult(aResultBody, aResultIndex);
144 case GeomAlgoAPI_Boolean::BOOL_FUSE: {
145 if(anObjects.empty() && aTools.size() > 1) {
146 anObjects.push_back(aTools.back());
148 }else if(aTools.empty() && anObjects.size() > 1) {
149 aTools.push_back(anObjects.back());
150 anObjects.pop_back();
153 if(anObjects.empty() || aTools.empty()) {
154 std::string aFeatureError = "Not enough objects for boolean operation";
155 setError(aFeatureError);
159 // Fuse all objects and all tools.
160 GeomAlgoAPI_Boolean aBoolAlgo(anObjects, aTools, aType);
162 // Checking that the algorithm worked properly.
163 if(!aBoolAlgo.isDone()) {
164 static const std::string aFeatureError = "Boolean algorithm failed";
165 setError(aFeatureError);
168 if(aBoolAlgo.shape()->isNull()) {
169 static const std::string aShapeError = "Resulting shape is Null";
170 setError(aShapeError);
173 if(!aBoolAlgo.isValid()) {
174 std::string aFeatureError = "Warning: resulting shape is not valid";
175 setError(aFeatureError);
179 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
180 LoadNamingDS(aResultBody, anObjects.front(), aTools, aBoolAlgo);
181 setResult(aResultBody, aResultIndex);
186 std::string anOperationError = "Error: wrong type of operation";
187 setError(anOperationError);
191 // remove the rest results if there were produced in the previous pass
192 removeResults(aResultIndex);
195 //=================================================================================================
196 void FeaturesPlugin_Boolean::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 theResultBody->storeModified(theBaseShape, theAlgo.shape(), _SUBSOLIDS_TAG);
207 GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
209 std::string aModName = "Modified";
210 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, FACE,
211 _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
212 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, FACE, _DELETED_TAG);
214 for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
215 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, FACE,
216 _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
217 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, FACE, _DELETED_TAG);