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