1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
3 // File: FeaturesPlugin_Pipe.cpp
4 // Created: 16 March 2016
5 // Author: Dmitry Bobylev
7 #include "FeaturesPlugin_Pipe.h"
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>
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>
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,
33 //==================================================================================================
34 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
38 //==================================================================================================
39 void FeaturesPlugin_Pipe::initAttributes()
41 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
43 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
44 data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
46 data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
48 data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
49 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
52 //==================================================================================================
53 void FeaturesPlugin_Pipe::execute()
55 // Getting creation method.
56 std::string aCreationMethod = string(CREATION_METHOD())->value();
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.");
66 if(aBaseObjectsSelectionList->size() == 0) {
67 setError("Error: Base objects list is empty.");
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.");
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()) &&
82 aST == GeomAPI_Shape::WIRE) {
83 // It is a wire on the sketch, store it to make face later.
84 aSketchWiresMap[aConstruction].push_back(aBaseShape);
87 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
88 aBaseShapesList.push_back(aBaseShape);
91 // This may be the whole sketch result selected, check and get faces.
92 ResultConstructionPtr aConstruction =
93 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
94 if(!aConstruction.get()) {
95 setError("Error: One of selected sketches does not have results.");
98 int aFacesNum = aConstruction->facesNum();
100 // Probably it can be construction.
101 aBaseShape = aConstruction->shape();
102 if(aBaseShape.get() && !aBaseShape->isNull()) {
103 aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
104 aBaseShapesList.push_back(aBaseShape);
107 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
108 std::shared_ptr<GeomAPI_Shape> aBaseFace =
109 std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
110 if(!aBaseFace.get() || aBaseFace->isNull()) {
111 setError("Error: One of the faces on selected sketch is Null.");
114 aBaseFacesList.push_back(aBaseFace);
120 // Make faces from sketch wires.
121 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
122 anIt != aSketchWiresMap.cend(); ++anIt) {
123 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
124 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
125 const ListOfShape& aWiresList = (*anIt).second;
127 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
128 aSketchPlanarEdges->norm(),
131 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
134 // Searching faces with common edges.
135 if(aCreationMethod == CREATION_METHOD_SIMPLE()) {
137 ListOfShape aFreeFaces;
138 std::shared_ptr<GeomAPI_Shape> aFacesCompound =
139 GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
140 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
141 aShells, aFreeFaces);
142 aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
143 aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
145 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
149 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
150 if(!aPathSelection.get()) {
151 setError("Error: Path selection is empty.");
154 std::shared_ptr<GeomAPI_Shape> aPathShape =
155 std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
156 if(!aPathShape.get()) {
157 // Probaply it is a construction.
158 aPathShape = aPathSelection->context()->shape();
160 if(!aPathShape.get() || aPathShape->isNull()) {
161 setError("Error: Path shape is null.");
166 std::shared_ptr<GeomAPI_Shape> aBiNormal;
167 if(aCreationMethod == CREATION_METHOD_BINORMAL()) {
168 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
169 if(!aBiNormalSelection.get()) {
170 setError("Error: Bi-Normal selection is empty.");
173 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
174 if(!aBiNormal.get()) {
175 // Probably it is a construction.
176 aBiNormal = aBiNormalSelection->context()->shape();
178 if(!aBiNormal.get() || aBiNormal->isNull()) {
179 setError("Error: Bi-Normal shape is null.");
184 // Getting locations.
185 ListOfShape aLocations;
186 if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
187 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
188 if(!aLocationsSelectionList.get()) {
189 setError("Error: Could not get locations selection list.");
192 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
193 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
194 if(!aLocationSelection.get()) {
195 setError("Error: One of the selected location is empty.");
198 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
199 if(!aLocationShape.get()) {
200 // Probably it is a construction.
201 aLocationShape = aLocationSelection->context()->shape();
203 if(!aLocationShape.get() || aLocationShape->isNull()) {
204 setError("Error: One of the selected location shape is null.");
207 aLocations.push_back(aLocationShape);
211 // Generating result for each object.
212 int aResultIndex = 0;
213 if(aCreationMethod == CREATION_METHOD_SIMPLE() ||
214 aCreationMethod == CREATION_METHOD_BINORMAL()) {
215 for(ListOfShape::const_iterator
216 anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
217 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
219 GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod ==
220 CREATION_METHOD_SIMPLE() ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
221 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
223 if(!aPipeAlgo.isDone()) {
224 setError("Error: Pipe algorithm failed.");
229 // Check if shape is valid
230 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
231 setError("Error: Resulting shape is Null.");
235 if(!aPipeAlgo.isValid()) {
236 setError("Error: Resulting shape is not valid.");
241 storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
243 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
244 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
246 if(!aPipeAlgo.isDone()) {
247 setError("Error: Pipe algorithm failed.");
252 // Check if shape is valid
253 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
254 setError("Error: Resulting shape is Null.");
258 if(!aPipeAlgo.isValid()) {
259 setError("Error: Resulting shape is not valid.");
264 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
266 setError("Error: Wrong creation method.");
270 removeResults(aResultIndex);
273 //==================================================================================================
274 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
275 GeomAlgoAPI_Pipe& thePipeAlgo,
276 const int theResultIndex)
278 // Create result body.
279 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
281 // Store generated shape.
282 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
284 // Store generated edges/faces.
285 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
286 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
288 std::string aGenName = "Generated_";
290 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
291 switch(aBaseShapeType) {
292 case GeomAPI_Shape::VERTEX: {
293 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
296 case GeomAPI_Shape::EDGE:
297 case GeomAPI_Shape::WIRE: {
298 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
299 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
300 ListOfShape aV1History, aV2History;
301 thePipeAlgo.generated(aV1, aV1History);
302 thePipeAlgo.generated(aV2, aV2History);
303 if(!aV1History.empty()) {
304 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
306 if(!aV2History.empty()) {
307 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
310 case GeomAPI_Shape::FACE:
311 case GeomAPI_Shape::SHELL: {
312 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
315 case GeomAPI_Shape::COMPOUND: {
316 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
320 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
321 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
322 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
323 aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
325 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
326 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
327 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
328 aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
331 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode,
332 aGenTag++, aGenName, *aMapOfSubShapes.get());
334 // Store from shapes.
335 int aFromTag = aGenTag;
336 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes,
337 thePipeAlgo.fromShapes(), "From_", aFromTag);
340 int aToTag = aFromTag;
341 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
343 setResult(aResultBody, theResultIndex);
346 //==================================================================================================
347 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
348 GeomAlgoAPI_Pipe& thePipeAlgo,
349 const int theResultIndex)
351 // Create result body.
352 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
354 // Store generated shape.
355 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
357 // Store generated edges/faces.
359 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
361 for(ListOfShape::const_iterator
362 anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
363 GeomShapePtr aBaseShape = *anIter;
364 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
365 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
366 std::string aGenName = "Generated_";
367 switch(aBaseShapeType) {
368 case GeomAPI_Shape::VERTEX: {
369 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
373 case GeomAPI_Shape::EDGE:
374 case GeomAPI_Shape::WIRE: {
375 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
376 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
377 ListOfShape aV1History, aV2History;
378 thePipeAlgo.generated(aV1, aV1History);
379 thePipeAlgo.generated(aV2, aV2History);
380 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
381 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
383 case GeomAPI_Shape::FACE:
384 case GeomAPI_Shape::SHELL: {
385 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
390 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode,
391 aGenTag++, aGenName, *aMapOfSubShapes.get());
394 // Store from shapes.
395 int aFromTag = aGenTag;
396 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes,
397 thePipeAlgo.fromShapes(), "From", aFromTag);
400 int aToTag = aFromTag;
401 storeShapes(aResultBody, theBaseShapes.back()->shapeType(),
402 aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
405 setResult(aResultBody, theResultIndex);
408 //==================================================================================================
409 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
410 const GeomAPI_Shape::ShapeType theBaseShapeType,
411 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
412 const ListOfShape& theShapes,
413 const std::string theName,
416 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
417 std::string aShapeTypeStr = "Face";
418 switch(theBaseShapeType) {
419 case GeomAPI_Shape::VERTEX: {
420 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
421 aShapeTypeStr = "Vertex";
424 case GeomAPI_Shape::EDGE:
425 case GeomAPI_Shape::WIRE: {
426 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
427 aShapeTypeStr = "Edge";
430 case GeomAPI_Shape::FACE:
431 case GeomAPI_Shape::SHELL: {
432 aShapeTypeToExplore = GeomAPI_Shape::FACE;
433 aShapeTypeStr = "Face";
436 case GeomAPI_Shape::COMPOUND: {
437 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
445 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
446 GeomShapePtr aShape = *anIt;
448 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
449 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
450 storeSubShape(theResultBody,
455 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
458 std::string aName = theName + aShapeTypeStr;
459 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
460 theMapOfSubShapes, aName, aShapeIndex, theTag);
465 //==================================================================================================
466 void storeSubShape(ResultBodyPtr theResultBody,
467 const GeomShapePtr theShape,
468 const GeomAPI_Shape::ShapeType theType,
469 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
470 const std::string theName,
474 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
475 GeomShapePtr aSubShape = anExp.current();
476 if(theMapOfSubShapes->isBound(aSubShape)) {
477 aSubShape = theMapOfSubShapes->find(aSubShape);
479 std::ostringstream aStr;
480 aStr << theName << "_" << theShapeIndex++;
481 theResultBody->generated(aSubShape, aStr.str(), theTag++);