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()) && aST == GeomAPI_Shape::WIRE) {
82 // It is a wire on the sketch, store it to make face later.
83 aSketchWiresMap[aConstruction].push_back(aBaseShape);
86 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
87 aBaseShapesList.push_back(aBaseShape);
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.");
96 int aFacesNum = aConstruction->facesNum();
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);
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.");
111 aBaseFacesList.push_back(aBaseFace);
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;
124 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
125 aSketchPlanarEdges->norm(),
128 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
131 // Searching faces with common edges.
132 if(aCreationMethod == "simple") {
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());
140 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
144 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
145 if(!aPathSelection.get()) {
146 setError("Error: Path selection is empty.");
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();
154 if(!aPathShape.get() || aPathShape->isNull()) {
155 setError("Error: Path shape is null.");
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.");
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();
172 if(!aBiNormal.get() || aBiNormal->isNull()) {
173 setError("Error: Bi-Normal shape is null.");
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.");
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.");
192 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
193 if(!aLocationShape.get()) {
194 // Probably it is a construction.
195 aLocationShape = aLocationSelection->context()->shape();
197 if(!aLocationShape.get() || aLocationShape->isNull()) {
198 setError("Error: One of the selected location shape is null.");
201 aLocations.push_back(aLocationShape);
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;
211 GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod == "simple" ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
212 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
214 if(!aPipeAlgo.isDone()) {
215 setError("Error: Pipe algorithm failed.");
220 // Check if shape is valid
221 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
222 setError("Error: Resulting shape is Null.");
226 if(!aPipeAlgo.isValid()) {
227 setError("Error: Resulting shape is not valid.");
232 storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
234 } else if(aCreationMethod == "locations") {
235 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
237 if(!aPipeAlgo.isDone()) {
238 setError("Error: Pipe algorithm failed.");
243 // Check if shape is valid
244 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
245 setError("Error: Resulting shape is Null.");
249 if(!aPipeAlgo.isValid()) {
250 setError("Error: Resulting shape is not valid.");
255 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
257 setError("Error: Wrong creation method.");
261 removeResults(aResultIndex);
264 //==================================================================================================
265 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
266 GeomAlgoAPI_Pipe& thePipeAlgo,
267 const int theResultIndex)
269 // Create result body.
270 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
272 // Store generated shape.
273 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
275 // Store generated edges/faces.
276 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
277 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
279 std::string aGenName = "Generated_";
281 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
282 switch(aBaseShapeType) {
283 case GeomAPI_Shape::VERTEX: {
284 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
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++);
297 if(!aV2History.empty()) {
298 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
301 case GeomAPI_Shape::FACE:
302 case GeomAPI_Shape::SHELL: {
303 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
306 case GeomAPI_Shape::COMPOUND: {
307 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
311 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
312 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
313 aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
315 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
316 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
317 aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
320 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
322 // Store from shapes.
323 int aFromTag = aGenTag;
324 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.fromShapes(), "From_", aFromTag);
327 int aToTag = aFromTag;
328 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
330 setResult(aResultBody, theResultIndex);
333 //==================================================================================================
334 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
335 GeomAlgoAPI_Pipe& thePipeAlgo,
336 const int theResultIndex)
338 // Create result body.
339 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
341 // Store generated shape.
342 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
344 // Store generated edges/faces.
346 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
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;
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++);
369 case GeomAPI_Shape::FACE:
370 case GeomAPI_Shape::SHELL: {
371 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
376 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
379 // Store from shapes.
380 int aFromTag = aGenTag;
381 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes, thePipeAlgo.fromShapes(), "From", aFromTag);
384 int aToTag = aFromTag;
385 storeShapes(aResultBody, theBaseShapes.back()->shapeType(), aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
388 setResult(aResultBody, theResultIndex);
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,
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";
407 case GeomAPI_Shape::EDGE:
408 case GeomAPI_Shape::WIRE: {
409 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
410 aShapeTypeStr = "Edge";
413 case GeomAPI_Shape::FACE:
414 case GeomAPI_Shape::SHELL: {
415 aShapeTypeToExplore = GeomAPI_Shape::FACE;
416 aShapeTypeStr = "Face";
419 case GeomAPI_Shape::COMPOUND: {
420 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
428 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
429 GeomShapePtr aShape = *anIt;
431 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
432 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
433 storeSubShape(theResultBody,
438 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
441 std::string aName = theName + aShapeTypeStr;
442 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
443 theMapOfSubShapes, aName, aShapeIndex, theTag);
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,
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);
462 std::ostringstream aStr;
463 aStr << theName << "_" << theShapeIndex++;
464 theResultBody->generated(aSubShape, aStr.str(), theTag++);