Salome HOME
Added multirotation feature.
[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   // 
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 = GeomAlgoAPI_ShapeTools::makeToto(aBaseShape, anAxis);
283     double x = aDir->x();
284     double y = aDir->y();
285     double z = aDir->z();
286     double norm = sqrt(x*x+y*y+z*z);
287
288     // Setting result.
289     if (isPart) {
290       /*ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
291       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
292       for (int j=0; j<aSecondNbCopies; j++) {
293         for (int i=0; i<aFirstNbCopies; i++) {
294           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
295           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
296           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
297           aTrsf->setTranslation(dx, dy, dz);
298           ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
299           aResultPart->setTrsf(*aContext, aTrsf);
300           setResult(aResultPart, aResultIndex);
301           aResultIndex++;
302         }
303       }*/
304     } else {
305       ListOfShape aListOfShape;
306       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
307       std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
308       for (int j=0; j<nbRadial; j++) {
309         // Translation
310         double dx = j*aStep*x/norm;
311         double dy = j*aStep*y/norm;
312         double dz = j*aStep*z/norm;
313         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
314           new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
315
316         if (!aTranslationAlgo->check()) {
317           setError(aTranslationAlgo->getError());
318           break;
319         }
320
321         aTranslationAlgo->build();
322
323         // Checking that the algorithm worked properly.
324         if (!aTranslationAlgo->isDone()) {
325           static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
326           setError(aFeatureError);
327           break;
328         }
329         if (aTranslationAlgo->shape()->isNull()) {
330           static const std::string aShapeError = "Error : Resulting shape is null.";
331           setError(aShapeError);
332           break;
333         }
334         if (!aTranslationAlgo->isValid()) {
335           static const std::string aFeatureError = "Error : Resulting shape in not valid.";
336           setError(aFeatureError);
337           break;
338         }
339         aListOfShape.push_back(aTranslationAlgo->shape());
340         aListOfTranslationAlgo.push_back(aTranslationAlgo);
341         for (int i=1; i<nbAngular; i++) {
342           std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
343             new GeomAlgoAPI_Rotation(aTranslationAlgo->shape(), anAxis, i*anAngle));
344           if (!aRotationnAlgo->check()) {
345             setError(aTranslationAlgo->getError());
346             break;
347           }
348           aRotationnAlgo->build();// Checking that the algorithm worked properly.
349           if (!aRotationnAlgo->isDone()) {
350             static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
351             setError(aFeatureError);
352             break;
353           }
354           if (aRotationnAlgo->shape()->isNull()) {
355             static const std::string aShapeError = "Error : Resulting shape is null.";
356             setError(aShapeError);
357             break;
358           }
359           if (!aRotationnAlgo->isValid()) {
360             static const std::string aFeatureError = "Error : Resulting shape in not valid.";
361             setError(aFeatureError);
362             break;
363           }
364           aListOfShape.push_back(aRotationnAlgo->shape());
365           aListOfRotationAlgo.push_back(aRotationnAlgo);
366         }
367       }
368       std::shared_ptr<GeomAPI_Shape> aCompound =
369         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
370       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
371       aResultBody->storeModified(aBaseShape, aCompound);
372       
373       loadNamingDS2(aListOfTranslationAlgo, aResultBody, aBaseShape);
374       loadNamingDS3(aListOfRotationAlgo, aResultBody, aBaseShape, nbRadial);
375       setResult(aResultBody, aResultIndex);
376     }
377     aResultIndex++;
378   }
379
380   // Remove the rest results if there were produced in the previous pass.
381   removeResults(aResultIndex);
382 }
383
384 //=================================================================================================
385 void FeaturesPlugin_MultiRotation::loadNamingDS2(
386     std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
387     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
388     std::shared_ptr<GeomAPI_Shape> theBaseShape)
389 {
390   int aTag = 1;
391   int anIndex = 1;
392   std::string aRotatedName;
393
394   for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
395     theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
396     std::cout << "LOAD" << std::endl;
397     std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
398
399     // naming of faces
400     aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
401     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
402                                                aTag++, aRotatedName, *aSubShapes.get(),
403                                                false, true);
404
405     // naming of edges
406     aRotatedName = "Rotated_Edge_" + std::to_string((long long) anIndex);
407     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
408                                                aTag++, aRotatedName, *aSubShapes.get(),
409                                                false, true);
410
411     // naming of vertex
412     aRotatedName = "Rotated_Vertex_" + std::to_string((long long) anIndex);
413     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
414                                                aTag++, aRotatedName, *aSubShapes.get(),
415                                                false, true);
416
417     ++anIndex;
418   }
419 }
420
421 //=================================================================================================
422 void FeaturesPlugin_MultiRotation::loadNamingDS3(
423     std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
424     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
425     std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb)
426 {
427   int aTag = 6*nb+1;
428   int anIndex = nb+1;
429   std::string aRotatedName;
430
431   for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
432     theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
433     
434     // naming of faces
435     int numFace = 1;
436     GeomAPI_ShapeExplorer anExp((*anIt)->shape(), GeomAPI_Shape::FACE);
437     for(; anExp.more(); anExp.next()) {
438        aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
439        aRotatedName = aRotatedName + "_" + std::to_string((long long) numFace);
440        theResultBody->generated(anExp.current(), aRotatedName, aTag++);
441        ++numFace;
442     }
443     ++anIndex;
444   }
445 }
446
447 //=================================================================================================
448 void FeaturesPlugin_MultiRotation::loadNamingDS(
449     std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
450     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
451     std::shared_ptr<GeomAPI_Shape> theBaseShape)
452 {
453   int aTag = 1;
454   int anIndex = 1;
455   std::string aRotatedName;
456
457   for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
458     theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
459     std::shared_ptr<GeomAPI_DataMapOfShapeShape> aSubShapes = (*anIt)->mapOfSubShapes();
460
461     // naming of faces
462     aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
463     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::FACE,
464                                                aTag++, aRotatedName, *aSubShapes.get(),
465                                                false, true);
466
467     // naming of edges
468     aRotatedName = "Rotated_Edge_" + std::to_string((long long) anIndex);
469     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::EDGE,
470                                                aTag++, aRotatedName, *aSubShapes.get(),
471                                                false, true);
472
473     // naming of vertex
474     aRotatedName = "Rotated_Vertex_" + std::to_string((long long) anIndex);
475     theResultBody->loadAndOrientModifiedShapes((*anIt).get(), theBaseShape, GeomAPI_Shape::VERTEX,
476                                                aTag++, aRotatedName, *aSubShapes.get(),
477                                                false, true);
478     ++anIndex;
479   }
480 }