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