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 //=================================================================================================
26 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
30 //=================================================================================================
31 void FeaturesPlugin_Pipe::initAttributes()
33 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
35 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
36 data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
38 data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
40 data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
41 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
44 //=================================================================================================
45 void FeaturesPlugin_Pipe::execute()
47 // Getting creation method.
48 std::string aCreationMethod = string(CREATION_METHOD())->value();
50 // Getting base objects.
51 ListOfShape aBaseShapesList, aBaseFacesList;
52 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
53 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
54 if(!aBaseObjectsSelectionList.get()) {
55 setError("Error: Could not get base objects selection list.");
58 if(aBaseObjectsSelectionList->size() == 0) {
59 setError("Error: Base objects list is empty.");
62 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
63 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
64 if(!aBaseObjectSelection.get()) {
65 setError("Error: One of the selected base objects is empty.");
68 std::shared_ptr<GeomAPI_Shape> aBaseShape = aBaseObjectSelection->value();
69 if(aBaseShape.get() && !aBaseShape->isNull()) {
70 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
71 ResultConstructionPtr aConstruction =
72 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
73 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) && aST == GeomAPI_Shape::WIRE) {
74 // It is a wire on the sketch, store it to make face later.
75 aSketchWiresMap[aConstruction].push_back(aBaseShape);
78 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
79 aBaseShapesList.push_back(aBaseShape);
82 // This may be the whole sketch result selected, check and get faces.
83 ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
84 if(!aConstruction.get()) {
85 setError("Error: One of selected sketches does not have results.");
88 int aFacesNum = aConstruction->facesNum();
90 // Probably it can be construction.
91 aBaseShape = aConstruction->shape();
92 if(aBaseShape.get() && !aBaseShape->isNull()) {
93 aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
94 aBaseShapesList.push_back(aBaseShape);
97 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
98 std::shared_ptr<GeomAPI_Shape> aBaseFace = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
99 if(!aBaseFace.get() || aBaseFace->isNull()) {
100 setError("Error: One of the faces on selected sketch is Null.");
103 aBaseFacesList.push_back(aBaseFace);
109 // Make faces from sketch wires.
110 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
111 anIt != aSketchWiresMap.cend(); ++anIt) {
112 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
113 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
114 const ListOfShape& aWiresList = (*anIt).second;
116 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
117 aSketchPlanarEdges->norm(),
120 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
123 // Searching faces with common edges.
124 if(aCreationMethod == "simple") {
126 ListOfShape aFreeFaces;
127 std::shared_ptr<GeomAPI_Shape> aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
128 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
129 aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
130 aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
132 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
136 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
137 if(!aPathSelection.get()) {
138 setError("Error: Path selection is empty.");
141 std::shared_ptr<GeomAPI_Shape> aPathShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
142 if(!aPathShape.get()) {
143 // Probaply it is a construction.
144 aPathShape = aPathSelection->context()->shape();
146 if(!aPathShape.get() || aPathShape->isNull()) {
147 setError("Error: Path shape is null.");
152 std::shared_ptr<GeomAPI_Shape> aBiNormal;
153 if(aCreationMethod == "binormal") {
154 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
155 if(!aBiNormalSelection.get()) {
156 setError("Error: Bi-Normal selection is empty.");
159 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
160 if(!aBiNormal.get()) {
161 // Probably it is a construction.
162 aBiNormal = aBiNormalSelection->context()->shape();
164 if(!aBiNormal.get() || aBiNormal->isNull()) {
165 setError("Error: Bi-Normal shape is null.");
170 // Getting locations.
171 ListOfShape aLocations;
172 if(aCreationMethod == "locations") {
173 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
174 if(!aLocationsSelectionList.get()) {
175 setError("Error: Could not get locations selection list.");
178 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
179 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
180 if(!aLocationSelection.get()) {
181 setError("Error: One of the selected location is empty.");
184 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
185 if(!aLocationShape.get()) {
186 // Probably it is a construction.
187 aLocationShape = aLocationSelection->context()->shape();
189 if(!aLocationShape.get() || aLocationShape->isNull()) {
190 setError("Error: One of the selected location shape is null.");
193 aLocations.push_back(aLocationShape);
197 // Generating result for each object.
198 int aResultIndex = 0;
199 if(aCreationMethod == "simple" || aCreationMethod == "binormal") {
200 for(ListOfShape::const_iterator anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
201 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
203 GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod == "simple" ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
204 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
206 if(!aPipeAlgo.isDone()) {
207 setError("Error: Pipe algorithm failed.");
212 // Check if shape is valid
213 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
214 setError("Error: Resulting shape is Null.");
218 if(!aPipeAlgo.isValid()) {
219 setError("Error: Resulting shape is not valid.");
224 storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
226 } else if(aCreationMethod == "locations") {
227 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
229 if(!aPipeAlgo.isDone()) {
230 setError("Error: Pipe algorithm failed.");
235 // Check if shape is valid
236 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
237 setError("Error: Resulting shape is Null.");
241 if(!aPipeAlgo.isValid()) {
242 setError("Error: Resulting shape is not valid.");
247 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
249 setError("Error: Wrong creation method.");
253 removeResults(aResultIndex);
256 //=================================================================================================
257 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
258 GeomAlgoAPI_Pipe& thePipeAlgo,
259 const int theResultIndex)
261 // Create result body.
262 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
264 // Store generated shape.
265 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
267 // Store generated edges/faces.
268 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
269 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
271 std::string aGenName = "Generated_";
273 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
274 switch(aBaseShapeType) {
275 case GeomAPI_Shape::VERTEX: {
276 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
280 case GeomAPI_Shape::EDGE:
281 case GeomAPI_Shape::WIRE: {
282 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
283 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
284 ListOfShape aV1History, aV2History;
285 thePipeAlgo.generated(aV1, aV1History);
286 thePipeAlgo.generated(aV2, aV2History);
287 if(!aV1History.empty()) {
288 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
290 if(!aV2History.empty()) {
291 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
294 case GeomAPI_Shape::FACE:
295 case GeomAPI_Shape::SHELL: {
296 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
301 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
303 // Store from shapes.
304 int aFromTag = aGenTag;
305 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.fromShapes(), "From_", aFromTag);
308 int aToTag = aFromTag;
309 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
311 setResult(aResultBody, theResultIndex);
314 //=================================================================================================
315 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
316 GeomAlgoAPI_Pipe& thePipeAlgo,
317 const int theResultIndex)
319 // Create result body.
320 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
322 // Store generated shape.
323 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
325 // Store generated edges/faces.
327 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
329 for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
330 GeomShapePtr aBaseShape = *anIter;
331 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
332 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
333 std::string aGenName = "Generated_";
334 switch(aBaseShapeType) {
335 case GeomAPI_Shape::VERTEX: {
336 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
340 case GeomAPI_Shape::EDGE:
341 case GeomAPI_Shape::WIRE: {
342 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
343 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
344 ListOfShape aV1History, aV2History;
345 thePipeAlgo.generated(aV1, aV1History);
346 thePipeAlgo.generated(aV2, aV2History);
347 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
348 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
350 case GeomAPI_Shape::FACE:
351 case GeomAPI_Shape::SHELL: {
352 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
357 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode, aGenTag++, aGenName, *aMapOfSubShapes.get());
360 // Store from shapes.
361 int aFromTag = aGenTag;
362 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes, thePipeAlgo.fromShapes(), "From", aFromTag);
365 int aToTag = aFromTag;
366 storeShapes(aResultBody, theBaseShapes.back()->shapeType(), aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
369 setResult(aResultBody, theResultIndex);
372 //=================================================================================================
373 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
374 const GeomAPI_Shape::ShapeType theBaseShapeType,
375 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
376 const ListOfShape& theShapes,
377 const std::string theName,
380 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
381 std::string aShapeTypeStr = "Face";
382 switch(theBaseShapeType) {
383 case GeomAPI_Shape::VERTEX: {
384 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
385 aShapeTypeStr = "Vertex";
388 case GeomAPI_Shape::EDGE:
389 case GeomAPI_Shape::WIRE: {
390 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
391 aShapeTypeStr = "Edge";
394 case GeomAPI_Shape::FACE:
395 case GeomAPI_Shape::SHELL: {
396 aShapeTypeToExplore = GeomAPI_Shape::FACE;
397 aShapeTypeStr = "Face";
404 std::string aName = theName + aShapeTypeStr;
405 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
406 std::shared_ptr<GeomAPI_Shape> aShape = *anIt;
407 for(GeomAPI_ShapeExplorer anExp(aShape, aShapeTypeToExplore); anExp.more(); anExp.next()) {
408 std::shared_ptr<GeomAPI_Shape> aSubShape = anExp.current();
409 if(theMapOfSubShapes->isBound(aSubShape)) {
410 aSubShape = theMapOfSubShapes->find(aSubShape);
412 std::ostringstream aStr;
413 aStr << aName << "_" << aShapeIndex++;
414 theResultBody->generated(aSubShape, aStr.str(), theTag++);