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