Salome HOME
Merge branch 'master' into cgt/devCEA
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Symmetry.cpp
1 // Copyright (C) 2014-2016 CEA/DEN, EDF R&D
2
3 // File:        FeaturesPlugin_Symmetry.cpp
4 // Created:     30 Nov 2016
5 // Author:      Clarisse Genrault (CEA)
6
7 #include <FeaturesPlugin_Symmetry.h>
8
9 #include <ModelAPI_AttributeSelectionList.h>
10 #include <ModelAPI_AttributeString.h>
11 #include <ModelAPI_ResultBody.h>
12
13 #include <GeomAPI_Edge.h>
14 #include <GeomAPI_Face.h>
15 #include <GeomAPI_Lin.h>
16 #include <GeomAPI_Pln.h>
17
18 #include <GeomAlgoAPI_PointBuilder.h>
19
20 #include <ModelAPI_ResultPart.h>
21
22 //=================================================================================================
23 FeaturesPlugin_Symmetry::FeaturesPlugin_Symmetry()
24 {
25 }
26
27 //=================================================================================================
28 void FeaturesPlugin_Symmetry::initAttributes()
29 {
30   data()->addAttribute(FeaturesPlugin_Symmetry::CREATION_METHOD(),
31                        ModelAPI_AttributeString::typeId());
32
33   AttributeSelectionListPtr aSelection =
34     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
35     FeaturesPlugin_Symmetry::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
36
37   data()->addAttribute(FeaturesPlugin_Symmetry::POINT_OBJECT_ID(),
38                        ModelAPI_AttributeSelection::typeId());
39
40   data()->addAttribute(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID(),
41                        ModelAPI_AttributeSelection::typeId());
42
43   data()->addAttribute(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID(),
44                        ModelAPI_AttributeSelection::typeId());
45 }
46
47 //=================================================================================================
48 void FeaturesPlugin_Symmetry::execute()
49 {
50   AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Symmetry::CREATION_METHOD());
51   std::string aMethodType = aMethodTypeAttr->value();
52
53   if (aMethodType == CREATION_METHOD_BY_POINT()) {
54     performSymmetryByPoint();
55   }
56
57   if (aMethodType == CREATION_METHOD_BY_AXIS()) {
58     performSymmetryByAxis();
59   }
60
61   if (aMethodType == CREATION_METHOD_BY_PLANE()) {
62     performSymmetryByPlane();
63   }
64 }
65
66 //=================================================================================================
67 void FeaturesPlugin_Symmetry::performSymmetryByPoint()
68 {
69   // Getting objects.
70   ListOfShape anObjects;
71   std::list<ResultPtr> aContextes;
72   AttributeSelectionListPtr anObjectsSelList =
73     selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID());
74   if (anObjectsSelList->size() == 0) {
75     return;
76   }
77   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
78     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
79       anObjectsSelList->value(anObjectsIndex);
80     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
81     if(!anObject.get()) { // may be for not-activated parts
82       eraseResults();
83       return;
84     }
85     anObjects.push_back(anObject);
86     aContextes.push_back(anObjectAttr->context());
87   }
88
89   //Getting point.
90   std::shared_ptr<GeomAPI_Pnt> aPoint;
91   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
92     selection(FeaturesPlugin_Symmetry::POINT_OBJECT_ID());
93   if (anObjRef.get() != NULL) {
94     GeomShapePtr aShape1 = anObjRef->value();
95     if (!aShape1.get()) {
96       aShape1 = anObjRef->context()->shape();
97     }
98     if (aShape1) {
99       aPoint = GeomAlgoAPI_PointBuilder::point(aShape1);
100     }
101   }
102
103   // Moving each object.
104   int aResultIndex = 0;
105   std::list<ResultPtr>::iterator aContext = aContextes.begin();
106   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
107         anObjectsIt++, aContext++) {
108     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
109     bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
110
111     // Setting result.
112     if (isPart) {
113       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
114       aTrsf->setSymmetry(aPoint);
115       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
116       ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
117       aResultPart->setTrsf(*aContext, aTrsf);
118       setResult(aResultPart, aResultIndex);
119     } else {
120       GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPoint);
121
122       if (!aSymmetryAlgo.check()) {
123         setError(aSymmetryAlgo.getError());
124         return;
125       }
126
127       aSymmetryAlgo.build();
128
129       // Checking that the algorithm worked properly.
130       if(!aSymmetryAlgo.isDone()) {
131         static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
132         setError(aFeatureError);
133         break;
134       }
135       if(aSymmetryAlgo.shape()->isNull()) {
136         static const std::string aShapeError = "Error: Resulting shape is Null.";
137         setError(aShapeError);
138         break;
139       }
140       if(!aSymmetryAlgo.isValid()) {
141         std::string aFeatureError = "Error: Resulting shape is not valid.";
142         setError(aFeatureError);
143         break;
144       }
145
146       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
147       loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape);
148       setResult(aResultBody, aResultIndex);
149     }
150     aResultIndex++;
151   }
152
153   // Remove the rest results if there were produced in the previous pass.
154   removeResults(aResultIndex);
155 }
156
157 //=================================================================================================
158 void FeaturesPlugin_Symmetry::performSymmetryByAxis()
159 {
160   // Getting objects.
161   ListOfShape anObjects;
162   std::list<ResultPtr> aContextes;
163   AttributeSelectionListPtr anObjectsSelList =
164     selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID());
165   if (anObjectsSelList->size() == 0) {
166     return;
167   }
168   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
169     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
170       anObjectsSelList->value(anObjectsIndex);
171     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
172     if(!anObject.get()) { // may be for not-activated parts
173       eraseResults();
174       return;
175     }
176     anObjects.push_back(anObject);
177     aContextes.push_back(anObjectAttr->context());
178   }
179
180   //Getting axis.
181   std::shared_ptr<GeomAPI_Ax1> anAxis;
182   std::shared_ptr<GeomAPI_Edge> anEdge;
183   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
184     selection(FeaturesPlugin_Symmetry::AXIS_OBJECT_ID());
185   if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
186     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
187   } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
188              anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
189     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
190   }
191   if(anEdge) {
192     anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
193                                                           anEdge->line()->direction()));
194   }
195
196   // Moving each object.
197   int aResultIndex = 0;
198   std::list<ResultPtr>::iterator aContext = aContextes.begin();
199   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
200         anObjectsIt++, aContext++) {
201     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
202     bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
203
204     // Setting result.
205     if (isPart) {
206       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
207       aTrsf->setSymmetry(anAxis);
208       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
209       ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
210       aResultPart->setTrsf(*aContext, aTrsf);
211       setResult(aResultPart, aResultIndex);
212     } else {
213       GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, anAxis);
214
215       if (!aSymmetryAlgo.check()) {
216         setError(aSymmetryAlgo.getError());
217         return;
218       }
219
220       aSymmetryAlgo.build();
221
222       // Checking that the algorithm worked properly.
223       if(!aSymmetryAlgo.isDone()) {
224         static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
225         setError(aFeatureError);
226         break;
227       }
228       if(aSymmetryAlgo.shape()->isNull()) {
229         static const std::string aShapeError = "Error: Resulting shape is Null.";
230         setError(aShapeError);
231         break;
232       }
233       if(!aSymmetryAlgo.isValid()) {
234         std::string aFeatureError = "Error: Resulting shape is not valid.";
235         setError(aFeatureError);
236         break;
237       }
238
239       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
240       loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape);
241       setResult(aResultBody, aResultIndex);
242     }
243     aResultIndex++;
244   }
245
246   // Remove the rest results if there were produced in the previous pass.
247   removeResults(aResultIndex);
248 }
249
250 //=================================================================================================
251 void FeaturesPlugin_Symmetry::performSymmetryByPlane()
252 {
253   // Getting objects.
254   ListOfShape anObjects;
255   std::list<ResultPtr> aContextes;
256   AttributeSelectionListPtr anObjectsSelList =
257     selectionList(FeaturesPlugin_Symmetry::OBJECTS_LIST_ID());
258   if (anObjectsSelList->size() == 0) {
259     return;
260   }
261   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
262     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
263       anObjectsSelList->value(anObjectsIndex);
264     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
265     if(!anObject.get()) { // may be for not-activated parts
266       eraseResults();
267       return;
268     }
269     anObjects.push_back(anObject);
270     aContextes.push_back(anObjectAttr->context());
271   }
272
273   //Getting axis.
274   std::shared_ptr<GeomAPI_Ax2> aPlane;
275   std::shared_ptr<GeomAPI_Pln> aPln;
276   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
277     selection(FeaturesPlugin_Symmetry::PLANE_OBJECT_ID());
278   if(anObjRef && anObjRef->value() && anObjRef->value()->isFace()) {
279     aPln = std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->value()))->getPlane();
280   }
281   else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
282              anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
283     aPln =
284       std::shared_ptr<GeomAPI_Face>(new GeomAPI_Face(anObjRef->context()->shape()))->getPlane();
285   }
286   if(aPln) {
287     aPlane = std::shared_ptr<GeomAPI_Ax2>(new GeomAPI_Ax2(aPln->location(),
288                                                           aPln->direction()));
289   }
290
291   // Moving each object.
292   int aResultIndex = 0;
293   std::list<ResultPtr>::iterator aContext = aContextes.begin();
294   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
295         anObjectsIt++, aContext++) {
296     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
297     bool isPart = (*aContext)->groupName() == ModelAPI_ResultPart::group();
298
299     // Setting result.
300     if (isPart) {
301       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
302       aTrsf->setSymmetry(aPlane);
303       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
304       ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
305       aResultPart->setTrsf(*aContext, aTrsf);
306       setResult(aResultPart, aResultIndex);
307     } else {
308       GeomAlgoAPI_Symmetry aSymmetryAlgo(aBaseShape, aPlane);
309
310       if (!aSymmetryAlgo.check()) {
311         setError(aSymmetryAlgo.getError());
312         return;
313       }
314
315       aSymmetryAlgo.build();
316
317       // Checking that the algorithm worked properly.
318       if(!aSymmetryAlgo.isDone()) {
319         static const std::string aFeatureError = "Error: Symmetry algorithm failed.";
320         setError(aFeatureError);
321         break;
322       }
323       if(aSymmetryAlgo.shape()->isNull()) {
324         static const std::string aShapeError = "Error: Resulting shape is Null.";
325         setError(aShapeError);
326         break;
327       }
328       if(!aSymmetryAlgo.isValid()) {
329         std::string aFeatureError = "Error: Resulting shape is not valid.";
330         setError(aFeatureError);
331         break;
332       }
333
334       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
335       loadNamingDS(aSymmetryAlgo, aResultBody, aBaseShape);
336       setResult(aResultBody, aResultIndex);
337     }
338     aResultIndex++;
339   }
340
341   // Remove the rest results if there were produced in the previous pass.
342   removeResults(aResultIndex);
343 }
344
345 //=================================================================================================
346 void FeaturesPlugin_Symmetry::loadNamingDS(GeomAlgoAPI_Symmetry& theSymmetryAlgo,
347                                            std::shared_ptr<ModelAPI_ResultBody> theResultBody,
348                                            std::shared_ptr<GeomAPI_Shape> theBaseShape)
349 {
350   // Store and name the result.
351   theResultBody->storeModified(theBaseShape, theSymmetryAlgo.shape());
352
353   // Name the faces
354   std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = theSymmetryAlgo.mapOfSubShapes();
355   int aReflectedTag = 1;
356   std::string aReflectedName = "Symmetried";
357   theResultBody->loadAndOrientModifiedShapes(&theSymmetryAlgo,
358                                               theBaseShape, GeomAPI_Shape::FACE,
359                                               aReflectedTag, aReflectedName, *aSubShapes.get());
360 }