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,
46 //==================================================================================================
47 FeaturesPlugin_Pipe::FeaturesPlugin_Pipe()
51 //==================================================================================================
52 void FeaturesPlugin_Pipe::initAttributes()
54 data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
56 data()->addAttribute(BASE_OBJECTS_ID(), ModelAPI_AttributeSelectionList::typeId());
57 data()->addAttribute(PATH_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
59 data()->addAttribute(BINORMAL_ID(), ModelAPI_AttributeSelection::typeId());
61 data()->addAttribute(LOCATIONS_ID(), ModelAPI_AttributeSelectionList::typeId());
62 ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), LOCATIONS_ID());
65 //==================================================================================================
66 void FeaturesPlugin_Pipe::execute()
68 // Getting creation method.
69 std::string aCreationMethod = string(CREATION_METHOD())->value();
71 // Getting base objects.
72 ListOfShape aBaseShapesList, aBaseFacesList;
73 std::map<ResultConstructionPtr, ListOfShape> aSketchWiresMap;
74 AttributeSelectionListPtr aBaseObjectsSelectionList = selectionList(BASE_OBJECTS_ID());
75 if(!aBaseObjectsSelectionList.get()) {
76 setError("Error: Could not get base objects selection list.");
79 if(aBaseObjectsSelectionList->size() == 0) {
80 setError("Error: Base objects list is empty.");
83 for(int anIndex = 0; anIndex < aBaseObjectsSelectionList->size(); anIndex++) {
84 AttributeSelectionPtr aBaseObjectSelection = aBaseObjectsSelectionList->value(anIndex);
85 if(!aBaseObjectSelection.get()) {
86 setError("Error: One of the selected base objects is empty.");
89 std::shared_ptr<GeomAPI_Shape> aBaseShape = aBaseObjectSelection->value();
90 if(aBaseShape.get() && !aBaseShape->isNull()) {
91 GeomAPI_Shape::ShapeType aST = aBaseShape->shapeType();
92 ResultConstructionPtr aConstruction =
93 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
94 if(aConstruction.get() && !aBaseShape->isEqual(aConstruction->shape()) &&
95 aST == GeomAPI_Shape::WIRE) {
96 // It is a wire on the sketch, store it to make face later.
97 aSketchWiresMap[aConstruction].push_back(aBaseShape);
100 aST == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
101 aBaseShapesList.push_back(aBaseShape);
104 // This may be the whole sketch result selected, check and get faces.
105 ResultConstructionPtr aConstruction =
106 std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aBaseObjectSelection->context());
107 if(!aConstruction.get()) {
108 setError("Error: One of selected sketches does not have results.");
111 int aFacesNum = aConstruction->facesNum();
113 // Probably it can be construction.
114 aBaseShape = aConstruction->shape();
115 if(aBaseShape.get() && !aBaseShape->isNull()) {
116 aBaseShape->shapeType() == GeomAPI_Shape::FACE ? aBaseFacesList.push_back(aBaseShape) :
117 aBaseShapesList.push_back(aBaseShape);
120 for(int aFaceIndex = 0; aFaceIndex < aFacesNum; aFaceIndex++) {
121 std::shared_ptr<GeomAPI_Shape> aBaseFace =
122 std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
123 if(!aBaseFace.get() || aBaseFace->isNull()) {
124 setError("Error: One of the faces on selected sketch is Null.");
127 aBaseFacesList.push_back(aBaseFace);
133 // Make faces from sketch wires.
134 for(std::map<ResultConstructionPtr, ListOfShape>::const_iterator anIt = aSketchWiresMap.cbegin();
135 anIt != aSketchWiresMap.cend(); ++anIt) {
136 const std::shared_ptr<GeomAPI_PlanarEdges> aSketchPlanarEdges =
137 std::dynamic_pointer_cast<GeomAPI_PlanarEdges>((*anIt).first->shape());
138 const ListOfShape& aWiresList = (*anIt).second;
140 GeomAlgoAPI_ShapeTools::makeFacesWithHoles(aSketchPlanarEdges->origin(),
141 aSketchPlanarEdges->norm(),
144 aBaseFacesList.insert(aBaseFacesList.end(), aFaces.begin(), aFaces.end());
147 // Searching faces with common edges.
148 if(aCreationMethod == CREATION_METHOD_SIMPLE()) {
150 ListOfShape aFreeFaces;
151 std::shared_ptr<GeomAPI_Shape> aFacesCompound =
152 GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
153 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL,
154 aShells, aFreeFaces);
155 aBaseShapesList.insert(aBaseShapesList.end(), aFreeFaces.begin(), aFreeFaces.end());
156 aBaseShapesList.insert(aBaseShapesList.end(), aShells.begin(), aShells.end());
158 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
162 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
163 if(!aPathSelection.get()) {
164 setError("Error: Path selection is empty.");
167 std::shared_ptr<GeomAPI_Shape> aPathShape =
168 std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
169 if(!aPathShape.get()) {
170 // Probaply it is a construction.
171 aPathShape = aPathSelection->context()->shape();
173 if(!aPathShape.get() || aPathShape->isNull()) {
174 setError("Error: Path shape is null.");
179 std::shared_ptr<GeomAPI_Shape> aBiNormal;
180 if(aCreationMethod == CREATION_METHOD_BINORMAL()) {
181 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
182 if(!aBiNormalSelection.get()) {
183 setError("Error: Bi-Normal selection is empty.");
186 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
187 if(!aBiNormal.get()) {
188 // Probably it is a construction.
189 aBiNormal = aBiNormalSelection->context()->shape();
191 if(!aBiNormal.get() || aBiNormal->isNull()) {
192 setError("Error: Bi-Normal shape is null.");
197 // Getting locations.
198 ListOfShape aLocations;
199 if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
200 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
201 if(!aLocationsSelectionList.get()) {
202 setError("Error: Could not get locations selection list.");
205 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
206 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
207 if(!aLocationSelection.get()) {
208 setError("Error: One of the selected location is empty.");
211 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
212 if(!aLocationShape.get()) {
213 // Probably it is a construction.
214 aLocationShape = aLocationSelection->context()->shape();
216 if(!aLocationShape.get() || aLocationShape->isNull()) {
217 setError("Error: One of the selected location shape is null.");
220 aLocations.push_back(aLocationShape);
224 // Generating result for each object.
225 int aResultIndex = 0;
226 if(aCreationMethod == CREATION_METHOD_SIMPLE() ||
227 aCreationMethod == CREATION_METHOD_BINORMAL()) {
228 for(ListOfShape::const_iterator
229 anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
230 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
232 GeomAlgoAPI_Pipe aPipeAlgo = aCreationMethod ==
233 CREATION_METHOD_SIMPLE() ? GeomAlgoAPI_Pipe(aBaseShape, aPathShape) :
234 GeomAlgoAPI_Pipe(aBaseShape, aPathShape, aBiNormal);
236 if(!aPipeAlgo.isDone()) {
237 setError("Error: Pipe algorithm failed.");
242 // Check if shape is valid
243 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
244 setError("Error: Resulting shape is Null.");
248 if(!aPipeAlgo.isValid()) {
249 setError("Error: Resulting shape is not valid.");
254 storeResult(aBaseShape, aPipeAlgo, aResultIndex++);
256 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
257 GeomAlgoAPI_Pipe aPipeAlgo = GeomAlgoAPI_Pipe(aBaseShapesList, aLocations, aPathShape);
259 if(!aPipeAlgo.isDone()) {
260 setError("Error: Pipe algorithm failed.");
265 // Check if shape is valid
266 if(!aPipeAlgo.shape().get() || aPipeAlgo.shape()->isNull()) {
267 setError("Error: Resulting shape is Null.");
271 if(!aPipeAlgo.isValid()) {
272 setError("Error: Resulting shape is not valid.");
277 storeResult(aBaseShapesList, aPipeAlgo, aResultIndex++);
279 setError("Error: Wrong creation method.");
283 removeResults(aResultIndex);
286 //==================================================================================================
287 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
288 GeomAlgoAPI_Pipe& thePipeAlgo,
289 const int theResultIndex)
291 // Create result body.
292 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
294 // Store generated shape.
295 aResultBody->storeGenerated(theBaseShape, thePipeAlgo.shape());
297 // Store generated edges/faces.
298 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
299 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
301 std::string aGenName = "Generated_";
303 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
304 switch(aBaseShapeType) {
305 case GeomAPI_Shape::VERTEX: {
306 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
309 case GeomAPI_Shape::EDGE:
310 case GeomAPI_Shape::WIRE: {
311 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
312 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
313 ListOfShape aV1History, aV2History;
314 thePipeAlgo.generated(aV1, aV1History);
315 thePipeAlgo.generated(aV2, aV2History);
316 if(!aV1History.empty()) {
317 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1");
319 if(!aV2History.empty()) {
320 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2");
323 case GeomAPI_Shape::FACE:
324 case GeomAPI_Shape::SHELL: {
325 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
328 case GeomAPI_Shape::COMPOUND: {
329 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
333 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
334 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
335 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX,
336 aGenTag++, aGenName + "Edge", *aMapOfSubShapes.get());
338 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
339 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
340 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE,
341 aGenTag++, aGenName + "Face", *aMapOfSubShapes.get());
344 // Store from shapes.
345 int aFromTag = aGenTag;
346 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes,
347 thePipeAlgo.fromShapes(), "From_", aFromTag);
350 int aToTag = aFromTag;
351 storeShapes(aResultBody, aBaseShapeType, aMapOfSubShapes, thePipeAlgo.toShapes(), "To_", aToTag);
353 setResult(aResultBody, theResultIndex);
356 //==================================================================================================
357 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
358 GeomAlgoAPI_Pipe& thePipeAlgo,
359 const int theResultIndex)
361 // Create result body.
362 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
364 // Store generated shape.
365 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo.shape());
367 // Store generated edges/faces.
369 std::shared_ptr<GeomAPI_DataMapOfShapeShape> aMapOfSubShapes = thePipeAlgo.mapOfSubShapes();
371 for(ListOfShape::const_iterator
372 anIter = theBaseShapes.cbegin(); anIter != theBaseShapes.cend(); anIter++) {
373 GeomShapePtr aBaseShape = *anIter;
374 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
375 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
376 std::string aGenName = "Generated_";
377 switch(aBaseShapeType) {
378 case GeomAPI_Shape::VERTEX: {
379 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
383 case GeomAPI_Shape::EDGE:
384 case GeomAPI_Shape::WIRE: {
385 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
386 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
387 ListOfShape aV1History, aV2History;
388 thePipeAlgo.generated(aV1, aV1History);
389 thePipeAlgo.generated(aV2, aV2History);
390 aResultBody->generated(aV1, aV1History.front(), aGenName + "Edge_1");
391 aResultBody->generated(aV2, aV2History.front(), aGenName + "Edge_2");
393 case GeomAPI_Shape::FACE:
394 case GeomAPI_Shape::SHELL: {
395 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
400 aResultBody->loadAndOrientGeneratedShapes(&thePipeAlgo, aBaseShape, aShapeTypeToExplode,
401 aGenTag++, aGenName, *aMapOfSubShapes.get());
404 // Store from shapes.
405 int aFromTag = aGenTag;
406 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), aMapOfSubShapes,
407 thePipeAlgo.fromShapes(), "From", aFromTag);
410 int aToTag = aFromTag;
411 storeShapes(aResultBody, theBaseShapes.back()->shapeType(),
412 aMapOfSubShapes, thePipeAlgo.toShapes(), "To", aToTag);
415 setResult(aResultBody, theResultIndex);
418 //==================================================================================================
419 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
420 const GeomAPI_Shape::ShapeType theBaseShapeType,
421 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
422 const ListOfShape& theShapes,
423 const std::string theName,
426 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
427 std::string aShapeTypeStr = "Face";
428 switch(theBaseShapeType) {
429 case GeomAPI_Shape::VERTEX: {
430 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
431 aShapeTypeStr = "Vertex";
434 case GeomAPI_Shape::EDGE:
435 case GeomAPI_Shape::WIRE: {
436 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
437 aShapeTypeStr = "Edge";
440 case GeomAPI_Shape::FACE:
441 case GeomAPI_Shape::SHELL: {
442 aShapeTypeToExplore = GeomAPI_Shape::FACE;
443 aShapeTypeStr = "Face";
446 case GeomAPI_Shape::COMPOUND: {
447 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
455 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
456 GeomShapePtr aShape = *anIt;
458 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
459 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
460 storeSubShape(theResultBody,
465 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex);
467 std::string aName = theName + aShapeTypeStr;
468 storeSubShape(theResultBody, aShape, aShapeTypeToExplore,
469 theMapOfSubShapes, aName, aShapeIndex);
474 //==================================================================================================
475 void storeSubShape(ResultBodyPtr theResultBody,
476 const GeomShapePtr theShape,
477 const GeomAPI_Shape::ShapeType theType,
478 const std::shared_ptr<GeomAPI_DataMapOfShapeShape> theMapOfSubShapes,
479 const std::string theName,
482 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
483 GeomShapePtr aSubShape = anExp.current();
484 if(theMapOfSubShapes->isBound(aSubShape)) {
485 aSubShape = theMapOfSubShapes->find(aSubShape);
487 std::ostringstream aStr;
488 aStr << theName << "_" << theShapeIndex++;
489 theResultBody->generated(aSubShape, aStr.str());