Salome HOME
7fd7c13017cb9eed0c3d886f2081a3712240f43e
[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 #include <ModelAPI_Session.h>
9 #include <ModelAPI_Validator.h>
10 #include <ModelAPI_Document.h>
11 #include <ModelAPI_Data.h>
12 #include <ModelAPI_ResultConstruction.h>
13 #include <ModelAPI_ResultBody.h>
14 #include <ModelAPI_AttributeDouble.h>
15 #include <ModelAPI_AttributeSelection.h>
16 #include <ModelAPI_AttributeSelectionList.h>
17 #include <ModelAPI_AttributeBoolean.h>
18 #include <ModelAPI_AttributeString.h>
19 #include <ModelAPI_AttributeReference.h>
20 #include <GeomAPI_Pln.h>
21 #include <GeomAPI_XYZ.h>
22 #include <GeomAlgoAPI_Extrusion.h>
23 #include <GeomAlgoAPI_FaceBuilder.h>
24 #include <GeomAlgoAPI_Prism.h>
25
26 using namespace std;
27 #define _LATERAL_TAG 1
28 #define _FIRST_TAG 2
29 #define _LAST_TAG 3
30 #define EDGE 6
31
32 FeaturesPlugin_Extrusion::FeaturesPlugin_Extrusion()
33 {
34 }
35
36 void FeaturesPlugin_Extrusion::initAttributes()
37 {
38   AttributeSelectionListPtr aSelection = 
39     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
40     FeaturesPlugin_Extrusion::LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
41   // extrusion works with faces always
42   aSelection->setSelectionType("FACE");
43
44   data()->addAttribute(FeaturesPlugin_Extrusion::TO_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
45   data()->addAttribute(FeaturesPlugin_Extrusion::FROM_SIZE_ID(), ModelAPI_AttributeDouble::typeId());
46
47   data()->addAttribute(FeaturesPlugin_Extrusion::FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
48   data()->addAttribute(FeaturesPlugin_Extrusion::TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
49
50   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
51   ModelAPI_Session::get()->validators()->registerNotObligatory(getKind(), FeaturesPlugin_Extrusion::TO_OBJECT_ID());
52 }
53
54 void FeaturesPlugin_Extrusion::execute()
55 {
56   AttributeSelectionListPtr aFaceRefs = selectionList(FeaturesPlugin_Extrusion::LIST_ID());
57
58   std::shared_ptr<GeomAPI_Shape> aFromShape;
59   std::shared_ptr<GeomAPI_Shape> aToShape;
60
61   // Getting bounding planes.
62   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef = selection(FeaturesPlugin_Extrusion::FROM_OBJECT_ID());
63   if (anObjRef) {
64     aFromShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
65   }
66   anObjRef = selection(FeaturesPlugin_Extrusion::TO_OBJECT_ID());
67   if (anObjRef) {
68     aToShape = std::dynamic_pointer_cast<GeomAPI_Shape>(anObjRef->value());
69   }
70
71   // Getting sizes.
72   double aFromSize = real(FeaturesPlugin_Extrusion::FROM_SIZE_ID())->value();
73   double aToSize = real(FeaturesPlugin_Extrusion::TO_SIZE_ID())->value();
74
75   // for each selected face generate a result
76   int anIndex = 0, aResultIndex = 0;
77   for(; anIndex < aFaceRefs->size(); anIndex++) {
78     std::shared_ptr<ModelAPI_AttributeSelection> aFaceRef = aFaceRefs->value(anIndex);
79     ResultPtr aContextRes = aFaceRef->context();
80     std::shared_ptr<GeomAPI_Shape> aContext = aContextRes->shape();
81     if (!aContext.get()) {
82       static const std::string aContextError = "The selection context is bad";
83       setError(aContextError);
84       break;
85     }
86
87     std::shared_ptr<GeomAPI_Shape> aValueFace = aFaceRef->value();
88     int aFacesNum = -1; // this mean that "aFace" is used
89     ResultConstructionPtr aConstruction =
90       std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(aContextRes);
91     if (!aValueFace.get()) { // this may be the whole sketch result selected, check and get faces
92       if (aConstruction.get()) {
93         aFacesNum = aConstruction->facesNum();
94       } else {
95         static const std::string aFaceError = "Can not find basis for extrusion";
96         setError(aFaceError);
97         break;
98       }
99     }
100
101     for(int aFaceIndex = 0; aFaceIndex < aFacesNum || aFacesNum == -1; aFaceIndex++) {
102       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
103       std::shared_ptr<GeomAPI_Shape> aBaseShape;
104       if (aFacesNum == -1) {
105         aBaseShape = aValueFace;
106       } else {
107         aBaseShape = std::dynamic_pointer_cast<GeomAPI_Shape>(aConstruction->face(aFaceIndex));
108       }
109
110       // If bounding faces was not set creating them.
111       std::shared_ptr<GeomAPI_Face>  aBaseFace(new GeomAPI_Face(aBaseShape));
112       std::shared_ptr<GeomAPI_Pln>   aBasePln = aBaseFace->getPlane();
113       std::shared_ptr<GeomAPI_Dir>   aBaseDir = aBasePln->direction();
114       std::shared_ptr<GeomAPI_Pnt>   aBaseLoc = aBasePln->location();
115       std::shared_ptr<GeomAPI_Shape> aBasePlane = GeomAlgoAPI_FaceBuilder::planarFace(aBaseLoc, aBaseDir);
116
117       std::shared_ptr<GeomAPI_Shape> aBoundingFromShape = aFromShape ? aFromShape : aBasePlane;
118       std::shared_ptr<GeomAPI_Shape> aBoundingToShape   = aToShape   ? aToShape   : aBasePlane;
119
120       // Moving bounding faces according to "from" and "to" sizes.
121       std::shared_ptr<GeomAPI_Face> aFromFace(new GeomAPI_Face(aBoundingFromShape));
122       std::shared_ptr<GeomAPI_Pln>  aFromPln = aFromFace->getPlane();
123       std::shared_ptr<GeomAPI_Pnt>  aFromLoc = aFromPln->location();
124       std::shared_ptr<GeomAPI_Dir>  aFromDir = aFromPln->direction();
125
126       std::shared_ptr<GeomAPI_Face> aToFace(new GeomAPI_Face(aBoundingToShape));
127       std::shared_ptr<GeomAPI_Pln>  aToPln = aToFace->getPlane();
128       std::shared_ptr<GeomAPI_Pnt>  aToLoc = aToPln->location();
129       std::shared_ptr<GeomAPI_Dir>  aToDir = aToPln->direction();
130
131       bool aSign = aFromLoc->xyz()->dot(aBaseDir->xyz()) > aToLoc->xyz()->dot(aBaseDir->xyz());
132
133       std::shared_ptr<GeomAPI_Pnt> aFromPnt(new GeomAPI_Pnt(aFromLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? aFromSize : -aFromSize))));
134       aBoundingFromShape = GeomAlgoAPI_FaceBuilder::planarFace(aFromPnt, aFromDir);
135
136       std::shared_ptr<GeomAPI_Pnt> aToPnt(new GeomAPI_Pnt(aToLoc->xyz()->added(aBaseDir->xyz()->multiplied(aSign ? -aToSize : aToSize))));
137       aBoundingToShape = GeomAlgoAPI_FaceBuilder::planarFace(aToPnt, aToDir);
138
139       //GeomAlgoAPI_Extrusion aFeature(aFace, aFromSize);
140       GeomAlgoAPI_Prism aFeature(aBaseShape, aBoundingFromShape, aBoundingToShape);
141       if(!aFeature.isDone()) {
142         static const std::string aFeatureError = "Extrusion algorithm failed";
143         setError(aFeatureError);
144         break;
145       }
146
147       // Check if shape is valid
148       if(aFeature.shape()->isNull()) {
149         static const std::string aShapeError = "Resulting shape is Null";
150         setError(aShapeError);
151         break;
152       }
153       if(!aFeature.isValid()) {
154         std::string aFeatureError = "Warning: resulting shape is not valid";
155         setError(aFeatureError);
156         break;
157       }
158       //LoadNamingDS
159       LoadNamingDS(aFeature, aResultBody, aBaseShape, aContext);
160
161       setResult(aResultBody, aResultIndex);
162       aResultIndex++;
163
164       if (aFacesNum == -1)
165         break;
166     }
167   }
168   // remove the rest results if there were produced in the previous pass
169   removeResults(aResultIndex);
170 }
171
172 //============================================================================
173 void FeaturesPlugin_Extrusion::LoadNamingDS(GeomAlgoAPI_Prism& theFeature,
174                                             std::shared_ptr<ModelAPI_ResultBody> theResultBody,
175                                             std::shared_ptr<GeomAPI_Shape> theBasis,
176                                             std::shared_ptr<GeomAPI_Shape> theContext)
177 {
178   //load result
179   if(theBasis->isEqual(theContext))
180     theResultBody->store(theFeature.shape());
181   else
182     theResultBody->storeGenerated(theBasis, theFeature.shape());
183
184   GeomAPI_DataMapOfShapeShape* aSubShapes = new GeomAPI_DataMapOfShapeShape();
185   theFeature.mapOfShapes(*aSubShapes);
186
187   //Insert lateral face : Face from Edge
188   std::string aLatName = "LateralFace";
189   theResultBody->loadAndOrientGeneratedShapes(theFeature.makeShape(), theBasis, EDGE,_LATERAL_TAG, aLatName, *aSubShapes);
190
191   //Insert bottom face
192   std::string aBotName = "BottomFace";
193   std::shared_ptr<GeomAPI_Shape> aBottomFace = theFeature.firstShape();
194   if(!aBottomFace->isNull()) {
195     if(aSubShapes->isBound(aBottomFace)) {
196       aBottomFace = aSubShapes->find(aBottomFace);
197     }
198     theResultBody->generated(aBottomFace, aBotName, _FIRST_TAG);
199   }
200
201   //Insert top face
202   std::string aTopName = "TopFace";
203   std::shared_ptr<GeomAPI_Shape> aTopFace = theFeature.lastShape();
204   if (!aTopFace->isNull()) {
205     if (aSubShapes->isBound(aTopFace)) {
206       aTopFace = aSubShapes->find(aTopFace);
207     }
208     theResultBody->generated(aTopFace, aTopName, _LAST_TAG);
209   }
210 }