Salome HOME
0b5a103ceb74a3e604583f174019fa0a9243e37e
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_CompositeSketch.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:        FeaturesPlugin_CompositeSketch.cpp
4 // Created:     11 September 2015
5 // Author:      Dmitry Bobylev
6
7 #include <FeaturesPlugin_CompositeSketch.h>
8
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_AttributeReference.h>
11 #include <ModelAPI_BodyBuilder.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_Session.h>
14 #include <ModelAPI_Validator.h>
15
16 #include <GeomAlgoAPI_CompoundBuilder.h>
17 #include <GeomAlgoAPI_Prism.h>
18 #include <GeomAlgoAPI_Revolution.h>
19 #include <GeomAlgoAPI_ShapeTools.h>
20 #include <GeomAPI_ShapeExplorer.h>
21
22 #include <sstream>
23
24 //=================================================================================================
25 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
26 {
27   // Initialize sketch launcher.
28   if(theInitFlags & InitSketchLauncher) {
29     data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
30     ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
31   }
32
33   // Initialize selection list.
34   if(theInitFlags & InitBaseObjectsList) {
35     data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
36   }
37 }
38
39 //=================================================================================================
40 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
41 {
42   FeaturePtr aNew = document()->addFeature(theID, false);
43   if(aNew) {
44     data()->reference(SKETCH_ID())->setValue(aNew);
45   }
46
47   // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
48   document()->setCurrentFeature(aNew, false);
49   return aNew;
50 }
51
52 //=================================================================================================
53 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
54 {
55   ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
56   return aObj.get() ? 1 : 0;
57 }
58
59 //=================================================================================================
60 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex, bool forTree)
61 {
62   if(theIndex == 0) {
63     return std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
64   }
65
66   return std::shared_ptr<ModelAPI_Feature>();
67 }
68
69 //=================================================================================================
70 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
71 {
72   if(theIndex == 0) {
73     FeaturePtr aFeature =
74       std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
75     if(aFeature.get()) {
76       return aFeature->data()->featureId();
77     }
78   }
79
80   return -1;
81 }
82
83 //=================================================================================================
84 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
85 {
86   // Check is this feature of result
87   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
88   if(!aFeature.get()) {
89     return false;
90   }
91
92   ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
93   return aSub == theObject;
94 }
95
96 //=================================================================================================
97 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
98 {
99   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
100   if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
101     aBaseObjectsSelectionList->clear();
102   }
103
104   reference(SKETCH_ID())->setValue(ObjectPtr());
105 }
106
107 //=================================================================================================
108 void FeaturesPlugin_CompositeSketch::erase()
109 {
110   if(data().get() && data()->isValid()) { // on abort of sketch of this composite it may be invalid
111     FeaturePtr aSketch = std::dynamic_pointer_cast<ModelAPI_Feature>(reference(SKETCH_ID())->value());
112     if(aSketch.get() && aSketch->data()->isValid()) {
113       document()->removeFeature(aSketch);
114     }
115   }
116
117   ModelAPI_CompositeFeature::erase();
118 }
119
120 //=================================================================================================
121 void FeaturesPlugin_CompositeSketch::setSketchObjectToList()
122 {
123   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
124   if(!aBaseObjectsSelectionList.get() || aBaseObjectsSelectionList->isInitialized()) {
125     return;
126   }
127
128   AttributeReferencePtr aSketchLauncherRef = reference(SKETCH_ID());
129   if(!aSketchLauncherRef.get() || !aSketchLauncherRef->isInitialized()) {
130     return;
131   }
132
133   FeaturePtr aSketchFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(aSketchLauncherRef->value());
134
135   if(!aSketchFeature.get() || aSketchFeature->results().empty()) {
136     return;
137   }
138
139   ResultPtr aSketchRes = aSketchFeature->results().front();
140   ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aSketchRes);
141   if(!aConstruction.get()) {
142     return;
143   }
144
145   if(aBaseObjectsSelectionList->size() == 0) {
146     aBaseObjectsSelectionList->append(aSketchRes, GeomShapePtr());
147   }
148 }
149
150 //=================================================================================================
151 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
152                                                    const bool theIsMakeShells)
153 {
154   theBaseShapesList.clear();
155
156   ListOfShape aBaseFacesList;
157   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
158   if(!aBaseObjectsSelectionList.get()) {
159     setError("Error: Could not get base objects selection list.");
160     return;
161   }
162   if(aBaseObjectsSelectionList->size() == 0) {
163     setError("Error: Base objects list is empty.");
164     return;
165   }
166   for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
167     AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
168     if(!aBaseObjectSelection.get()) {
169       setError("Error: One of the selected base objects is empty.");
170       return;
171     }
172     GeomShapePtr aBaseShape = aBaseObjectSelection->value();
173     if(aBaseShape.get() && !aBaseShape->isNull()) {
174       aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
175                                                        theBaseShapesList.push_back(aBaseShape);
176     } else {
177       // This may be the whole sketch result selected, check and get faces.
178       ResultConstructionPtr aConstruction =
179         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
180       if(!aConstruction.get()) {
181         setError("Error: One of selected sketches does not have results.");
182         return;
183       }
184       int aFacesNum = aConstruction->facesNum();
185       if(aFacesNum == 0) {
186         // Probably it can be construction.
187         aBaseShape = aConstruction->shape();
188         if(aBaseShape.get() && !aBaseShape->isNull()) {
189           aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
190                                                            theBaseShapesList.push_back(aBaseShape);
191         }
192       } else {
193         for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
194           GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
195           if(!aBaseFace.get() || aBaseFace->isNull()) {
196             setError("Error: One of the faces on selected sketch is Null.");
197             return;
198           }
199           aBaseFacesList.push_back(aBaseFace);
200         }
201       }
202     }
203   }
204
205   // Searching faces with common edges.
206   if(theIsMakeShells) {
207     ListOfShape aShells;
208     ListOfShape aFreeFaces;
209     GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
210     GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
211     theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
212     theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
213   } else {
214     theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
215   }
216 }
217
218 //=================================================================================================
219 bool FeaturesPlugin_CompositeSketch::isMakeShapeValid(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
220 {
221   // Check that algo is done.
222   if(!theMakeShape->isDone()) {
223     setError("Error:" + getKind() + "algorithm failed.");
224     return false;
225   }
226
227   // Check if shape is not null.
228   if(!theMakeShape->shape().get() || theMakeShape->shape()->isNull()) {
229     setError("Error: Resulting shape is null.");
230     return false;
231   }
232
233   // Check that resulting shape is valid.
234   if(!theMakeShape->isValid()) {
235     setError("Error: Resulting shape is not valid.");
236     return false;
237   }
238
239   return true;
240 }
241
242 //=================================================================================================
243 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
244                                                  const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
245                                                  const int theResultIndex)
246 {
247   // Create result body.
248   ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
249
250   // Store generated shape.
251   aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
252
253   // Store generated edges/faces.
254   int aGenTag = 1;
255   storeGenerationHistory(aResultBody, theBaseShape, theMakeShape, aGenTag);
256
257   setResult(aResultBody, theResultIndex);
258 }
259
260 //=================================================================================================
261 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
262                                                             const GeomShapePtr theBaseShape,
263                                                             const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
264                                                             int& theTag)
265 {
266   GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
267   GeomAPI_Shape::ShapeType aShapeTypeToExplode;
268   std::string aGenName = "Generated_";
269
270   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = theMakeShape->mapOfSubShapes();
271   switch(aBaseShapeType) {
272     case GeomAPI_Shape::VERTEX: {
273       aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
274       aGenName += "Edge";
275       break;
276     }
277     case GeomAPI_Shape::EDGE:
278     case GeomAPI_Shape::WIRE: {
279       std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
280       GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
281       ListOfShape aV1History, aV2History;
282       theMakeShape->generated(aV1, aV1History);
283       theMakeShape->generated(aV2, aV2History);
284       theResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", theTag++);
285       theResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", theTag++);
286     }
287     case GeomAPI_Shape::FACE:
288     case GeomAPI_Shape::SHELL: {
289       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
290       aGenName += "Face";
291       break;
292     }
293   }
294   theResultBody->loadAndOrientGeneratedShapes(theMakeShape.get(), theBaseShape, aShapeTypeToExplode,
295                                               theTag++, aGenName, *aMapOfSubShapes.get());
296
297   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep = std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
298   if(aMakeSweep.get()) {
299     // Store from shapes.
300     storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->fromShapes(), "From_", theTag);
301
302     // Store to shapes.
303     storeShapes(theResultBody, aBaseShapeType, aMapOfSubShapes, aMakeSweep->toShapes(), "To_", theTag);
304   }
305 }
306
307 //=================================================================================================
308 void FeaturesPlugin_CompositeSketch::storeShapes(ResultBodyPtr theResultBody,
309                                                  const GeomAPI_Shape::ShapeType theBaseShapeType,
310                                                  const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
311                                                  const ListOfShape& theShapes,
312                                                  const std::string theName,
313                                                  int& theTag)
314 {
315   GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
316   std::string aShapeTypeStr = "Face";
317   switch(theBaseShapeType) {
318     case GeomAPI_Shape::VERTEX: {
319       aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
320       aShapeTypeStr = "Vertex";
321       break;
322     }
323     case GeomAPI_Shape::EDGE:
324     case GeomAPI_Shape::WIRE: {
325       aShapeTypeToExplore = GeomAPI_Shape::EDGE;
326       aShapeTypeStr = "Edge";
327       break;
328     }
329     case GeomAPI_Shape::FACE:
330     case GeomAPI_Shape::SHELL: {
331       aShapeTypeToExplore = GeomAPI_Shape::FACE;
332       aShapeTypeStr = "Face";
333       break;
334     }
335   }
336
337   // Store shapes.
338   int aShapeIndex = 1;
339   std::string aName = theName + aShapeTypeStr;
340   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
341     GeomShapePtr aShape = *anIt;
342     for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
343       GeomShapePtr aSubShape = anExp.current();
344       if(theMapOfSubShapes->isBound(aSubShape)) {
345         aSubShape = theMapOfSubShapes->find(aSubShape);
346       }
347       std::ostringstream aStr;
348       aStr << aName << "_" << aShapeIndex++;
349       theResultBody->generated(aSubShape, aStr.str(), theTag++);
350     }
351   }
352 }