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