]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_CompositeSketch.cpp
Salome HOME
[Code coverage]: Move checking the algorithm's result into separate function
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_CompositeSketch.cpp
1 // Copyright (C) 2014-2017  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License, or (at your option) any later version.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include <FeaturesPlugin_CompositeSketch.h>
22
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeReference.h>
25 #include <ModelAPI_BodyBuilder.h>
26 #include <ModelAPI_ResultConstruction.h>
27 #include <ModelAPI_Session.h>
28 #include <ModelAPI_Validator.h>
29
30 #include <GeomAlgoAPI_CompoundBuilder.h>
31 #include <GeomAlgoAPI_Prism.h>
32 #include <GeomAlgoAPI_Revolution.h>
33 #include <GeomAlgoAPI_ShapeTools.h>
34 #include <GeomAlgoAPI_SketchBuilder.h>
35
36 #include <GeomAPI_PlanarEdges.h>
37 #include <GeomAPI_ShapeExplorer.h>
38
39 #include <map>
40 #include <sstream>
41
42 static void storeSubShape(const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
43                           ResultBodyPtr theResultBody,
44                           const GeomShapePtr theShape,
45                           const GeomAPI_Shape::ShapeType theType,
46                           const std::string& theName);
47
48 //=================================================================================================
49 void FeaturesPlugin_CompositeSketch::initCompositeSketchAttribtues(const int theInitFlags)
50 {
51   // Initialize sketch launcher.
52   if(theInitFlags & InitSketchLauncher) {
53     data()->addAttribute(SKETCH_ID(), ModelAPI_AttributeReference::typeId());
54     ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), SKETCH_ID());
55   }
56
57   // Initialize selection list.
58   if(theInitFlags & InitBaseObjectsList) {
59     data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
60   }
61 }
62
63 //=================================================================================================
64 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::addFeature(std::string theID)
65 {
66   FeaturePtr aNew = document()->addFeature(theID, false);
67   if(aNew) {
68     data()->reference(SKETCH_ID())->setValue(aNew);
69   }
70
71   // Set as current also after it becomes sub to set correctly enabled for other sketch subs.
72   document()->setCurrentFeature(aNew, false);
73   return aNew;
74 }
75
76 //=================================================================================================
77 int FeaturesPlugin_CompositeSketch::numberOfSubs(bool forTree) const
78 {
79   ObjectPtr aObj = data()->reference(SKETCH_ID())->value();
80   return aObj.get() ? 1 : 0;
81 }
82
83 //=================================================================================================
84 std::shared_ptr<ModelAPI_Feature> FeaturesPlugin_CompositeSketch::subFeature(const int theIndex,
85                                                                              bool forTree)
86 {
87   FeaturePtr aSubFeature;
88   if(theIndex == 0) {
89     aSubFeature =
90         std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
91   }
92   return aSubFeature;
93 }
94
95 //=================================================================================================
96 int FeaturesPlugin_CompositeSketch::subFeatureId(const int theIndex) const
97 {
98   if(theIndex == 0) {
99     FeaturePtr aFeature =
100       std::dynamic_pointer_cast<ModelAPI_Feature>(data()->reference(SKETCH_ID())->value());
101     if(aFeature.get()) {
102       return aFeature->data()->featureId();
103     }
104   }
105
106   return -1;
107 }
108
109 //=================================================================================================
110 bool FeaturesPlugin_CompositeSketch::isSub(ObjectPtr theObject) const
111 {
112   bool isSubFeature = false;
113   // Check is this feature of result
114   FeaturePtr aFeature = std::dynamic_pointer_cast<ModelAPI_Feature>(theObject);
115   if (aFeature.get()) {
116     ObjectPtr aSub = data()->reference(SKETCH_ID())->value();
117     isSubFeature = aSub == theObject;
118   }
119   return isSubFeature;
120 }
121
122 //=================================================================================================
123 void FeaturesPlugin_CompositeSketch::removeFeature(std::shared_ptr<ModelAPI_Feature> theFeature)
124 {
125   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
126   if(aBaseObjectsSelectionList.get() && aBaseObjectsSelectionList->size() > 0) {
127     aBaseObjectsSelectionList->clear();
128   }
129
130   reference(SKETCH_ID())->setValue(ObjectPtr());
131 }
132
133 //=================================================================================================
134 void FeaturesPlugin_CompositeSketch::getBaseShapes(ListOfShape& theBaseShapesList,
135                                                    const bool theIsMakeShells)
136 {
137   theBaseShapesList.clear();
138
139   ListOfShape aBaseFacesList;
140   std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
141   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
142   if(!aBaseObjectsSelectionList.get()) {
143     setError("Error: Could not get base objects selection list.");
144     return;
145   }
146   if(aBaseObjectsSelectionList->size() == 0) {
147     setError("Error: Base objects list is empty.");
148     return;
149   }
150   for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
151     AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
152     if(!aBaseObjectSelection.get()) {
153       setError("Error: Selected base object is empty.");
154       return;
155     }
156     GeomShapePtr aBaseShape = aBaseObjectSelection->value();
157     if(aBaseShape.get() && !aBaseShape->isNull()) {
158       GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
159       if(aST == GeomAPI_Shape::SOLID || aST == GeomAPI_Shape::COMPSOLID) {
160         setError("Error: Selected shapes has unsupported type.");
161         return;
162       }
163       ResultConstructionPtr aConstruction =
164         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
165       if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
166           aST == GeomAPI_Shape::WIRE) {
167         // It is a wire on the sketch, store it to make face later.
168         aSketchWiresMap[aConstruction].push_back(aBaseShape);
169         continue;
170       } else {
171       aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
172                                    theBaseShapesList.push_back(aBaseShape);
173       }
174     } else {
175       // This may be the whole sketch result selected, check and get faces.
176       ResultConstructionPtr aConstruction =
177         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
178       if(!aConstruction.get()) {
179         setError("Error: Selected sketches does not have results.");
180         return;
181       }
182       int aFacesNum = aConstruction->facesNum();
183       if(aFacesNum == 0) {
184         // Probably it can be construction.
185         aBaseShape = aConstruction->shape();
186         if(aBaseShape.get() && !aBaseShape->isNull()) {
187           GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
188           if(aST != GeomAPI_Shape::VERTEX && aST != GeomAPI_Shape::EDGE &&
189              aST != GeomAPI_Shape::WIRE &&
190              aST != GeomAPI_Shape::FACE && aST != GeomAPI_Shape::SHELL) {
191             setError("Error: Selected shapes has unsupported type.");
192             return;
193           }
194           aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
195                                        theBaseShapesList.push_back(aBaseShape);
196         }
197       } else {
198         for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
199           GeomShapePtr aBaseFace = aConstruction->face(aFaceIndex);
200           if(!aBaseFace.get() || aBaseFace->isNull()) {
201             setError("Error: One of the faces on selected sketch is null.");
202             return;
203           }
204           aBaseFacesList.push_back(aBaseFace);
205         }
206       }
207     }
208   }
209
210   // Make faces from sketch wires.
211   for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
212       anIt != aSketchWiresMap.cend(); ++anIt) {
213     const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
214       std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
215     const ListOfShape& aWiresList = (*anIt).second;
216     ListOfShape aFaces;
217     GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
218                                                aSketchPlanarEdges->norm(),
219                                                aWiresList,
220                                                aFaces);
221     aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
222   }
223
224   // Searching faces with common edges.
225   if(theIsMakeShells && aBaseFacesList.size() > 1) {
226     ListOfShape aShells;
227     ListOfShape aFreeFaces;
228     GeomShapePtr aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
229     GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
230                                           aShells, aFreeFaces);
231     theBaseShapesList.insert(theBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
232     theBaseShapesList.insert(theBaseShapesList.end(), aShells.begin(), aShells.end());
233   } else {
234     theBaseShapesList.insert(theBaseShapesList.end(), aBaseFacesList.begin(),
235                              aBaseFacesList.end());
236   }
237 }
238
239 //=================================================================================================
240 void FeaturesPlugin_CompositeSketch::storeResult(const GeomShapePtr theBaseShape,
241                                         const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
242                                         const int theIndex)
243 {
244   // Create result body.
245   ResultBodyPtr aResultBody = document()->createBody(data(), theIndex);
246
247   // Store generated shape.
248   aResultBody->storeGenerated(theBaseShape, theMakeShape->shape());
249
250   // Store generated edges/faces.
251   storeGenerationHistory(aResultBody, theBaseShape, theMakeShape);
252
253   setResult(aResultBody, theIndex);
254 }
255
256 //=================================================================================================
257 void FeaturesPlugin_CompositeSketch::storeGenerationHistory(ResultBodyPtr theResultBody,
258                                         const GeomShapePtr theBaseShape,
259                                         const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape)
260 {
261   GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
262   GeomAPI_Shape::ShapeType aShapeTypeToExplode = GeomAPI_Shape::SHAPE;
263
264   switch(aBaseShapeType) {
265     case GeomAPI_Shape::EDGE: {
266             aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
267       break;
268     }
269     case GeomAPI_Shape::WIRE: {
270       aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
271       break;
272     }
273     case GeomAPI_Shape::FACE:
274     case GeomAPI_Shape::SHELL: {
275       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
276       break;
277     }
278     case GeomAPI_Shape::COMPOUND: {
279       aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
280     }
281   }
282
283   int aLateralIndex = 1;
284   int aBaseEdgeIndex = 1;
285   int aVertexIndex = 1;
286   int aBaseVertexIndex = 1;
287
288   if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
289       aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
290     theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::VERTEX);
291   }
292   if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
293       aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
294     theResultBody->loadGeneratedShapes(theMakeShape, theBaseShape, GeomAPI_Shape::EDGE);
295   }
296   std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> > aSweeps; // all sweeps collected
297   std::shared_ptr<GeomAlgoAPI_MakeSweep> aMakeSweep =
298     std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(theMakeShape);
299   if(aMakeSweep.get()) {
300     aSweeps.push_back(aMakeSweep);
301   } else {
302     std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeList =
303       std::dynamic_pointer_cast<GeomAlgoAPI_MakeShapeList>(theMakeShape);
304     if (aMakeList.get()) {
305       ListOfMakeShape::const_iterator anIter = aMakeList->list().cbegin();
306       for(; anIter != aMakeList->list().cend(); anIter++) {
307         std::shared_ptr<GeomAlgoAPI_MakeSweep> aSweep =
308           std::dynamic_pointer_cast<GeomAlgoAPI_MakeSweep>(*anIter);
309         if (aSweep.get())
310           aSweeps.push_back(aSweep);
311       }
312     }
313   }
314   std::list<std::shared_ptr<GeomAlgoAPI_MakeSweep> >::iterator aSweep = aSweeps.begin();
315   for(; aSweep != aSweeps.end(); aSweep++) {
316     // Store from shapes.
317     storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->fromShapes(), "From_");
318
319     // Store to shapes.
320     storeShapes(theMakeShape, theResultBody, aBaseShapeType, (*aSweep)->toShapes(), "To_");
321   }
322 }
323
324 //=================================================================================================
325 void FeaturesPlugin_CompositeSketch::storeShapes(
326   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
327   ResultBodyPtr theResultBody,
328   const GeomAPI_Shape::ShapeType theBaseShapeType,
329   const ListOfShape& theShapes,
330   const std::string theName)
331 {
332   GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
333   std::string aShapeTypeStr = "Face";
334   switch(theBaseShapeType) {
335     case GeomAPI_Shape::VERTEX: {
336       aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
337       aShapeTypeStr = "Vertex";
338       break;
339     }
340     case GeomAPI_Shape::EDGE:
341     case GeomAPI_Shape::WIRE: {
342       aShapeTypeToExplore = GeomAPI_Shape::EDGE;
343       aShapeTypeStr = "Edge";
344       break;
345     }
346     case GeomAPI_Shape::FACE:
347     case GeomAPI_Shape::SHELL: {
348       aShapeTypeToExplore = GeomAPI_Shape::FACE;
349       aShapeTypeStr = "Face";
350       break;
351     }
352     case GeomAPI_Shape::COMPOUND: {
353       aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
354       break;
355     }
356   }
357
358   // Store shapes.
359   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
360     GeomShapePtr aShape = *anIt;
361
362     if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
363       std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
364       storeSubShape(theMakeShape, theResultBody, aShape, aShape->shapeType(), aName);
365     } else {
366       std::string aName = theName + aShapeTypeStr;
367       storeSubShape(theMakeShape, theResultBody, aShape, aShapeTypeToExplore, aName);
368       if (theBaseShapeType == GeomAPI_Shape::WIRE) { // issue 2289: special names also for vertices
369         aName = theName + "Vertex";
370         storeSubShape(theMakeShape, theResultBody, aShape, GeomAPI_Shape::VERTEX, aName);
371       }
372     }
373   }
374 }
375
376 void storeSubShape(
377   const std::shared_ptr<GeomAlgoAPI_MakeShape> theMakeShape,
378   ResultBodyPtr theResultBody,
379   const GeomShapePtr theShape,
380   const GeomAPI_Shape::ShapeType theType,
381   const std::string& theName)
382 {
383   for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
384     GeomShapePtr aSubShape = anExp.current();
385     if (!theResultBody->generated(aSubShape, theName)) {
386       // store from/to shapes as primitives and then store modification of them by the boolean
387       theResultBody->generated(aSubShape, theName, false);
388       theResultBody->loadModifiedShapes(theMakeShape, aSubShape, theType);
389     }
390   }
391 }