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