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 == CREATION_METHOD_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 == CREATION_METHOD_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 == CREATION_METHOD_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 == CREATION_METHOD_SIMPLE() || aCreationMethod == CREATION_METHOD_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 ==
212 CREATION_METHOD_SIMPLE() ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
213 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
215 if(!aPipeAlgo.isDone()) {
216 setError("Error: Pipe algorithm failed.");
221 // Check if shape is valid
222 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
223 setError("Error: Resulting shape is Null.");
227 if(!aPipeAlgo.isValid()) {
228 setError("Error: Resulting shape is not valid.");
233 storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
235 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
236 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
238 if(!aPipeAlgo.isDone()) {
239 setError("Error: Pipe algorithm failed.");
244 // Check if shape is valid
245 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
246 setError("Error: Resulting shape is Null.");
250 if(!aPipeAlgo.isValid()) {
251 setError("Error: Resulting shape is not valid.");
256 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
258 setError("Error: Wrong creation method.");
262 removeResults(aResultIndex);
265 //==================================================================================================
266 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
267 GeomAlgoAPI_Pipe& thePipeAlgo,
268 const int theResultIndex)
270 // Create result body.
271 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
273 // Store generated shape.
274 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
276 // Store generated edges/faces.
277 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
278 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
280 std::string aGenName = "Generated_";
282 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
283 switch(aBaseShapeType) {
284 case GeomAPI_Shape::VERTEX: {
285 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
288 case GeomAPI_Shape::EDGE:
289 case GeomAPI_Shape::WIRE: {
290 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
291 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
292 ListOfShape aV1History, aV2History;
293 thePipeAlgo.generated(aV1, aV1History);
294 thePipeAlgo.generated(aV2, aV2History);
295 if(!aV1History.empty()) {
296 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
298 if(!aV2History.empty()) {
299 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
302 case GeomAPI_Shape::FACE:
303 case GeomAPI_Shape::SHELL: {
304 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
307 case GeomAPI_Shape::COMPOUND: {
308 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
312 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
313 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
314 aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
316 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE || aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
317 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
318 aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
321 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
323 // Store from shapes.
324 int aFromTag = aGenTag;
325 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.fromShapes(), "From_", aFromTag);
328 int aToTag = aFromTag;
329 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
331 setResult(aResultBody, theResultIndex);
334 //==================================================================================================
335 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
336 GeomAlgoAPI_Pipe& thePipeAlgo,
337 const int theResultIndex)
339 // Create result body.
340 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
342 // Store generated shape.
343 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
345 // Store generated edges/faces.
347 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
349 for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
350 GeomShapePtr aBaseShape = *anIter;
351 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
352 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
353 std::string aGenName = "Generated_";
354 switch(aBaseShapeType) {
355 case GeomAPI_Shape::VERTEX: {
356 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
360 case GeomAPI_Shape::EDGE:
361 case GeomAPI_Shape::WIRE: {
362 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
363 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
364 ListOfShape aV1History, aV2History;
365 thePipeAlgo.generated(aV1, aV1History);
366 thePipeAlgo.generated(aV2, aV2History);
367 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
368 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
370 case GeomAPI_Shape::FACE:
371 case GeomAPI_Shape::SHELL: {
372 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
377 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
380 // Store from shapes.
381 int aFromTag = aGenTag;
382 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes, thePipeAlgo.fromShapes(), "From", aFromTag);
385 int aToTag = aFromTag;
386 storeShapes(aResultBody, theBaseShapes.back()->shapeType(), aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
389 setResult(aResultBody, theResultIndex);
392 //==================================================================================================
393 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
394 const GeomAPI_Shape::ShapeType theBaseShapeType,
395 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
396 const ListOfShape& theShapes,
397 const std::string theName,
400 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
401 std::string aShapeTypeStr = "Face";
402 switch(theBaseShapeType) {
403 case GeomAPI_Shape::VERTEX: {
404 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
405 aShapeTypeStr = "Vertex";
408 case GeomAPI_Shape::EDGE:
409 case GeomAPI_Shape::WIRE: {
410 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
411 aShapeTypeStr = "Edge";
414 case GeomAPI_Shape::FACE:
415 case GeomAPI_Shape::SHELL: {
416 aShapeTypeToExplore = GeomAPI_Shape::FACE;
417 aShapeTypeStr = "Face";
420 case GeomAPI_Shape::COMPOUND: {
421 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
429 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
430 GeomShapePtr aShape = *anIt;
432 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
433 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
434 storeSubShape(theResultBody,
439 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
442 std::string aName = theName + aShapeTypeStr;
443 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
444 theMapOfSubShapes, aName, aShapeIndex, theTag);
449 //==================================================================================================
450 void storeSubShape(ResultBodyPtr theResultBody,
451 const GeomShapePtr theShape,
452 const GeomAPI_Shape::ShapeType theType,
453 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
454 const std::string theName,
458 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
459 GeomShapePtr aSubShape = anExp.current();
460 if(theMapOfSubShapes->isBound(aSubShape)) {
461 aSubShape = theMapOfSubShapes->find(aSubShape);
463 std::ostringstream aStr;
464 aStr << theName << "_" << theShapeIndex++;
465 theResultBody->generated(aSubShape, aStr.str(), theTag++);