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