Salome HOME
Fix for the issue #2753 : error when dump/load script
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_MultiRotation.cpp
1 // Copyright (C) 2014-201x CEA/DEN, EDF R&D
2
3 // File:        FeaturesPlugin_MultiRotation.cpp
4 // Created:     30 Jan 2017
5 // Author:      Clarisse Genrault (CEA)
6
7 #include <FeaturesPlugin_MultiRotation.h>
8
9 #include <GeomAlgoAPI_CompoundBuilder.h>
10 #include <GeomAlgoAPI_ShapeTools.h>
11 #include <GeomAlgoAPI_Translation.h>
12
13 #include <GeomAPI_ShapeExplorer.h>
14
15 #include <GeomAPI_Ax1.h>
16 #include <GeomAPI_Edge.h>
17 #include <GeomAPI_Lin.h>
18 #include <GeomAPI_ShapeIterator.h>
19 #include <GeomAPI_Trsf.h>
20
21 #include <ModelAPI_AttributeDouble.h>
22 #include <ModelAPI_AttributeInteger.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_ResultPart.h>
27
28 #include <math.h>
29 #include <iostream>
30
31 //=================================================================================================
32 FeaturesPlugin_MultiRotation::FeaturesPlugin_MultiRotation()
33 {
34 }
35
36 //=================================================================================================
37 void FeaturesPlugin_MultiRotation::initAttributes()
38 {
39   AttributeSelectionListPtr aSelection =
40     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
41     FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID(),
42     ModelAPI_AttributeSelectionList::typeId()));
43
44   data()->addAttribute(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID(),
45                        ModelAPI_AttributeSelection::typeId());
46   data()->addAttribute(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID(),
47                        ModelAPI_AttributeString::typeId());
48   data()->addAttribute(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID(),
49                        ModelAPI_AttributeDouble::typeId());
50   data()->addAttribute(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID(),
51                        ModelAPI_AttributeInteger::typeId());
52
53   /*data()->addAttribute(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID(),
54                        ModelAPI_AttributeString::typeId());
55   data()->addAttribute(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID(),
56                        ModelAPI_AttributeDouble::typeId());
57   data()->addAttribute(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID(),
58                        ModelAPI_AttributeInteger::typeId());*/
59 }
60
61 //=================================================================================================
62 void FeaturesPlugin_MultiRotation::execute()
63 {
64   /*std::string useRadialDir = string(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID())->value();
65   if (useRadialDir.empty()) {
66     performRotation1D();
67   } else {
68     performRotation2D();
69   }*/
70   performRotation1D();
71 }
72
73 //=================================================================================================
74 void FeaturesPlugin_MultiRotation::performRotation1D()
75 {
76   // Getting objects.
77   ListOfShape anObjects;
78   std::list<ResultPtr> aContextes;
79   AttributeSelectionListPtr anObjectsSelList =
80     selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
81   if (anObjectsSelList->size() == 0) {
82     return;
83   }
84   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
85     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
86       anObjectsSelList->value(anObjectsIndex);
87     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
88     if(!anObject.get()) { // may be for not-activated parts
89       return;
90     }
91     anObjects.push_back(anObject);
92     aContextes.push_back(anObjectAttr->context());
93   }
94
95   //Getting axis.
96   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
97   AttributeSelectionPtr anObjRef = selection(AXIS_ANGULAR_ID());
98   GeomShapePtr aShape = anObjRef->value();
99   if (!aShape.get()) {
100     if (anObjRef->context().get()) {
101       aShape = anObjRef->context()->shape();
102     }
103   }
104   if (!aShape.get()) {
105     setError(aSelectionError);
106     return;
107   }
108
109   GeomEdgePtr anEdge;
110   if (aShape->isEdge())
111   {
112     anEdge = aShape->edge();
113   }
114   else if (aShape->isCompound())
115   {
116     GeomAPI_ShapeIterator anIt(aShape);
117     anEdge = anIt.current()->edge();
118   }
119   else
120   {
121     setError(aSelectionError);
122     return;
123   }
124
125   if (!anEdge.get())
126   {
127     setError(aSelectionError);
128     return;
129   }
130
131   std::shared_ptr<GeomAPI_Ax1> anAxis(new GeomAPI_Ax1(anEdge->line()->location(),
132                                                       anEdge->line()->direction()));
133
134   // Getting number of copies.
135   int nbCopies =
136     integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID())->value();
137
138   if (nbCopies <=0) {
139     std::string aFeatureError = "Multirotation builder ";
140     aFeatureError+=":: the number of copies for the angular direction is null or negative.";
141     setError(aFeatureError);
142     return;
143   }
144
145   // Getting angle
146   double anAngle;
147   std::string useAngularStep =
148     string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value();
149   if (!useAngularStep.empty()) {
150     anAngle = real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID())->value();
151   } else {
152     anAngle = 360./nbCopies;
153   }
154
155   // Moving each object.
156   int aResultIndex = 0;
157   std::list<ResultPtr>::iterator aContext = aContextes.begin();
158   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
159         anObjectsIt++, aContext++) {
160     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
161     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
162
163     // Setting result.
164     if (isPart) {
165       ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
166       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
167       for (int i=0; i<nbCopies; i++) {
168         aTrsf->setRotation(anAxis, i*anAngle);
169         ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
170         aResultPart->setTrsf(*aContext, aTrsf);
171         setResult(aResultPart, aResultIndex);
172         aResultIndex++;
173       }
174     } else {
175       ListOfShape aListOfShape;
176       std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
177
178       for (int i=0; i<nbCopies; i++) {
179         std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
180           new GeomAlgoAPI_Rotation(aBaseShape, anAxis, i*anAngle));
181
182         if (!aRotationnAlgo->check()) {
183           setError(aRotationnAlgo->getError());
184           break;
185         }
186
187         aRotationnAlgo->build();
188
189         // Checking that the algorithm worked properly.
190         if (!aRotationnAlgo->isDone()) {
191           static const std::string aFeatureError = "Error : Multitranslation algorithm failed.";
192           setError(aFeatureError);
193           break;
194         }
195         if (aRotationnAlgo->shape()->isNull()) {
196           static const std::string aShapeError = "Error : Resulting shape is null.";
197           setError(aShapeError);
198           break;
199         }
200         if (!aRotationnAlgo->isValid()) {
201           static const std::string aFeatureError = "Error : Resulting shape in not valid.";
202           setError(aFeatureError);
203           break;
204         }
205         aListOfShape.push_back(aRotationnAlgo->shape());
206         aListOfRotationAlgo.push_back(aRotationnAlgo);
207       }
208       std::shared_ptr<GeomAPI_Shape> aCompound =
209         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
210       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
211       aResultBody->storeModified(aBaseShape, aCompound);
212       loadNamingDS(aListOfRotationAlgo, aResultBody, aBaseShape);
213
214       setResult(aResultBody, aResultIndex);
215     }
216     aResultIndex++;
217   }
218
219   // Remove the rest results if there were produced in the previous pass.
220   removeResults(aResultIndex);
221 }
222
223 //=================================================================================================
224 void FeaturesPlugin_MultiRotation::performRotation2D()
225 {
226   // Getting objects.
227   ListOfShape anObjects;
228   std::list<ResultPtr> aContextes;
229   AttributeSelectionListPtr anObjectsSelList =
230     selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
231   if (anObjectsSelList->size() == 0) {
232     return;
233   }
234   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
235     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
236       anObjectsSelList->value(anObjectsIndex);
237     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
238     if(!anObject.get()) { // may be for not-activated parts
239       return;
240     }
241     anObjects.push_back(anObject);
242     aContextes.push_back(anObjectAttr->context());
243   }
244
245   //Getting axis.
246   std::shared_ptr<GeomAPI_Ax1> anAxis;
247   std::shared_ptr<GeomAPI_Edge> anEdge;
248   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
249     selection(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID());
250   if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
251     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
252   } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
253              anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
254     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
255   }
256   if(anEdge) {
257     anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
258                                                           anEdge->line()->direction()));
259   }
260
261   // Getting number of copies int he angular direction.
262   int nbAngular =
263     integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID())->value();
264
265   if (nbAngular <=0) {
266     std::string aFeatureError = "Multirotation builder ";
267     aFeatureError+=":: the number of copies for the angular direction is null or negative.";
268     setError(aFeatureError);
269     return;
270   }
271
272   // Getting number of copies int he radial direction.
273   int nbRadial =
274     integer(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID())->value();
275
276   if (nbRadial <=0) {
277     std::string aFeatureError = "Multirotation builder ";
278     aFeatureError+=":: the number of copies for the radial direction is null or negative.";
279     setError(aFeatureError);
280     return;
281   }
282
283   // Getting angle
284   double anAngle;
285   std::string useAngularStep =
286     string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value();
287   if (!useAngularStep.empty()) {
288     anAngle = real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID())->value();
289   } else {
290     anAngle = 360./nbAngular;
291   }
292
293   // Getting step
294   double aStep = real(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID())->value();
295
296   // Moving each object.
297   int aResultIndex = 0;
298   std::list<ResultPtr>::iterator aContext = aContextes.begin();
299   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
300         anObjectsIt++, aContext++) {
301     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
302     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
303
304     std::shared_ptr<GeomAPI_Dir> aDir =
305       GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(aBaseShape, anAxis);
306     double x = aDir->x();
307     double y = aDir->y();
308     double z = aDir->z();
309     double norm = sqrt(x*x+y*y+z*z);
310
311     // Setting result.
312     if (isPart) {
313       /*ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
314       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
315       for (int j=0; j<aSecondNbCopies; j++) {
316         for (int i=0; i<aFirstNbCopies; i++) {
317           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
318           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
319           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
320           aTrsf->setTranslation(dx, dy, dz);
321           ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
322           aResultPart->setTrsf(*aContext, aTrsf);
323           setResult(aResultPart, aResultIndex);
324           aResultIndex++;
325         }
326       }*/
327     } else {
328       ListOfShape aListOfShape;
329       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
330       std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
331       for (int j=0; j<nbRadial; j++) {
332         // Translation
333         double dx = j*aStep*x/norm;
334         double dy = j*aStep*y/norm;
335         double dz = j*aStep*z/norm;
336         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
337           new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
338
339         if (!aTranslationAlgo->check()) {
340           setError(aTranslationAlgo->getError());
341           break;
342         }
343
344         aTranslationAlgo->build();
345
346         // Checking that the algorithm worked properly.
347         if (!aTranslationAlgo->isDone()) {
348           static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
349           setError(aFeatureError);
350           break;
351         }
352         if (aTranslationAlgo->shape()->isNull()) {
353           static const std::string aShapeError = "Error : Resulting shape is null.";
354           setError(aShapeError);
355           break;
356         }
357         if (!aTranslationAlgo->isValid()) {
358           static const std::string aFeatureError = "Error : Resulting shape in not valid.";
359           setError(aFeatureError);
360           break;
361         }
362         aListOfShape.push_back(aTranslationAlgo->shape());
363         aListOfTranslationAlgo.push_back(aTranslationAlgo);
364         for (int i=1; i<nbAngular; i++) {
365           std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
366             new GeomAlgoAPI_Rotation(aTranslationAlgo->shape(), anAxis, i*anAngle));
367           if (!aRotationnAlgo->check()) {
368             setError(aTranslationAlgo->getError());
369             break;
370           }
371           aRotationnAlgo->build();// Checking that the algorithm worked properly.
372           if (!aRotationnAlgo->isDone()) {
373             static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
374             setError(aFeatureError);
375             break;
376           }
377           if (aRotationnAlgo->shape()->isNull()) {
378             static const std::string aShapeError = "Error : Resulting shape is null.";
379             setError(aShapeError);
380             break;
381           }
382           if (!aRotationnAlgo->isValid()) {
383             static const std::string aFeatureError = "Error : Resulting shape in not valid.";
384             setError(aFeatureError);
385             break;
386           }
387           aListOfShape.push_back(aRotationnAlgo->shape());
388           aListOfRotationAlgo.push_back(aRotationnAlgo);
389         }
390       }
391       std::shared_ptr<GeomAPI_Shape> aCompound =
392         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
393       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
394       aResultBody->storeModified(aBaseShape, aCompound);
395
396       loadNamingDS2(aListOfTranslationAlgo, aResultBody, aBaseShape);
397       loadNamingDS3(aListOfRotationAlgo, aResultBody, aBaseShape, nbRadial);
398       setResult(aResultBody, aResultIndex);
399     }
400     aResultIndex++;
401   }
402
403   // Remove the rest results if there were produced in the previous pass.
404   removeResults(aResultIndex);
405 }
406
407 //=================================================================================================
408 void FeaturesPlugin_MultiRotation::loadNamingDS2(
409     std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
410     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
411     std::shared_ptr<GeomAPI_Shape> theBaseShape)
412 {
413   for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
414     theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
415     // naming of faces
416     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::FACE, "Rotated_Face");
417
418     // naming of edges
419     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::EDGE, "Rotated_Edge");
420
421     // naming of vertex
422     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::VERTEX, "Rotated_Vertex");
423   }
424 }
425
426 //=================================================================================================
427 void FeaturesPlugin_MultiRotation::loadNamingDS3(
428     std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
429     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
430     std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb)
431 {
432   int anIndex = nb+1;
433   std::string aRotatedName;
434
435   for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
436     theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
437
438     // naming of faces
439     int numFace = 1;
440     GeomAPI_ShapeExplorer anExp((*anIt)->shape(), GeomAPI_Shape::FACE);
441     for(; anExp.more(); anExp.next()) {
442        aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
443        aRotatedName = aRotatedName + "_" + std::to_string((long long) numFace);
444        theResultBody->generated(anExp.current(), aRotatedName);
445        ++numFace;
446     }
447     ++anIndex;
448   }
449 }
450
451 //=================================================================================================
452 void FeaturesPlugin_MultiRotation::loadNamingDS(
453     std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
454     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
455     std::shared_ptr<GeomAPI_Shape> theBaseShape)
456 {
457   for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
458     theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
459     // naming of faces
460     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::FACE, "Rotated_Face");
461
462     // naming of edges
463     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::EDGE, "Rotated_Edge");
464
465     // naming of vertex
466     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::VERTEX, "Rotated_Vertex");
467   }
468 }