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::string theName,
45 //==================================================================================================
46 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
50 //==================================================================================================
51 void FeaturesPlugin_Pipe::initAttributes()
53 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
55 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
56 data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
58 data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
60 data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
61 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
64 //==================================================================================================
65 void FeaturesPlugin_Pipe::execute()
67 // Getting creation method.
68 std::string aCreationMethod = string(CREATION_METHOD())->value();
70 // Getting base objects.
71 ListOfShape aBaseShapesList, aBaseFacesList;
72 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
73 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
74 if(!aBaseObjectsSelectionList.get()) {
75 setError("Error: Could not get base objects selection list.");
78 if(aBaseObjectsSelectionList->size() == 0) {
79 setError("Error: Base objects list is empty.");
82 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
83 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
84 if(!aBaseObjectSelection.get()) {
85 setError("Error: One of the selected base objects is empty.");
88 std::shared_ptr<GeomAPI_Shape> aBaseShape = aBaseObjectSelection->value();
89 if(aBaseShape.get() && !aBaseShape->isNull()) {
90 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
91 ResultConstructionPtr aConstruction =
92 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
93 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
94 aST == GeomAPI_Shape::WIRE) {
95 // It is a wire on the sketch, store it to make face later.
96 aSketchWiresMap[aConstruction].push_back(aBaseShape);
99 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
100 aBaseShapesList.push_back(aBaseShape);
103 // This may be the whole sketch result selected, check and get faces.
104 ResultConstructionPtr aConstruction =
105 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
106 if(!aConstruction.get()) {
107 setError("Error: One of selected sketches does not have results.");
110 int aFacesNum = aConstruction->facesNum();
112 // Probably it can be construction.
113 aBaseShape = aConstruction->shape();
114 if(aBaseShape.get() && !aBaseShape->isNull()) {
115 aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
116 aBaseShapesList.push_back(aBaseShape);
119 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
120 std::shared_ptr<GeomAPI_Shape> aBaseFace =
121 std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
122 if(!aBaseFace.get() || aBaseFace->isNull()) {
123 setError("Error: One of the faces on selected sketch is Null.");
126 aBaseFacesList.push_back(aBaseFace);
132 // Make faces from sketch wires.
133 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
134 anIt != aSketchWiresMap.cend(); ++anIt) {
135 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
136 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
137 const ListOfShape& aWiresList = (*anIt).second;
139 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
140 aSketchPlanarEdges->norm(),
143 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
146 // Searching faces with common edges.
147 if(aCreationMethod == CREATION_METHOD_SIMPLE()) {
149 ListOfShape aFreeFaces;
150 std::shared_ptr<GeomAPI_Shape> aFacesCompound =
151 GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
152 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
153 aShells, aFreeFaces);
154 aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
155 aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
157 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
161 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
162 if(!aPathSelection.get()) {
163 setError("Error: Path selection is empty.");
166 std::shared_ptr<GeomAPI_Shape> aPathShape =
167 std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
168 if(!aPathShape.get()) {
169 // Probaply it is a construction.
170 aPathShape = aPathSelection->context()->shape();
172 if(!aPathShape.get() || aPathShape->isNull()) {
173 setError("Error: Path shape is null.");
178 std::shared_ptr<GeomAPI_Shape> aBiNormal;
179 if(aCreationMethod == CREATION_METHOD_BINORMAL()) {
180 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
181 if(!aBiNormalSelection.get()) {
182 setError("Error: Bi-Normal selection is empty.");
185 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
186 if(!aBiNormal.get()) {
187 // Probably it is a construction.
188 aBiNormal = aBiNormalSelection->context()->shape();
190 if(!aBiNormal.get() || aBiNormal->isNull()) {
191 setError("Error: Bi-Normal shape is null.");
196 // Getting locations.
197 ListOfShape aLocations;
198 if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
199 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
200 if(!aLocationsSelectionList.get()) {
201 setError("Error: Could not get locations selection list.");
204 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
205 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
206 if(!aLocationSelection.get()) {
207 setError("Error: One of the selected location is empty.");
210 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
211 if(!aLocationShape.get()) {
212 // Probably it is a construction.
213 aLocationShape = aLocationSelection->context()->shape();
215 if(!aLocationShape.get() || aLocationShape->isNull()) {
216 setError("Error: One of the selected location shape is null.");
219 aLocations.push_back(aLocationShape);
223 // Generating result for each object.
224 int aResultIndex = 0;
225 if(aCreationMethod == CREATION_METHOD_SIMPLE() ||
226 aCreationMethod == CREATION_METHOD_BINORMAL()) {
227 for(ListOfShape::const_iterator
228 anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
229 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
231 std::shared_ptr<GeomAlgoAPI_Pipe> aPipeAlgo(
232 aCreationMethod == CREATION_METHOD_SIMPLE() ? new GeomAlgoAPI_Pipe(aBaseShape,
234 : new GeomAlgoAPI_Pipe(aBaseShape,
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(aBaseShape, aPipeAlgo, aResultIndex++);
258 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
259 std::shared_ptr<GeomAlgoAPI_Pipe> aPipeAlgo(new GeomAlgoAPI_Pipe(aBaseShapesList,
263 if(!aPipeAlgo->isDone()) {
264 setError("Error: Pipe algorithm failed.");
269 // Check if shape is valid
270 if(!aPipeAlgo->shape().get() || aPipeAlgo->shape()->isNull()) {
271 setError("Error: Resulting shape is Null.");
275 if(!aPipeAlgo->isValid()) {
276 setError("Error: Resulting shape is not valid.");
281 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
283 setError("Error: Wrong creation method.");
287 removeResults(aResultIndex);
290 //==================================================================================================
291 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
292 const std::shared_ptr<GeomAlgoAPI_Pipe> thePipeAlgo,
293 const int theResultIndex)
295 // Create result body.
296 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
298 // Store generated shape.
299 aResultBody->storeGenerated(theBaseShape, thePipeAlgo->shape());
301 // Store generated edges/faces.
302 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
303 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
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());
320 if(!aV2History.empty()) {
321 aResultBody->generated(aV2, aV2History.front());
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->loadGeneratedShapes(thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX);
338 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
339 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
340 aResultBody->loadGeneratedShapes(thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE);
343 // Store from shapes.
344 storeShapes(aResultBody, aBaseShapeType, thePipeAlgo->fromShapes(), "From_");
347 storeShapes(aResultBody, aBaseShapeType, thePipeAlgo->toShapes(), "To_");
349 setResult(aResultBody, theResultIndex);
352 //==================================================================================================
353 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
354 const std::shared_ptr<GeomAlgoAPI_Pipe> thePipeAlgo,
355 const int theResultIndex)
357 // Create result body.
358 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
360 // Store generated shape.
361 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo->shape());
363 // Store generated edges/faces.
364 for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin();
365 anIter != theBaseShapes.cend();
368 GeomShapePtr aBaseShape = *anIter;
369 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
370 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
371 switch(aBaseShapeType) {
372 case GeomAPI_Shape::VERTEX: {
373 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
376 case GeomAPI_Shape::EDGE:
377 case GeomAPI_Shape::WIRE: {
378 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
379 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
380 ListOfShape aV1History, aV2History;
381 thePipeAlgo->generated(aV1, aV1History);
382 thePipeAlgo->generated(aV2, aV2History);
383 aResultBody->generated(aV1, aV1History.front());
384 aResultBody->generated(aV2, aV2History.front());
386 case GeomAPI_Shape::FACE:
387 case GeomAPI_Shape::SHELL: {
388 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
392 aResultBody->loadGeneratedShapes(thePipeAlgo, aBaseShape, aShapeTypeToExplode);
395 // Store from shapes.
396 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), thePipeAlgo->fromShapes(), "From_");
399 storeShapes(aResultBody, theBaseShapes.back()->shapeType(), thePipeAlgo->toShapes(), "To_");
402 setResult(aResultBody, theResultIndex);
405 //==================================================================================================
406 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
407 const GeomAPI_Shape::ShapeType theBaseShapeType,
408 const ListOfShape& theShapes,
409 const std::string theName)
411 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
412 std::string aShapeTypeStr = "Face";
413 switch(theBaseShapeType) {
414 case GeomAPI_Shape::VERTEX: {
415 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
416 aShapeTypeStr = "Vertex";
419 case GeomAPI_Shape::EDGE:
420 case GeomAPI_Shape::WIRE: {
421 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
422 aShapeTypeStr = "Edge";
425 case GeomAPI_Shape::FACE:
426 case GeomAPI_Shape::SHELL: {
427 aShapeTypeToExplore = GeomAPI_Shape::FACE;
428 aShapeTypeStr = "Face";
431 case GeomAPI_Shape::COMPOUND: {
432 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
440 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
441 GeomShapePtr aShape = *anIt;
443 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
444 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
445 storeSubShape(theResultBody, aShape,
448 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex);
450 std::string aName = theName + aShapeTypeStr;
451 storeSubShape(theResultBody, aShape, aShapeTypeToExplore, aName, aShapeIndex);
456 //==================================================================================================
457 void storeSubShape(ResultBodyPtr theResultBody,
458 const GeomShapePtr theShape,
459 const GeomAPI_Shape::ShapeType theType,
460 const std::string theName,
463 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
464 GeomShapePtr aSubShape = anExp.current();
465 std::ostringstream aStr;
466 aStr << theName << "_" << theShapeIndex++;
467 theResultBody->generated(aSubShape, aStr.str());