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