Salome HOME
Result CompSolid should inherits ResultBody. All model realization concerned Naming...
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Boolean.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Boolean.cpp
4 // Created:     02 Sept 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "FeaturesPlugin_Boolean.h"
8
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>
18
19 #include <GeomAlgoAPI_Boolean.h>
20 #include <GeomAlgoAPI_MakeShapeList.h>
21 #include <GeomAlgoAPI_ShapeProps.h>
22
23 #define FACE 4
24 #define _MODIFY_TAG 1
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
27
28 //=================================================================================================
29 FeaturesPlugin_Boolean::FeaturesPlugin_Boolean()
30 {
31 }
32
33 //=================================================================================================
34 void FeaturesPlugin_Boolean::initAttributes()
35 {
36   data()->addAttribute(FeaturesPlugin_Boolean::TYPE_ID(), ModelAPI_AttributeInteger::typeId());
37
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");
43
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");
48
49   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), OBJECT_LIST_ID());
50   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TOOL_LIST_ID());
51 }
52
53 //=================================================================================================
54 std::shared_ptr<GeomAPI_Shape> FeaturesPlugin_Boolean::getShape(const std::string& theAttrName)
55 {
56   std::shared_ptr<ModelAPI_AttributeReference> aObjRef = std::dynamic_pointer_cast<
57       ModelAPI_AttributeReference>(data()->attribute(theAttrName));
58   if (aObjRef) {
59     std::shared_ptr<ModelAPI_ResultBody> aConstr = std::dynamic_pointer_cast<
60         ModelAPI_ResultBody>(aObjRef->value());
61     if (aConstr)
62       return aConstr->shape();
63   }
64   return std::shared_ptr<GeomAPI_Shape>();
65 }
66
67 //=================================================================================================
68 void FeaturesPlugin_Boolean::execute()
69 {
70   // Getting operation type.
71   std::shared_ptr<ModelAPI_AttributeInteger> aTypeAttr = std::dynamic_pointer_cast<
72       ModelAPI_AttributeInteger>(data()->attribute(FeaturesPlugin_Boolean::TYPE_ID()));
73   if (!aTypeAttr)
74     return;
75   GeomAlgoAPI_Boolean::OperationType aType = (GeomAlgoAPI_Boolean::OperationType)aTypeAttr->value();
76
77   ListOfShape anObjects, aTools;
78
79   // Getting objects.
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();
84     if(!anObject.get()) {
85       return;
86     }
87     anObjects.push_back(anObject);
88   }
89
90   // Getting tools.
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();
95     if(!aTool.get()) {
96       return;
97     }
98     aTools.push_back(aTool);
99   }
100
101   int aResultIndex = 0;
102
103   switch(aType) {
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);
109         return;
110       }
111
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);
118
119         // Checking that the algorithm worked properly.
120         if(!aBoolAlgo.isDone()) {
121           static const std::string aFeatureError = "Boolean algorithm failed";
122           setError(aFeatureError);
123           return;
124         }
125         if(aBoolAlgo.shape()->isNull()) {
126           static const std::string aShapeError = "Resulting shape is Null";
127           setError(aShapeError);
128           return;
129         }
130         if(!aBoolAlgo.isValid()) {
131           std::string aFeatureError = "Warning: resulting shape is not valid";
132           setError(aFeatureError);
133           return;
134         }
135
136         if(GeomAlgoAPI_ShapeProps::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);
140           aResultIndex++;
141         }
142       }
143       break;
144     }
145     case GeomAlgoAPI_Boolean::BOOL_FUSE: {
146       if(anObjects.empty() && aTools.size() > 1) {
147         anObjects.push_back(aTools.back());
148         aTools.pop_back();
149       }else if(aTools.empty() && anObjects.size() > 1) {
150         aTools.push_back(anObjects.back());
151         anObjects.pop_back();
152       }
153
154       if(anObjects.empty() || aTools.empty()) {
155         std::string aFeatureError = "Not enough objects for boolean operation";
156         setError(aFeatureError);
157         return;
158       }
159
160       // Fuse all objects and all tools.
161       GeomAlgoAPI_Boolean aBoolAlgo(anObjects, aTools, aType);
162
163       // Checking that the algorithm worked properly.
164       if(!aBoolAlgo.isDone()) {
165         static const std::string aFeatureError = "Boolean algorithm failed";
166         setError(aFeatureError);
167         return;
168       }
169       if(aBoolAlgo.shape()->isNull()) {
170         static const std::string aShapeError = "Resulting shape is Null";
171         setError(aShapeError);
172         return;
173       }
174       if(!aBoolAlgo.isValid()) {
175         std::string aFeatureError = "Warning: resulting shape is not valid";
176         setError(aFeatureError);
177         return;
178       }
179
180       std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
181       LoadNamingDS(aResultBody, anObjects.front(), aTools, aBoolAlgo);
182       setResult(aResultBody, aResultIndex);
183       aResultIndex++;
184       break;
185     }
186     default: {
187       std::string anOperationError = "Error: wrong type of operation";
188       setError(anOperationError);
189       return;
190     }
191   }
192   // remove the rest results if there were produced in the previous pass
193   removeResults(aResultIndex);
194 }
195
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)
201 {
202   ModelAPI_BodyBuilder* aResultBuilder = theResultBody->getBodyBuilder();
203   //load result
204   if(theBaseShape->isEqual(theAlgo.shape())) {
205     aResultBuilder->store(theAlgo.shape());
206   } else {
207     aResultBuilder->storeModified(theBaseShape, theAlgo.shape(), _SUBSOLIDS_TAG);
208
209     GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
210
211     std::string aModName = "Modified";
212     aResultBuilder->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, FACE,
213                                                _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
214     aResultBuilder->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, FACE, _DELETED_TAG);
215
216     for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
217       aResultBuilder->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, FACE,
218                                                  _MODIFY_TAG, aModName, *theAlgo.mapOfShapes().get());
219       aResultBuilder->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, FACE, _DELETED_TAG);
220     }
221   }
222 }