1 // Copyright (C) 2014-2019 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 email : webmaster.salome@opencascade.com
20 #include "FeaturesPlugin_Pipe.h"
22 #include <ModelAPI_AttributeSelection.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultConstruction.h>
26 #include <ModelAPI_Session.h>
27 #include <ModelAPI_Validator.h>
29 #include <GeomAlgoAPI_CompoundBuilder.h>
30 #include <GeomAlgoAPI_Pipe.h>
31 #include <GeomAlgoAPI_ShapeTools.h>
32 #include <GeomAlgoAPI_Tools.h>
34 #include <GeomAPI_PlanarEdges.h>
35 #include <GeomAPI_ShapeExplorer.h>
40 static void storeSubShape(ResultBodyPtr theResultBody,
41 const GeomShapePtr theShape,
42 const GeomAPI_Shape::ShapeType theType,
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()) {
149 std::shared_ptr<GeomAPI_Shape> aFacesCompound =
150 GeomAlgoAPI_CompoundBuilder::compound(aBaseFacesList);
151 GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aBaseShapesList);
153 aBaseShapesList.insert(aBaseShapesList.end(), aBaseFacesList.begin(), aBaseFacesList.end());
157 AttributeSelectionPtr aPathSelection = selection(PATH_OBJECT_ID());
158 if(!aPathSelection.get()) {
159 setError("Error: Path selection is empty.");
162 std::shared_ptr<GeomAPI_Shape> aPathShape =
163 std::dynamic_pointer_cast<GeomAPI_Shape>(aPathSelection->value());
164 if(!aPathShape.get() && aPathSelection->context().get()) {
165 // Probably it is a construction.
166 aPathShape = aPathSelection->context()->shape();
168 if(!aPathShape.get() || aPathShape->isNull()) {
169 setError("Error: Path shape is null.");
174 std::shared_ptr<GeomAPI_Shape> aBiNormal;
175 if(aCreationMethod == CREATION_METHOD_BINORMAL()) {
176 AttributeSelectionPtr aBiNormalSelection = selection(BINORMAL_ID());
177 if(!aBiNormalSelection.get()) {
178 setError("Error: Bi-Normal selection is empty.");
181 aBiNormal = std::dynamic_pointer_cast<GeomAPI_Shape>(aBiNormalSelection->value());
182 if(!aBiNormal.get() && aBiNormalSelection->context().get()) {
183 // Probably it is a construction.
184 aBiNormal = aBiNormalSelection->context()->shape();
186 if(!aBiNormal.get() || aBiNormal->isNull()) {
187 setError("Error: Bi-Normal shape is null.");
192 // Getting locations.
193 ListOfShape aLocations;
194 if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
195 AttributeSelectionListPtr aLocationsSelectionList = selectionList(LOCATIONS_ID());
196 if(!aLocationsSelectionList.get()) {
197 setError("Error: Could not get locations selection list.");
200 for(int anIndex = 0; anIndex < aLocationsSelectionList->size(); anIndex++) {
201 AttributeSelectionPtr aLocationSelection = aLocationsSelectionList->value(anIndex);
202 if(!aLocationSelection.get()) {
203 setError("Error: One of the selected location is empty.");
206 std::shared_ptr<GeomAPI_Shape> aLocationShape = aLocationSelection->value();
207 if(!aLocationShape.get() && aLocationSelection->context().get()) {
208 // Probably it is a construction.
209 aLocationShape = aLocationSelection->context()->shape();
211 if(!aLocationShape.get() || aLocationShape->isNull()) {
212 setError("Error: One of the selected location shape is null.");
215 aLocations.push_back(aLocationShape);
219 // Generating result for each object.
220 int aResultIndex = 0;
222 if(aCreationMethod == CREATION_METHOD_SIMPLE() ||
223 aCreationMethod == CREATION_METHOD_BINORMAL()) {
224 for(ListOfShape::const_iterator
225 anIter = aBaseShapesList.cbegin(); anIter != aBaseShapesList.cend(); anIter++) {
226 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
228 std::shared_ptr<GeomAlgoAPI_Pipe> aPipeAlgo(
229 aCreationMethod == CREATION_METHOD_SIMPLE() ? new GeomAlgoAPI_Pipe(aBaseShape,
231 : new GeomAlgoAPI_Pipe(aBaseShape,
235 if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPipeAlgo, getKind(), anError)) {
241 storeResult(aBaseShape, aPathShape, aPipeAlgo, aResultIndex++);
243 } else if(aCreationMethod == CREATION_METHOD_LOCATIONS()) {
244 std::shared_ptr<GeomAlgoAPI_Pipe> aPipeAlgo(new GeomAlgoAPI_Pipe(aBaseShapesList,
248 if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aPipeAlgo, getKind(), anError)) {
254 storeResult(aBaseShapesList, aPathShape, aPipeAlgo, aResultIndex++);
256 setError("Error: Wrong creation method.");
260 removeResults(aResultIndex);
263 //==================================================================================================
264 void FeaturesPlugin_Pipe::storeResult(const std::shared_ptr<GeomAPI_Shape> theBaseShape,
265 const std::shared_ptr<GeomAPI_Shape> thePathShape,
266 const std::shared_ptr<GeomAlgoAPI_Pipe> thePipeAlgo,
267 const int theResultIndex)
269 // Create result body.
270 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
272 // Store generated shape.
273 aResultBody->storeGenerated(theBaseShape, thePipeAlgo->shape());
275 // Store generated edges/faces.
276 GeomAPI_Shape::ShapeType aBaseShapeType = theBaseShape->shapeType();
277 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
279 switch(aBaseShapeType) {
280 case GeomAPI_Shape::VERTEX: {
281 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
284 case GeomAPI_Shape::EDGE:
285 case GeomAPI_Shape::WIRE: {
286 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
287 GeomAlgoAPI_ShapeTools::findBounds(theBaseShape, aV1, aV2);
288 ListOfShape aV1History, aV2History;
289 thePipeAlgo->generated(aV1, aV1History);
290 thePipeAlgo->generated(aV2, aV2History);
291 if(!aV1History.empty()) {
292 aResultBody->generated(aV1, aV1History.front());
294 if(!aV2History.empty()) {
295 aResultBody->generated(aV2, aV2History.front());
298 case GeomAPI_Shape::FACE:
299 case GeomAPI_Shape::SHELL: {
300 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
303 case GeomAPI_Shape::COMPOUND: {
304 aShapeTypeToExplode = GeomAPI_Shape::COMPOUND;
308 if(aShapeTypeToExplode == GeomAPI_Shape::VERTEX ||
309 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
310 aResultBody->loadGeneratedShapes(thePipeAlgo, theBaseShape, GeomAPI_Shape::VERTEX);
312 if(aShapeTypeToExplode == GeomAPI_Shape::EDGE ||
313 aShapeTypeToExplode == GeomAPI_Shape::COMPOUND) {
314 aResultBody->loadGeneratedShapes(thePipeAlgo, theBaseShape, GeomAPI_Shape::EDGE);
316 if (thePathShape.get())
317 aResultBody->loadGeneratedShapes(thePipeAlgo, thePathShape, GeomAPI_Shape::EDGE);
319 // Store from shapes.
320 storeShapes(aResultBody, aBaseShapeType, thePipeAlgo->fromShapes(), "From_");
323 storeShapes(aResultBody, aBaseShapeType, thePipeAlgo->toShapes(), "To_");
325 setResult(aResultBody, theResultIndex);
328 //==================================================================================================
329 void FeaturesPlugin_Pipe::storeResult(const ListOfShape& theBaseShapes,
330 const std::shared_ptr<GeomAPI_Shape> thePathShape,
331 const std::shared_ptr<GeomAlgoAPI_Pipe> thePipeAlgo,
332 const int theResultIndex)
334 // Create result body.
335 ResultBodyPtr aResultBody = document()->createBody(data(), theResultIndex);
337 // Store generated shape.
338 aResultBody->storeGenerated(theBaseShapes.front(), thePipeAlgo->shape());
340 // Store generated edges/faces.
341 for(ListOfShape::const_iterator anIter = theBaseShapes.cbegin();
342 anIter != theBaseShapes.cend();
345 GeomShapePtr aBaseShape = *anIter;
346 GeomAPI_Shape::ShapeType aBaseShapeType = aBaseShape->shapeType();
347 GeomAPI_Shape::ShapeType aShapeTypeToExplode;
348 switch(aBaseShapeType) {
349 case GeomAPI_Shape::VERTEX: {
350 aShapeTypeToExplode = GeomAPI_Shape::VERTEX;
353 case GeomAPI_Shape::EDGE:
354 case GeomAPI_Shape::WIRE: {
355 std::shared_ptr<GeomAPI_Vertex> aV1, aV2;
356 GeomAlgoAPI_ShapeTools::findBounds(aBaseShape, aV1, aV2);
357 ListOfShape aV1History, aV2History;
358 thePipeAlgo->generated(aV1, aV1History);
359 thePipeAlgo->generated(aV2, aV2History);
360 aResultBody->generated(aV1, aV1History.front());
361 aResultBody->generated(aV2, aV2History.front());
363 case GeomAPI_Shape::FACE:
364 case GeomAPI_Shape::SHELL: {
365 aShapeTypeToExplode = GeomAPI_Shape::EDGE;
369 aResultBody->loadGeneratedShapes(thePipeAlgo, aBaseShape, aShapeTypeToExplode);
372 if (thePathShape.get())
373 aResultBody->loadGeneratedShapes(thePipeAlgo, thePathShape, GeomAPI_Shape::EDGE);
375 // Store from shapes.
376 storeShapes(aResultBody, theBaseShapes.front()->shapeType(), thePipeAlgo->fromShapes(), "From_");
379 storeShapes(aResultBody, theBaseShapes.back()->shapeType(), thePipeAlgo->toShapes(), "To_");
382 setResult(aResultBody, theResultIndex);
385 //==================================================================================================
386 void FeaturesPlugin_Pipe::storeShapes(ResultBodyPtr theResultBody,
387 const GeomAPI_Shape::ShapeType theBaseShapeType,
388 const ListOfShape& theShapes,
389 const std::string theName)
391 GeomAPI_Shape::ShapeType aShapeTypeToExplore = GeomAPI_Shape::FACE;
392 std::string aShapeTypeStr = "Face";
393 switch(theBaseShapeType) {
394 case GeomAPI_Shape::VERTEX: {
395 aShapeTypeToExplore = GeomAPI_Shape::VERTEX;
396 aShapeTypeStr = "Vertex";
399 case GeomAPI_Shape::EDGE:
400 case GeomAPI_Shape::WIRE: {
401 aShapeTypeToExplore = GeomAPI_Shape::EDGE;
402 aShapeTypeStr = "Edge";
405 case GeomAPI_Shape::FACE:
406 case GeomAPI_Shape::SHELL: {
407 aShapeTypeToExplore = GeomAPI_Shape::FACE;
408 aShapeTypeStr = "Face";
411 case GeomAPI_Shape::COMPOUND: {
412 aShapeTypeToExplore = GeomAPI_Shape::COMPOUND;
420 for(ListOfShape::const_iterator anIt = theShapes.cbegin(); anIt != theShapes.cend(); ++anIt) {
421 GeomShapePtr aShape = *anIt;
423 if(aShapeTypeToExplore == GeomAPI_Shape::COMPOUND) {
424 std::string aName = theName + (aShape->shapeType() == GeomAPI_Shape::EDGE ? "Edge" : "Face");
425 storeSubShape(theResultBody, aShape,
428 aShape->shapeType() == GeomAPI_Shape::EDGE ? aShapeIndex : aFaceIndex);
430 std::string aName = theName + aShapeTypeStr;
431 storeSubShape(theResultBody, aShape, aShapeTypeToExplore, aName, aShapeIndex);
436 //==================================================================================================
437 void storeSubShape(ResultBodyPtr theResultBody,
438 const GeomShapePtr theShape,
439 const GeomAPI_Shape::ShapeType theType,
440 const std::string theName,
443 for(GeomAPI_ShapeExplorer anExp(theShape, theType); anExp.more(); anExp.next()) {
444 GeomShapePtr aSubShape = anExp.current();
445 std::ostringstream aStr;
446 aStr << theName << "_" << theShapeIndex++;
447 theResultBody->generated(aSubShape, aStr.str());