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