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