Salome HOME
Optimization of the widget code
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Pipe.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Pipe.cpp
4 // Created:     16 March 2016
5 // Author:      Dmitry Bobylev
6
7 #include "FeaturesPlugin_Pipe.h"
8
9 #include <ModelAPI_AttributeSelection.h>
10 #include <ModelAPI_AttributeSelectionList.h>
11 #include <ModelAPI_AttributeString.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_Pipe.h>
18 #include <GeomAlgoAPI_ShapeTools.h>
19 #include <GeomAPI_PlanarEdges.h>
20 #include <GeomAPI_ShapeExplorer.h>
21
22 #include <map>
23 #include <sstream>
24
25 //=================================================================================================
26 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
27 {
28 }
29
30 //=================================================================================================
31 void FeaturesPlugin_Pipe::initAttributes()
32 {
33   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
34
35   data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
36   data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
37
38   data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
39
40   data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
41   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
42 }
43
44 //=================================================================================================
45 void FeaturesPlugin_Pipe::execute()
46 {
47   // Getting creation method.
48   std::string aCreationMethod = string(CREATION_METHOD())->value();
49
50   // Getting base objects.
51   ListOfShape aBaseShapesList, aBaseFacesList;
52   std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
53   AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
54   if(!aBaseObjectsSelectionList.get()) {
55     setError("Error: Could not get base objects selection list.");
56     return;
57   }
58   if(aBaseObjectsSelectionList->size() == 0) {
59     setError("Error: Base objects list is empty.");
60     return;
61   }
62   for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
63     AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
64     if(!aBaseObjectSelection.get()) {
65       setError("Error: One of the selected base objects is empty.");
66       return;
67     }
68     std::shared_ptr<GeomAPI_Shape> aBaseShape = aBaseObjectSelection->value();
69     if(aBaseShape.get() && !aBaseShape->isNull()) {
70       GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
71       ResultConstructionPtr aConstruction =
72         std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
73       if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) && aST == GeomAPI_Shape::WIRE) {
74         // It is a wire on the sketch, store it to make face later.
75         aSketchWiresMap[aConstruction].push_back(aBaseShape);
76         continue;
77       } else {
78       aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
79                                    aBaseShapesList.push_back(aBaseShape);
80       }
81     } else {
82       // This may be the whole sketch result selected, check and get faces.
83       ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
84       if(!aConstruction.get()) {
85         setError("Error: One of selected sketches does not have results.");
86         return;
87       }
88       int aFacesNum = aConstruction->facesNum();
89       if(aFacesNum == 0) {
90         // Probably it can be construction.
91         aBaseShape = aConstruction->shape();
92         if(aBaseShape.get() && !aBaseShape->isNull()) {
93           aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
94                                                            aBaseShapesList.push_back(aBaseShape);
95         }
96       } else {
97         for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
98           std::shared_ptr<GeomAPI_Shape> aBaseFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
99           if(!aBaseFace.get() || aBaseFace->isNull()) {
100             setError("Error: One of the faces on selected sketch is Null.");
101             return;
102           }
103           aBaseFacesList.push_back(aBaseFace);
104         }
105       }
106     }
107   }
108
109   // Make faces from sketch wires.
110   for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
111       anIt != aSketchWiresMap.cend(); ++anIt) {
112     const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
113       std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
114     const ListOfShape& aWiresList = (*anIt).second;
115     ListOfShape aFaces;
116     GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
117                                                aSketchPlanarEdges->norm(),
118                                                aWiresList,
119                                                aFaces);
120     aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
121   }
122
123   // Searching faces with common edges.
124   if(aCreationMethod == "simple") {
125     ListOfShape aShells;
126     ListOfShape aFreeFaces;
127     std::shared_ptr<GeomAPI_Shape> aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
128     GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
129     aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
130     aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
131   } else {
132     aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
133   }
134
135   // Getting path.
136   AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
137   if(!aPathSelection.get()) {
138     setError("Error: Path selection is empty.");
139     return;
140   }
141   std::shared_ptr<GeomAPI_Shape> aPathShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
142   if(!aPathShape.get()) {
143     // Probaply it is a construction.
144     aPathShape = aPathSelection->context()->shape();
145   }
146   if(!aPathShape.get() || aPathShape->isNull()) {
147     setError("Error: Path shape is null.");
148     return;
149   }
150
151   // Getting Bi-Normal
152   std::shared_ptr<GeomAPI_Shape> aBiNormal;
153   if(aCreationMethod == "binormal") {
154     AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
155     if(!aBiNormalSelection.get()) {
156       setError("Error: Bi-Normal selection is empty.");
157       return;
158     }
159     aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
160     if(!aBiNormal.get()) {
161       // Probably it is a construction.
162       aBiNormal = aBiNormalSelection->context()->shape();
163     }
164     if(!aBiNormal.get() || aBiNormal->isNull()) {
165       setError("Error: Bi-Normal shape is null.");
166       return;
167     }
168   }
169
170   // Getting locations.
171   ListOfShape aLocations;
172   if(aCreationMethod == "locations") {
173     AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
174     if(!aLocationsSelectionList.get()) {
175       setError("Error: Could not get locations selection list.");
176       return;
177     }
178     for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
179       AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
180       if(!aLocationSelection.get()) {
181         setError("Error: One of the selected location is empty.");
182         return;
183       }
184       std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
185       if(!aLocationShape.get()) {
186         // Probably it is a construction.
187         aLocationShape = aLocationSelection->context()->shape();
188       }
189       if(!aLocationShape.get() || aLocationShape->isNull()) {
190         setError("Error: One of the selected location shape is null.");
191         return;
192       }
193       aLocations.push_back(aLocationShape);
194     }
195   }
196
197   // Generating result for each object.
198   int aResultIndex = 0;
199   if(aCreationMethod == "simple" || aCreationMethod == "binormal") {
200     for(ListOfShape::const_iterator anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
201       std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
202
203       GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod == "simple" ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
204                                                                  GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
205
206       if(!aPipeAlgo.isDone()) {
207         setError("Error: Pipe algorithm failed.");
208         aResultIndex = 0;
209         break;
210       }
211
212       // Check if shape is valid
213       if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
214         setError("Error: Resulting shape is Null.");
215         aResultIndex = 0;
216         break;
217       }
218       if(!aPipeAlgo.isValid()) {
219         setError("Error: Resulting shape is not valid.");
220         aResultIndex = 0;
221         break;
222       }
223
224       storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
225     }
226   } else if(aCreationMethod == "locations") {
227     GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
228
229     if(!aPipeAlgo.isDone()) {
230       setError("Error: Pipe algorithm failed.");
231       removeResults(0);
232       return;
233     }
234
235     // Check if shape is valid
236     if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
237       setError("Error: Resulting shape is Null.");
238       removeResults(0);
239       return;
240     }
241     if(!aPipeAlgo.isValid()) {
242       setError("Error: Resulting shape is not valid.");
243       removeResults(0);
244       return;
245     }
246
247     storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
248   } else {
249     setError("Error: Wrong creation method.");
250     return;
251   }
252
253   removeResults(aResultIndex);
254 }
255
256 //=================================================================================================
257 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
258                                       GeomAlgoAPI_Pipe& thePipeAlgo,
259                                       const int theResultIndex)
260 {
261   // Create result body.
262   ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
263
264   // Store generated shape.
265   aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
266
267   // Store generated edges/faces.
268   GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
269   GeomAPI_Shape::ShapeType aShapeTypeToExplode;
270   int aGenTag = 1;
271   std::string aGenName = "Generated_";
272
273   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
274   switch(aBaseShapeType) {
275     case GeomAPI_Shape::VERTEX: {
276       aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
277       aGenName += "Edge";
278       break;
279     }
280     case GeomAPI_Shape::EDGE:
281     case GeomAPI_Shape::WIRE: {
282       std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
283       GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
284       ListOfShape aV1History, aV2History;
285       thePipeAlgo.generated(aV1, aV1History);
286       thePipeAlgo.generated(aV2, aV2History);
287       if(!aV1History.empty()) {
288         aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
289       }
290       if(!aV2History.empty()) {
291         aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
292       }
293     }
294     case GeomAPI_Shape::FACE:
295     case GeomAPI_Shape::SHELL: {
296       aShapeTypeToExplode = GeomAPI_Shape::EDGE;
297       aGenName += "Face";
298       break;
299     }
300   }
301   aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
302
303   // Store from shapes.
304   int aFromTag = aGenTag;
305   storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.fromShapes(), "From_", aFromTag);
306
307   // Store to shapes.
308   int aToTag = aFromTag;
309   storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
310
311   setResult(aResultBody, theResultIndex);
312 }
313
314 //=================================================================================================
315 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
316                                       GeomAlgoAPI_Pipe& thePipeAlgo,
317                                       const int theResultIndex)
318 {
319   // Create result body.
320   ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
321
322   // Store generated shape.
323   aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
324
325   // Store generated edges/faces.
326   int aGenTag = 1;
327   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
328
329   for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
330     GeomShapePtr aBaseShape = *anIter;
331     GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
332     GeomAPI_Shape::ShapeType aShapeTypeToExplode;
333     std::string aGenName = "Generated_";
334     switch(aBaseShapeType) {
335       case GeomAPI_Shape::VERTEX: {
336         aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
337         aGenName += "Edge";
338         break;
339       }
340       case GeomAPI_Shape::EDGE:
341       case GeomAPI_Shape::WIRE: {
342         std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
343         GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
344         ListOfShape aV1History, aV2History;
345         thePipeAlgo.generated(aV1, aV1History);
346         thePipeAlgo.generated(aV2, aV2History);
347         aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
348         aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
349       }
350       case GeomAPI_Shape::FACE:
351       case GeomAPI_Shape::SHELL: {
352         aShapeTypeToExplode = GeomAPI_Shape::EDGE;
353         aGenName += "Face";
354         break;
355       }
356     }
357     aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
358   }
359
360   // Store from shapes.
361   int aFromTag = aGenTag;
362   storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes, thePipeAlgo.fromShapes(), "From", aFromTag);
363
364   // Store to shapes.
365   int aToTag = aFromTag;
366   storeShapes(aResultBody, theBaseShapes.back()->shapeType(), aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
367
368
369   setResult(aResultBody, theResultIndex);
370 }
371
372 //=================================================================================================
373 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
374                                       const GeomAPI_Shape::ShapeType theBaseShapeType,
375                                       const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
376                                       const ListOfShape& theShapes,
377                                       const std::string theName,
378                                       int& theTag)
379 {
380   GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
381   std::string aShapeTypeStr = "Face";
382   switch(theBaseShapeType) {
383     case GeomAPI_Shape::VERTEX: {
384       aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
385       aShapeTypeStr = "Vertex";
386       break;
387     }
388     case GeomAPI_Shape::EDGE:
389     case GeomAPI_Shape::WIRE: {
390       aShapeTypeToExplore = GeomAPI_Shape::EDGE;
391       aShapeTypeStr = "Edge";
392       break;
393     }
394     case GeomAPI_Shape::FACE:
395     case GeomAPI_Shape::SHELL: {
396       aShapeTypeToExplore = GeomAPI_Shape::FACE;
397       aShapeTypeStr = "Face";
398       break;
399     }
400   }
401
402   // Store shapes.
403   int aShapeIndex = 1;
404   std::string aName = theName + aShapeTypeStr;
405   for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
406     std::shared_ptr<GeomAPI_Shape> aShape = *anIt;
407     for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
408       std::shared_ptr<GeomAPI_Shape> aSubShape = anExp.current();
409       if(theMapOfSubShapes->isBound(aSubShape)) {
410         aSubShape = theMapOfSubShapes->find(aSubShape);
411       }
412       std::ostringstream aStr;
413       aStr << aName << "_" << aShapeIndex++;
414       theResultBody->generated(aSubShape, aStr.str(), theTag++);
415     }
416   }
417 }