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