Salome HOME
Adding Scale feature.
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Scale.cpp
1 // Copyright (C) 2014-201x CEA/DEN, EDF R&D
2
3 // File:        FeaturesPlugin_Scale.cpp
4 // Created:     13 Jan 2017
5 // Author:      Clarisse Genrault (CEA)
6
7 #include <FeaturesPlugin_Scale.h>
8
9 #include <GeomAlgoAPI_PointBuilder.h>
10
11 #include <ModelAPI_AttributeDouble.h>
12 #include <ModelAPI_AttributeSelectionList.h>
13 #include <ModelAPI_AttributeString.h>
14 #include <ModelAPI_ResultBody.h>
15 #include <ModelAPI_ResultPart.h>
16
17 //=================================================================================================
18 FeaturesPlugin_Scale::FeaturesPlugin_Scale()
19 {
20 }
21
22 //=================================================================================================
23 void FeaturesPlugin_Scale::initAttributes()
24 {
25   data()->addAttribute(FeaturesPlugin_Scale::CREATION_METHOD(),
26                        ModelAPI_AttributeString::typeId());
27
28   AttributeSelectionListPtr aSelection =
29     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
30     FeaturesPlugin_Scale::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
31
32   data()->addAttribute(FeaturesPlugin_Scale::CENTER_POINT_ID(),
33                        ModelAPI_AttributeSelection::typeId());
34
35   data()->addAttribute(FeaturesPlugin_Scale::SCALE_FACTOR_ID(),
36                        ModelAPI_AttributeDouble::typeId());
37
38   data()->addAttribute(FeaturesPlugin_Scale::SCALE_FACTOR_X_ID(),
39                        ModelAPI_AttributeDouble::typeId());
40   data()->addAttribute(FeaturesPlugin_Scale::SCALE_FACTOR_Y_ID(),
41                        ModelAPI_AttributeDouble::typeId());
42   data()->addAttribute(FeaturesPlugin_Scale::SCALE_FACTOR_Z_ID(),
43                        ModelAPI_AttributeDouble::typeId());
44 }
45
46 //=================================================================================================
47 void FeaturesPlugin_Scale::execute()
48 {
49   AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Scale::CREATION_METHOD());
50   std::string aMethodType = aMethodTypeAttr->value();
51
52   if (aMethodType == FeaturesPlugin_Scale::CREATION_METHOD_BY_FACTOR()) {
53     performScaleByFactor();
54   }
55
56   if (aMethodType == FeaturesPlugin_Scale::CREATION_METHOD_BY_DIMENSIONS()) {
57     performScaleByDimensions();
58   }
59 }
60
61 //=================================================================================================
62 void FeaturesPlugin_Scale::performScaleByFactor()
63 {
64   // Getting objects.
65   ListOfShape anObjects;
66   std::list<ResultPtr> aContextes;
67   AttributeSelectionListPtr anObjectsSelList =
68     selectionList(FeaturesPlugin_Scale::OBJECTS_LIST_ID());
69   if (anObjectsSelList->size() == 0) {
70     return;
71   }
72   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
73     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
74       anObjectsSelList->value(anObjectsIndex);
75     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
76     if(!anObject.get()) { // may be for not-activated parts
77       eraseResults();
78       return;
79     }
80     anObjects.push_back(anObject);
81     aContextes.push_back(anObjectAttr->context());
82   }
83
84   // Getting the center point
85   std::shared_ptr<GeomAPI_Pnt> aCenterPoint;
86   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
87     selection(FeaturesPlugin_Scale::CENTER_POINT_ID());
88   if (anObjRef.get() != NULL) {
89     GeomShapePtr aShape = anObjRef->value();
90     if (!aShape.get()) {
91       aShape = anObjRef->context()->shape();
92     }
93     if (aShape) {
94       aCenterPoint = GeomAlgoAPI_PointBuilder::point(aShape);
95     }
96   }
97
98   // Getting scale factor
99   double aScaleFactor = real(FeaturesPlugin_Scale::SCALE_FACTOR_ID())->value();
100
101   // Moving each object.
102   int aResultIndex = 0;
103   std::list<ResultPtr>::iterator aContext = aContextes.begin();
104   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
105         anObjectsIt++, aContext++) {
106     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
107     bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
108
109     // Setting result.
110     if (isPart) {
111       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
112       //aTrsf->setSymmetry(anAxis);
113       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
114       ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
115       aResultPart->setTrsf(*aContext, aTrsf);
116       setResult(aResultPart, aResultIndex);
117     } else {
118       GeomAlgoAPI_Scale aScaleAlgo(aBaseShape, aCenterPoint, aScaleFactor);
119
120       if (!aScaleAlgo.check()) {
121         setError(aScaleAlgo.getError());
122         return;
123       }
124
125       aScaleAlgo.build();
126
127       // Checking that the algorithm worked properly.
128       if(!aScaleAlgo.isDone()) {
129         static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
130         setError(aFeatureError);
131         break;
132       }
133       if(aScaleAlgo.shape()->isNull()) {
134         static const std::string aShapeError = "Error: Resulting shape is Null.";
135         setError(aShapeError);
136         break;
137       }
138       if(!aScaleAlgo.isValid()) {
139         std::string aFeatureError = "Error: Resulting shape is not valid.";
140         setError(aFeatureError);
141         break;
142       }
143
144       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
145       loadNamingDS(aScaleAlgo, aResultBody, aBaseShape);
146       setResult(aResultBody, aResultIndex);
147     }
148     aResultIndex++;
149   }
150
151   // Remove the rest results if there were produced in the previous pass.
152   removeResults(aResultIndex);
153 }
154
155 //=================================================================================================
156 void FeaturesPlugin_Scale::performScaleByDimensions()
157 {
158   // Getting objects.
159   ListOfShape anObjects;
160   std::list<ResultPtr> aContextes;
161   AttributeSelectionListPtr anObjectsSelList =
162     selectionList(FeaturesPlugin_Scale::OBJECTS_LIST_ID());
163   if (anObjectsSelList->size() == 0) {
164     return;
165   }
166   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
167     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
168       anObjectsSelList->value(anObjectsIndex);
169     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
170     if(!anObject.get()) { // may be for not-activated parts
171       eraseResults();
172       return;
173     }
174     anObjects.push_back(anObject);
175     aContextes.push_back(anObjectAttr->context());
176   }
177
178   // Getting the center point
179   std::shared_ptr<GeomAPI_Pnt> aCenterPoint;
180   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
181     selection(FeaturesPlugin_Scale::CENTER_POINT_ID());
182   if (anObjRef.get() != NULL) {
183     GeomShapePtr aShape = anObjRef->value();
184     if (!aShape.get()) {
185       aShape = anObjRef->context()->shape();
186     }
187     if (aShape) {
188       aCenterPoint = GeomAlgoAPI_PointBuilder::point(aShape);
189     }
190   }
191
192   // Getting dimensions
193   double aScaleFactorX = real(FeaturesPlugin_Scale::SCALE_FACTOR_X_ID())->value();
194   double aScaleFactorY = real(FeaturesPlugin_Scale::SCALE_FACTOR_Y_ID())->value();
195   double aScaleFactorZ = real(FeaturesPlugin_Scale::SCALE_FACTOR_Z_ID())->value();
196
197   // Moving each object.
198   int aResultIndex = 0;
199   std::list<ResultPtr>::iterator aContext = aContextes.begin();
200   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
201         anObjectsIt++, aContext++) {
202     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
203     bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
204
205     // Setting result.
206     if (isPart) {
207       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
208       //aTrsf->setSymmetry(anAxis);
209       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
210       ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
211       aResultPart->setTrsf(*aContext, aTrsf);
212       setResult(aResultPart, aResultIndex);
213     } else {
214       GeomAlgoAPI_Scale aScaleAlgo(aBaseShape, aCenterPoint,
215                                    aScaleFactorX, aScaleFactorY, aScaleFactorZ);
216
217       if (!aScaleAlgo.check()) {
218         setError(aScaleAlgo.getError());
219         return;
220       }
221
222       aScaleAlgo.build();
223
224       // Checking that the algorithm worked properly.
225       if(!aScaleAlgo.isDone()) {
226         static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
227         setError(aFeatureError);
228         break;
229       }
230       if(aScaleAlgo.shape()->isNull()) {
231         static const std::string aShapeError = "Error: Resulting shape is Null.";
232         setError(aShapeError);
233         break;
234       }
235       if(!aScaleAlgo.isValid()) {
236         std::string aFeatureError = "Error: Resulting shape is not valid.";
237         setError(aFeatureError);
238         break;
239       }
240
241       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
242       loadNamingDS(aScaleAlgo, aResultBody, aBaseShape);
243       setResult(aResultBody, aResultIndex);
244     }
245     aResultIndex++;
246   }
247
248   // Remove the rest results if there were produced in the previous pass.
249   removeResults(aResultIndex);
250 }
251
252 //=================================================================================================
253 void FeaturesPlugin_Scale::loadNamingDS(GeomAlgoAPI_Scale& theScaleAlgo,
254                                         std::shared_ptr<ModelAPI_ResultBody> theResultBody,
255                                         std::shared_ptr<GeomAPI_Shape> theBaseShape)
256 {
257   // Store and name the result.
258   theResultBody->storeModified(theBaseShape, theScaleAlgo.shape());
259
260   // Name the faces
261   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = theScaleAlgo.mapOfSubShapes();
262   int aReflectedTag = 1;
263   std::string aReflectedName = "Scaled";
264   theResultBody->loadAndOrientModifiedShapes(&theScaleAlgo,
265                                               theBaseShape, GeomAPI_Shape::FACE,
266                                               aReflectedTag, aReflectedName, *aSubShapes.get());
267 }