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