Salome HOME
Bug #740 - name of group entity is wrong
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_CompositeBoolean.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        FeaturesPlugin_CompositeBoolean.cpp
4 // Created:     11 June 2015
5 // Author:      Dmitry Bobylev
6
7 #include <FeaturesPlugin_CompositeBoolean.h>
8
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_ResultBody.h>
12 #include <ModelAPI_ResultConstruction.h>
13
14 #include <GeomAlgoAPI_Prism.h>
15 #include <GeomAlgoAPI_Revolution.h>
16 #include <GeomAlgoAPI_ShapeProps.h>
17
18 //=================================================================================================
19 void FeaturesPlugin_CompositeBoolean::initAttributes()
20 {
21   data()->addAttribute(SKETCH_OBJECT_ID(), ModelAPI_AttributeReference::typeId());
22
23   // Boolean works with solids always.
24   data()->addAttribute(BOOLEAN_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
25   AttributeSelectionListPtr aSelection = data()->selectionList(BOOLEAN_OBJECTS_ID());
26   aSelection->setSelectionType("SOLID");
27
28   initMakeSolidsAttributes();
29 }
30
31 //=================================================================================================
32 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeBoolean::addFeature(std::string theID)
33 {
34   std::shared_ptr<ModelAPI_Feature> aNew = document()->addFeature(theID, false);
35   if (aNew) {
36     data()->reference(SKETCH_OBJECT_ID())->setValue(aNew);
37   }
38    // set as current also after it becomes sub to set correctly enabled for other sketch subs
39   document()->setCurrentFeature(aNew, false);
40   return aNew;
41 }
42
43 //=================================================================================================
44 int FeaturesPlugin_CompositeBoolean::numberOfSubs(bool forTree) const
45 {
46   ObjectPtr aObj = data()->reference(SKETCH_OBJECT_ID())->value();
47   return aObj.get()? 1 : 0;
48 }
49
50 //=================================================================================================
51 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeBoolean::subFeature(const int theIndex, bool forTree) const
52 {
53   if (theIndex == 0)
54     return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_OBJECT_ID())->value());
55   return std::shared_ptr<ModelAPI_Feature>();
56 }
57
58 //=================================================================================================
59 int FeaturesPlugin_CompositeBoolean::subFeatureId(const int theIndex) const
60 {
61   std::shared_ptr<ModelAPI_Feature> aFeature = subFeature(theIndex);
62   if (aFeature.get())
63     return aFeature->data()->featureId();
64   return -1;
65 }
66
67 //=================================================================================================
68 bool FeaturesPlugin_CompositeBoolean::isSub(ObjectPtr theObject) const
69 {
70   // check is this feature of result
71   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
72   if (!aFeature)
73     return false;
74  
75   ObjectPtr aSub = data()->reference(SKETCH_OBJECT_ID())->value();
76   return aSub == theObject;
77 }
78
79 //=================================================================================================
80 void FeaturesPlugin_CompositeBoolean::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
81 {
82 }
83
84 //=================================================================================================
85 void FeaturesPlugin_CompositeBoolean::erase()
86 {
87   if (data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
88     FeaturePtr aSketch =
89       std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_OBJECT_ID())->value());
90     if (aSketch.get() && aSketch->data()->isValid()) {
91       document()->removeFeature(aSketch);
92     }
93   }
94   ModelAPI_CompositeFeature::erase();
95 }
96
97
98 //=================================================================================================
99 void FeaturesPlugin_CompositeBoolean::execute()
100 {
101   // Getting faces to create solids.
102   std::shared_ptr<ModelAPI_Feature> aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(
103                                                      reference(SKETCH_OBJECT_ID())->value());
104   if(!aSketchFeature) {
105     return;
106   }
107   ResultPtr aSketchRes = aSketchFeature->results().front();
108   ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
109   if(!aConstruction.get()) {
110     return;
111   }
112   int aSketchFacesNum = aConstruction->facesNum();
113   if(aSketchFacesNum == 0) {
114     return; //TODO: set error message
115   }
116   ListOfShape aSketchFacesList;
117   for(int aFaceIndex = 0; aFaceIndex < aSketchFacesNum; aFaceIndex++) {
118     std::shared_ptr<GeomAPI_Shape> aFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
119     aSketchFacesList.push_back(aFace);
120   }
121
122   // Pass faces to soldis creation function.
123   ListOfShape aBooleanTools;
124   std::list<std::shared_ptr<GeomAPI_Interface>> theSolidsAlgos;
125   makeSolids(aSketchFacesList, aBooleanTools, theSolidsAlgos);
126   if(aBooleanTools.empty()) {
127     return;
128   }
129
130   // Getting objects for boolean operation.
131   ListOfShape aBooleanObjects;
132   AttributeSelectionListPtr anObjectsSelList = selectionList(BOOLEAN_OBJECTS_ID());
133   if (anObjectsSelList->size() == 0) {
134     return;
135   }
136   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
137     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr = anObjectsSelList->value(anObjectsIndex);
138     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
139     if(!anObject.get()) {
140       return;
141     }
142     aBooleanObjects.push_back(anObject);
143   }
144
145   // Cut from each object solids.
146   int aResultIndex = 0;
147
148   switch(myBooleanOperationType) {
149     case GeomAlgoAPI_Boolean::BOOL_CUT:
150     case GeomAlgoAPI_Boolean::BOOL_COMMON:{
151       // Cut each object with all tools
152       for(ListOfShape::iterator anObjectsIt = aBooleanObjects.begin(); anObjectsIt != aBooleanObjects.end(); anObjectsIt++) {
153         std::shared_ptr<GeomAPI_Shape> anObject = *anObjectsIt;
154         ListOfShape aListWithObject;
155         aListWithObject.push_back(anObject);
156         GeomAlgoAPI_Boolean aBoolAlgo(aListWithObject, aBooleanTools, myBooleanOperationType);
157
158         // Checking that the algorithm worked properly.
159         if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
160           setError("Boolean algorithm failed");
161           return;
162         }
163
164         if(GeomAlgoAPI_ShapeProps::volume(aBoolAlgo.shape()) > 1.e-7) {
165           std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
166           loadNamingDS(aResultBody, anObject, aSketchFacesList, theSolidsAlgos, aBooleanTools, aBoolAlgo);
167           setResult(aResultBody, aResultIndex);
168           aResultIndex++;
169         }
170       }
171       break;
172     }
173     case GeomAlgoAPI_Boolean::BOOL_FUSE: {
174       // Fuse all objects and all tools.
175       GeomAlgoAPI_Boolean aBoolAlgo(aBooleanObjects, aBooleanTools, myBooleanOperationType);
176
177       // Checking that the algorithm worked properly.
178       if(!aBoolAlgo.isDone() || aBoolAlgo.shape()->isNull() || !aBoolAlgo.isValid()) {
179         setError("Boolean algorithm failed");
180         return;
181       }
182
183       std::shared_ptr<ModelAPI_ResultBody> aResultBody = document()->createBody(data(), aResultIndex);
184       loadNamingDS(aResultBody, aBooleanObjects.front(), aSketchFacesList, theSolidsAlgos, aBooleanTools, aBoolAlgo);
185       setResult(aResultBody, aResultIndex);
186       aResultIndex++;
187       break;
188     }
189     default: {
190       setError("Error: wrong type of boolean operation");
191       return;
192     }
193   }
194
195   // Remove the rest results if there were produced in the previous pass.
196   removeResults(aResultIndex);
197 }
198
199 //=================================================================================================
200 void FeaturesPlugin_CompositeBoolean::loadNamingDS(std::shared_ptr<ModelAPI_ResultBody> theResultBody,
201                                                    const std::shared_ptr<GeomAPI_Shape>& theBaseShape,
202                                                    const ListOfShape& theFaces,
203                                                    const std::list<std::shared_ptr<GeomAPI_Interface>>& theSolidsAlgos,
204                                                    const ListOfShape& theTools,
205                                                    const GeomAlgoAPI_Boolean& theAlgo)
206 {
207   //load result
208   if(theBaseShape->isEqual(theAlgo.shape())) {
209     theResultBody->store(theAlgo.shape());
210   } else {
211     const int aGenTag = 1;
212     const int aFrTag = 2;
213     const int aToTag = 3;
214     const int aModTag = 4;
215     const int aDelTag = 5;
216     const int aSubsolidsTag=6; /// sub solids will be placed at labels 6, 7, etc. if result is compound of solids
217     const std::string aGenName = "Generated";
218     const std::string aModName = "Modified";
219     const std::string aLatName = "LateralFace";
220     const std::string aFrName = "FromFace";
221     const std::string aToName = "ToFace";
222
223     theResultBody->storeModified(theBaseShape, theAlgo.shape(), aSubsolidsTag);
224
225     ListOfShape::const_iterator aFaceIter = theFaces.begin();
226     std::list<std::shared_ptr<GeomAPI_Interface>>::const_iterator aSolidsAlgosIter = theSolidsAlgos.begin();
227     for(; aFaceIter != theFaces.end() && aSolidsAlgosIter != theSolidsAlgos.end(); aFaceIter++, aSolidsAlgosIter++) {
228       std::shared_ptr<GeomAPI_Shape> aFromFace;
229       std::shared_ptr<GeomAPI_Shape> aToFace;
230       std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes;
231
232       //Insert lateral face : Face from Edge
233       if(std::dynamic_pointer_cast<GeomAlgoAPI_Prism>(*aSolidsAlgosIter)) {
234         std::shared_ptr<GeomAlgoAPI_Prism> aPrismAlgo = std::dynamic_pointer_cast<GeomAlgoAPI_Prism>(*aSolidsAlgosIter);
235         aSubShapes = aPrismAlgo->mapOfShapes();
236         theResultBody->loadAndOrientGeneratedShapes(aPrismAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag,
237                                                     aLatName, *aSubShapes.get());
238         aFromFace = aPrismAlgo->firstShape();
239         aToFace = aPrismAlgo->lastShape();
240       } else if(std::dynamic_pointer_cast<GeomAlgoAPI_Revolution>(*aSolidsAlgosIter)) {
241         std::shared_ptr<GeomAlgoAPI_Revolution> aRevolAlgo = std::dynamic_pointer_cast<GeomAlgoAPI_Revolution>(*aSolidsAlgosIter);
242         aSubShapes = aRevolAlgo->mapOfShapes();
243         theResultBody->loadAndOrientGeneratedShapes(aRevolAlgo->makeShape().get(), *aFaceIter, GeomAPI_Shape::EDGE, aGenTag,
244                                                     aLatName, *aSubShapes.get());
245         aFromFace = aRevolAlgo->firstShape();
246         aToFace = aRevolAlgo->lastShape();
247       }
248
249       //Insert bottom face
250       if(!aFromFace->isNull()) {
251         if(aSubShapes->isBound(aFromFace)) {
252           aFromFace = aSubShapes->find(aFromFace);
253         }
254         theResultBody->generated(aFromFace, aFrName, aFrTag);
255       }
256
257       //Insert top face
258       if (!aToFace->isNull()) {
259         if (aSubShapes->isBound(aToFace)) {
260           aToFace = aSubShapes->find(aToFace);
261         }
262         theResultBody->generated(aToFace, aToName, aToTag);
263       }
264     }
265
266     theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE,
267                                                aModTag, aModName, *theAlgo.mapOfShapes().get());
268     theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), theBaseShape, GeomAPI_Shape::FACE, aDelTag);
269
270     for(ListOfShape::const_iterator anIter = theTools.begin(); anIter != theTools.end(); anIter++) {
271       theResultBody->loadAndOrientModifiedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE,
272                                                  aModTag, aModName, *theAlgo.mapOfShapes().get());
273       theResultBody->loadDeletedShapes(theAlgo.makeShape().get(), *anIter, GeomAPI_Shape::FACE, aDelTag);
274     }
275   }
276 }