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