1 // Copyright (C) 2014-2017 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
21 #include "FeaturesPlugin_Pipe.h"
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>
30 #include <GeomAlgoAPI_CompoundBuilder.h>
31 #include <GeomAlgoAPI_Pipe.h>
32 #include <GeomAlgoAPI_ShapeTools.h>
33 #include <GeomAPI_PlanarEdges.h>
34 #include <GeomAPI_ShapeExplorer.h>
39 static void storeSubShape(ResultBodyPtr theResultBody,
40 const GeomShapePtr theShape,
41 const GeomAPI_Shape::ShapeType theType,
42 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
43 const std::string theName,
47 //==================================================================================================
48 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
52 //==================================================================================================
53 void FeaturesPlugin_Pipe::initAttributes()
55 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
57 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
58 data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
60 data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
62 data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
63 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
66 //==================================================================================================
67 void FeaturesPlugin_Pipe::execute()
69 // Getting creation method.
70 std::string aCreationMethod = string(CREATION_METHOD())->value();
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.");
80 if(aBaseObjectsSelectionList->size() == 0) {
81 setError("Error: Base objects list is empty.");
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.");
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);
101 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
102 aBaseShapesList.push_back(aBaseShape);
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.");
112 int aFacesNum = aConstruction->facesNum();
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);
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.");
128 aBaseFacesList.push_back(aBaseFace);
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;
141 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
142 aSketchPlanarEdges->norm(),
145 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
148 // Searching faces with common edges.
149 if(aCreationMethod == CREATION_METHOD_SIMPLE()) {
151 ListOfShape aFreeFaces;
152 std::shared_ptr<GeomAPI_Shape> aFacesCompound =
153 GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
154 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
155 aShells, aFreeFaces);
156 aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
157 aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
159 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
163 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
164 if(!aPathSelection.get()) {
165 setError("Error: Path selection is empty.");
168 std::shared_ptr<GeomAPI_Shape> aPathShape =
169 std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
170 if(!aPathShape.get()) {
171 // Probaply it is a construction.
172 aPathShape = aPathSelection->context()->shape();
174 if(!aPathShape.get() || aPathShape->isNull()) {
175 setError("Error: Path shape is null.");
180 std::shared_ptr<GeomAPI_Shape> aBiNormal;
181 if(aCreationMethod == CREATION_METHOD_BINORMAL()) {
182 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
183 if(!aBiNormalSelection.get()) {
184 setError("Error: Bi-Normal selection is empty.");
187 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
188 if(!aBiNormal.get()) {
189 // Probably it is a construction.
190 aBiNormal = aBiNormalSelection->context()->shape();
192 if(!aBiNormal.get() || aBiNormal->isNull()) {
193 setError("Error: Bi-Normal shape is null.");
198 // Getting locations.
199 ListOfShape aLocations;
200 if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
201 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
202 if(!aLocationsSelectionList.get()) {
203 setError("Error: Could not get locations selection list.");
206 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
207 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
208 if(!aLocationSelection.get()) {
209 setError("Error: One of the selected location is empty.");
212 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
213 if(!aLocationShape.get()) {
214 // Probably it is a construction.
215 aLocationShape = aLocationSelection->context()->shape();
217 if(!aLocationShape.get() || aLocationShape->isNull()) {
218 setError("Error: One of the selected location shape is null.");
221 aLocations.push_back(aLocationShape);
225 // Generating result for each object.
226 int aResultIndex = 0;
227 if(aCreationMethod == CREATION_METHOD_SIMPLE() ||
228 aCreationMethod == CREATION_METHOD_BINORMAL()) {
229 for(ListOfShape::const_iterator
230 anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
231 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
233 GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod ==
234 CREATION_METHOD_SIMPLE() ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
235 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
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(aBaseShape, aPipeAlgo, aResultIndex++);
257 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
258 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
260 if(!aPipeAlgo.isDone()) {
261 setError("Error: Pipe algorithm failed.");
266 // Check if shape is valid
267 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
268 setError("Error: Resulting shape is Null.");
272 if(!aPipeAlgo.isValid()) {
273 setError("Error: Resulting shape is not valid.");
278 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
280 setError("Error: Wrong creation method.");
284 removeResults(aResultIndex);
287 //==================================================================================================
288 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
289 GeomAlgoAPI_Pipe& thePipeAlgo,
290 const int theResultIndex)
292 // Create result body.
293 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
295 // Store generated shape.
296 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
298 // Store generated edges/faces.
299 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
300 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
302 std::string aGenName = "Generated_";
304 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
305 switch(aBaseShapeType) {
306 case GeomAPI_Shape::VERTEX: {
307 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
310 case GeomAPI_Shape::EDGE:
311 case GeomAPI_Shape::WIRE: {
312 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
313 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
314 ListOfShape aV1History, aV2History;
315 thePipeAlgo.generated(aV1, aV1History);
316 thePipeAlgo.generated(aV2, aV2History);
317 if(!aV1History.empty()) {
318 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
320 if(!aV2History.empty()) {
321 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
324 case GeomAPI_Shape::FACE:
325 case GeomAPI_Shape::SHELL: {
326 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
329 case GeomAPI_Shape::COMPOUND: {
330 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
334 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
335 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
336 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
337 aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
339 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
340 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
341 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
342 aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
345 // Store from shapes.
346 int aFromTag = aGenTag;
347 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes,
348 thePipeAlgo.fromShapes(), "From_", aFromTag);
351 int aToTag = aFromTag;
352 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
354 setResult(aResultBody, theResultIndex);
357 //==================================================================================================
358 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
359 GeomAlgoAPI_Pipe& thePipeAlgo,
360 const int theResultIndex)
362 // Create result body.
363 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
365 // Store generated shape.
366 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
368 // Store generated edges/faces.
370 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
372 for(ListOfShape::const_iterator
373 anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
374 GeomShapePtr aBaseShape = *anIter;
375 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
376 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
377 std::string aGenName = "Generated_";
378 switch(aBaseShapeType) {
379 case GeomAPI_Shape::VERTEX: {
380 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
384 case GeomAPI_Shape::EDGE:
385 case GeomAPI_Shape::WIRE: {
386 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
387 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
388 ListOfShape aV1History, aV2History;
389 thePipeAlgo.generated(aV1, aV1History);
390 thePipeAlgo.generated(aV2, aV2History);
391 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1", aGenTag++);
392 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2", aGenTag++);
394 case GeomAPI_Shape::FACE:
395 case GeomAPI_Shape::SHELL: {
396 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
401 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode,
402 aGenTag++, aGenName, *aMapOfSubShapes.get());
405 // Store from shapes.
406 int aFromTag = aGenTag;
407 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes,
408 thePipeAlgo.fromShapes(), "From", aFromTag);
411 int aToTag = aFromTag;
412 storeShapes(aResultBody, theBaseShapes.back()->shapeType(),
413 aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
416 setResult(aResultBody, theResultIndex);
419 //==================================================================================================
420 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
421 const GeomAPI_Shape::ShapeType theBaseShapeType,
422 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
423 const ListOfShape& theShapes,
424 const std::string theName,
427 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
428 std::string aShapeTypeStr = "Face";
429 switch(theBaseShapeType) {
430 case GeomAPI_Shape::VERTEX: {
431 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
432 aShapeTypeStr = "Vertex";
435 case GeomAPI_Shape::EDGE:
436 case GeomAPI_Shape::WIRE: {
437 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
438 aShapeTypeStr = "Edge";
441 case GeomAPI_Shape::FACE:
442 case GeomAPI_Shape::SHELL: {
443 aShapeTypeToExplore = GeomAPI_Shape::FACE;
444 aShapeTypeStr = "Face";
447 case GeomAPI_Shape::COMPOUND: {
448 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
456 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
457 GeomShapePtr aShape = *anIt;
459 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
460 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
461 storeSubShape(theResultBody,
466 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex,
469 std::string aName = theName + aShapeTypeStr;
470 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
471 theMapOfSubShapes, aName, aShapeIndex, theTag);
476 //==================================================================================================
477 void storeSubShape(ResultBodyPtr theResultBody,
478 const GeomShapePtr theShape,
479 const GeomAPI_Shape::ShapeType theType,
480 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
481 const std::string theName,
485 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
486 GeomShapePtr aSubShape = anExp.current();
487 if(theMapOfSubShapes->isBound(aSubShape)) {
488 aSubShape = theMapOfSubShapes->find(aSubShape);
490 std::ostringstream aStr;
491 aStr << theName << "_" << theShapeIndex++;
492 theResultBody->generated(aSubShape, aStr.str(), theTag++);