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