Salome HOME
GeomAlgoAPI_Prism now derived from GeomAlgoAPI_MakeSweep
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Extrusion.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:        FeaturesPlugin_Extrusion.cpp
4 // Created:     30 May 2014
5 // Author:      Vitaly SMETANNIKOV
6
7 #include "FeaturesPlugin_Extrusion.h"
8
9 #include <ModelAPI_Session.h>
10 #include <ModelAPI_Validator.h>
11 #include <ModelAPI_ResultConstruction.h>
12 #include <ModelAPI_ResultBody.h>
13 #include <ModelAPI_AttributeDouble.h>
14 #include <ModelAPI_AttributeSelection.h>
15 #include <ModelAPI_AttributeSelectionList.h>
16 #include <ModelAPI_AttributeString.h>
17
18 #include <GeomAlgoAPI_CompoundBuilder.h>
19 #include <GeomAlgoAPI_Prism.h>
20 #include <GeomAlgoAPI_ShapeTools.h>
21
22 //=================================================================================================
23 FeaturesPlugin_Extrusion::FeaturesPlugin_Extrusion()
24 {
25 }
26
27 //=================================================================================================
28 void FeaturesPlugin_Extrusion::initAttributes()
29 {
30   AttributeSelectionListPtr aSelection = 
31     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
32     LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
33   // extrusion works with faces always
34   aSelection->setSelectionType("FACE");
35
36   data()->addAttribute(CREATION_METHOD(), ModelAPI_AttributeString::typeId());
37
38   data()->addAttribute(TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
39   data()->addAttribute(FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
40
41   data()->addAttribute(TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
42   data()->addAttribute(TO_OFFSET_ID(), ModelAPI_AttributeDouble::typeId());
43
44   data()->addAttribute(FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
45   data()->addAttribute(FROM_OFFSET_ID(), ModelAPI_AttributeDouble::typeId());
46
47   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), TO_OBJECT_ID());
48   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FROM_OBJECT_ID());
49 }
50
51 //=================================================================================================
52 void FeaturesPlugin_Extrusion::execute()
53 {
54   // Getting faces.
55   ListOfShape aFacesList;
56   AttributeSelectionListPtr aFacesSelectionList = selectionList(LIST_ID());
57   for(int anIndex = 0; anIndex < aFacesSelectionList->size(); anIndex++) {
58     AttributeSelectionPtr aFaceSel = aFacesSelectionList->value(anIndex);
59     std::shared_ptr<GeomAPI_Shape> aFaceShape = aFaceSel->value();
60     if(aFaceShape.get() && !aFaceShape->isNull()) { // Getting face.
61       aFacesList.push_back(aFaceShape);
62     } else { // This may be the whole sketch result selected, check and get faces.
63       ResultPtr aContext = aFaceSel->context();
64       std::shared_ptr<GeomAPI_Shape> aContextShape = aContext->shape();
65       if(!aContextShape.get()) {
66         static const std::string aContextError = "The selection context is bad";
67         setError(aContextError);
68         return;
69       }
70       ResultConstructionPtr aConstruction = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContext);
71       if(!aConstruction.get()) {
72         static const std::string aFaceError = "Can not find basis for extrusion";
73         setError(aFaceError);
74         return;
75       }
76       int aFacesNum = aConstruction->facesNum();
77       for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
78         aFaceShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
79         aFacesList.push_back(aFaceShape);
80       }
81     }
82   }
83
84   // Getting sizes.
85   double aToSize = 0.0;
86   double aFromSize = 0.0;
87
88   if(string(CREATION_METHOD())->value() == "BySizes") {
89     aToSize = real(TO_SIZE_ID())->value();
90     aFromSize =  real(FROM_SIZE_ID())->value();
91   } else {
92     aToSize = real(TO_OFFSET_ID())->value();
93     aFromSize =  real(FROM_OFFSET_ID())->value();
94   }
95
96   // Getting bounding planes.
97   std::shared_ptr<GeomAPI_Shape> aToShape;
98   std::shared_ptr<GeomAPI_Shape> aFromShape;
99
100   if(string(CREATION_METHOD())->value() == "ByPlanesAndOffsets") {
101     std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = selection(TO_OBJECT_ID());
102     if(anObjRef.get() != NULL) {
103       aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
104       if(aToShape.get() == NULL && anObjRef->context().get() != NULL) {
105         aToShape =  anObjRef->context()->shape();
106       }
107     }
108     anObjRef = selection(FROM_OBJECT_ID());
109     if(anObjRef.get() != NULL) {
110       aFromShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
111       if(aFromShape.get() == NULL && anObjRef->context().get() != NULL) {
112         aFromShape = anObjRef->context()->shape();
113       }
114     }
115   }
116
117   // Searching faces with common edges.
118   ListOfShape aShells;
119   ListOfShape aFreeFaces;
120   std::shared_ptr<GeomAPI_Shape> aFacesCompound = GeomAlgoAPI_CompoundBuilder::compound(aFacesList);
121   GeomAlgoAPI_ShapeTools::combineShapes(aFacesCompound, GeomAPI_Shape::SHELL, aShells, aFreeFaces);
122   aShells.insert(aShells.end(), aFreeFaces.begin(), aFreeFaces.end());
123
124   // Generating result for each shell and face.
125   int aResultIndex = 0;
126   for(ListOfShape::const_iterator anIter = aShells.cbegin(); anIter != aShells.cend(); anIter++) {
127     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anIter;
128
129     GeomAlgoAPI_Prism aPrismAlgo(aBaseShape, aToShape, aToSize, aFromShape, aFromSize);
130     if(!aPrismAlgo.isDone()) {
131       static const std::string aPrismAlgoError = "Extrusion algorithm failed";
132       setError(aPrismAlgoError);
133       aResultIndex = 0;
134       break;
135     }
136
137     // Check if shape is valid
138     if(!aPrismAlgo.shape().get() || aPrismAlgo.shape()->isNull()) {
139       static const std::string aShapeError = "Resulting shape is Null";
140       setError(aShapeError);
141       aResultIndex = 0;
142       break;
143     }
144     if(!aPrismAlgo.isValid()) {
145       std::string aPrismAlgoError = "Warning: resulting shape is not valid";
146       setError(aPrismAlgoError);
147       aResultIndex = 0;
148       break;
149     }
150
151     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
152     loadNamingDS(aPrismAlgo, aResultBody, aBaseShape);
153     setResult(aResultBody, aResultIndex);
154     aResultIndex++;
155   }
156
157   removeResults(aResultIndex);
158 }
159
160 //=================================================================================================
161 void FeaturesPlugin_Extrusion::loadNamingDS(GeomAlgoAPI_Prism& thePrismAlgo,
162                                             std::shared_ptr<ModelAPI_ResultBody> theResultBody,
163                                             std::shared_ptr<GeomAPI_Shape> theBasis)
164 {
165   //load result
166   theResultBody->storeGenerated(theBasis, thePrismAlgo.shape());
167
168   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = thePrismAlgo.mapOfSubShapes();
169
170   //Insert lateral face : Face from Edge
171   const std::string aLatName = "LateralFace";
172   const int aLatTag = 1;
173   theResultBody->loadAndOrientGeneratedShapes(&thePrismAlgo, theBasis, GeomAPI_Shape::EDGE, aLatTag, aLatName, *aSubShapes);
174
175   //Insert to faces
176   const std::string aToName = "ToFace";
177   int aToTag = 2;
178   const ListOfShape& aToFaces = thePrismAlgo.toFaces();
179   for(ListOfShape::const_iterator anIt = aToFaces.cbegin(); anIt != aToFaces.cend(); anIt++) {
180     std::shared_ptr<GeomAPI_Shape> aToFace = *anIt;
181     if(aSubShapes->isBound(aToFace)) {
182       aToFace = aSubShapes->find(aToFace);
183     }
184     theResultBody->generated(aToFace, aToName, aToTag++);
185   }
186
187   //Insert from faces
188   const std::string aFromName = "FromFace";
189   int aFromTag = aToTag > 10000 ? aToTag : 10000;
190   const ListOfShape& aFromFaces = thePrismAlgo.fromFaces();
191   for(ListOfShape::const_iterator anIt = aFromFaces.cbegin(); anIt != aFromFaces.cend(); anIt++) {
192     std::shared_ptr<GeomAPI_Shape> aFromFace = *anIt;
193     if(aSubShapes->isBound(aFromFace)) {
194       aFromFace = aSubShapes->find(aFromFace);
195     }
196     theResultBody->generated(aFromFace, aFromName, aFromTag++);
197   }
198 }