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_BodyBuilder.h>
14 #include <ModelAPI_ResultBody.h>
15 #include <ModelAPI_AttributeSelectionList.h>
16 #include <ModelAPI_Session.h>
17 #include <ModelAPI_Validator.h>
19 #include <GeomAlgoAPI_Boolean.h>
20 #include <GeomAlgoAPI_MakeShapeList.h>
21 #include <GeomAlgoAPI_ShapeTools.h>
25 #define _DELETED_TAG 2
26 #define _SUBSOLIDS_TAG 3 /// sub solids will be placed at labels 3, 4, etc. if result is compound of solids
28 //=================================================================================================
29 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean()
33 //=================================================================================================
34 void FeaturesPlugin_Boolean::initAttributes()
36 data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
38 AttributeSelectionListPtr aSelection =
39 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
40 FeaturesPlugin_Boolean::OBJECT_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
41 // extrusion works with faces always
42 aSelection->setSelectionType("SOLID");
44 aSelection = std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
45 FeaturesPlugin_Boolean::TOOL_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
46 // extrusion works with faces always
47 aSelection->setSelectionType("SOLID");
49 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
50 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
53 //=================================================================================================
54 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
56 std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
57 ModelAPI_AttributeReference>(data()->attribute(theAttrName));
59 std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
60 ModelAPI_ResultBody>(aObjRef->value());
62 return aConstr->shape();
64 return std::shared_ptr<GeomAPI_Shape>();
67 //=================================================================================================
68 void FeaturesPlugin_Boolean::execute()
70 // Getting operation type.
71 std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
72 ModelAPI_AttributeInteger>(data()->attribute(FeaturesPlugin_Boolean::TYPE_ID()));
75 GeomAlgoAPI_Boolean::OperationType aType = (GeomAlgoAPI_Boolean::OperationType)aTypeAttr->value();
77 ListOfShape anObjects, aTools;
80 AttributeSelectionListPtr anObjectsSelList = selectionList(FeaturesPlugin_Boolean::OBJECT_LIST_ID());
81 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
82 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
83 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
87 anObjects.push_back(anObject);
91 AttributeSelectionListPtr aToolsSelList = selectionList(FeaturesPlugin_Boolean::TOOL_LIST_ID());
92 for(int aToolsIndex = 0; aToolsIndex < aToolsSelList->size(); aToolsIndex++) {
93 std::shared_ptr<ModelAPI_AttributeSelection> aToolAttr = aToolsSelList->value(aToolsIndex);
94 std::shared_ptr<GeomAPI_Shape> aTool = aToolAttr->value();
98 aTools.push_back(aTool);
101 int aResultIndex = 0;
104 case GeomAlgoAPI_Boolean::BOOL_CUT:
105 case GeomAlgoAPI_Boolean::BOOL_COMMON:{
106 if(anObjects.empty() || aTools.empty()) {
107 std::string aFeatureError = "Not enough objects for boolean operation";
108 setError(aFeatureError);
112 // Cut each object with all tools
113 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end(); anObjectsIt++) {
114 std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
115 ListOfShape aListWithObject;
116 aListWithObject.push_back(anObject);
117 GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aTools, aType);
119 // Checking that the algorithm worked properly.
120 if(!aBoolAlgo.isDone()) {
121 static const std::string aFeatureError = "Boolean algorithm failed";
122 setError(aFeatureError);
125 if(aBoolAlgo.shape()->isNull()) {
126 static const std::string aShapeError = "Resulting shape is Null";
127 setError(aShapeError);
130 if(!aBoolAlgo.isValid()) {
131 std::string aFeatureError = "Warning: resulting shape is not valid";
132 setError(aFeatureError);
136 if(GeomAlgoAPI_ShapeTools::volume(aBoolAlgo.shape()) > 1.e-7) {
137 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
138 LoadNamingDS(aResultBody, anObject, aTools, aBoolAlgo);
139 setResult(aResultBody, aResultIndex);
145 case GeomAlgoAPI_Boolean::BOOL_FUSE: {
146 if(anObjects.empty() && aTools.size() > 1) {
147 anObjects.push_back(aTools.back());
149 }else if(aTools.empty() && anObjects.size() > 1) {
150 aTools.push_back(anObjects.back());
151 anObjects.pop_back();
154 if(anObjects.empty() || aTools.empty()) {
155 std::string aFeatureError = "Not enough objects for boolean operation";
156 setError(aFeatureError);
160 // Fuse all objects and all tools.
161 GeomAlgoAPI_Boolean aBoolAlgo(anObjects, aTools, aType);
163 // Checking that the algorithm worked properly.
164 if(!aBoolAlgo.isDone()) {
165 static const std::string aFeatureError = "Boolean algorithm failed";
166 setError(aFeatureError);
169 if(aBoolAlgo.shape()->isNull()) {
170 static const std::string aShapeError = "Resulting shape is Null";
171 setError(aShapeError);
174 if(!aBoolAlgo.isValid()) {
175 std::string aFeatureError = "Warning: resulting shape is not valid";
176 setError(aFeatureError);
180 std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
181 LoadNamingDS(aResultBody, anObjects.front(), aTools, aBoolAlgo);
182 setResult(aResultBody, aResultIndex);
187 std::string anOperationError = "Error: wrong type of operation";
188 setError(anOperationError);
192 // remove the rest results if there were produced in the previous pass
193 removeResults(aResultIndex);
196 //=================================================================================================
197 void FeaturesPlugin_Boolean::LoadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
198 const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
199 const ListOfShape& theTools,
200 const GeomAlgoAPI_Boolean& theAlgo)
203 if(theBaseShape->isEqual(theAlgo.shape())) {
204 theResultBody->store(theAlgo.shape());
206 theResultBody->storeModified(theBaseShape, theAlgo.shape(), _SUBSOLIDS_TAG);
208 GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
210 std::string aModName = "Modified";
211 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, FACE,
212 _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
213 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, FACE, _DELETED_TAG);
215 for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
216 theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, FACE,
217 _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
218 theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, FACE, _DELETED_TAG);