]> SALOME platform Git repositories - modules/shaper.git/blob - src/FeaturesPlugin/FeaturesPlugin_MultiRotation.cpp
Salome HOME
[Code coverage FeaturesPlugin]: Improve coverage of Partition, Symmetry, (Multi)Rotat...
[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 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
54   data()->addAttribute(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID(),
55                        ModelAPI_AttributeString::typeId());
56   data()->addAttribute(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID(),
57                        ModelAPI_AttributeDouble::typeId());
58   data()->addAttribute(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID(),
59                        ModelAPI_AttributeInteger::typeId());
60 #endif
61 }
62
63 //=================================================================================================
64 void FeaturesPlugin_MultiRotation::execute()
65 {
66 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
67   std::string useRadialDir = string(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID())->value();
68   if (useRadialDir.empty()) {
69     performRotation1D();
70   } else {
71     performRotation2D();
72   }
73 #else
74   performRotation1D();
75 #endif
76 }
77
78 //=================================================================================================
79 void FeaturesPlugin_MultiRotation::performRotation1D()
80 {
81   // Getting objects.
82   ListOfShape anObjects;
83   std::list<ResultPtr> aContextes;
84   AttributeSelectionListPtr anObjectsSelList =
85     selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
86   if (anObjectsSelList->size() == 0) {
87     return;
88   }
89   for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
90     std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
91       anObjectsSelList->value(anObjectsIndex);
92     std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
93     if(!anObject.get()) { // may be for not-activated parts
94       return;
95     }
96     anObjects.push_back(anObject);
97     aContextes.push_back(anObjectAttr->context());
98   }
99
100   //Getting axis.
101   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
102   AttributeSelectionPtr anObjRef = selection(AXIS_ANGULAR_ID());
103   GeomShapePtr aShape = anObjRef->value();
104   if (!aShape.get()) {
105     if (anObjRef->context().get()) {
106       aShape = anObjRef->context()->shape();
107     }
108   }
109   if (!aShape.get()) {
110     setError(aSelectionError);
111     return;
112   }
113
114   GeomEdgePtr anEdge;
115   if (aShape->isEdge())
116   {
117     anEdge = aShape->edge();
118   }
119   else if (aShape->isCompound())
120   {
121     GeomAPI_ShapeIterator anIt(aShape);
122     anEdge = anIt.current()->edge();
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 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
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       return;
241     }
242     anObjects.push_back(anObject);
243     aContextes.push_back(anObjectAttr->context());
244   }
245
246   //Getting axis.
247   std::shared_ptr<GeomAPI_Ax1> anAxis;
248   std::shared_ptr<GeomAPI_Edge> anEdge;
249   std::shared_ptr<ModelAPI_AttributeSelection> anObjRef =
250     selection(FeaturesPlugin_MultiRotation::AXIS_ANGULAR_ID());
251   if(anObjRef && anObjRef->value() && anObjRef->value()->isEdge()) {
252     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->value()));
253   } else if (anObjRef && !anObjRef->value() && anObjRef->context() &&
254              anObjRef->context()->shape() && anObjRef->context()->shape()->isEdge()) {
255     anEdge = std::shared_ptr<GeomAPI_Edge>(new GeomAPI_Edge(anObjRef->context()->shape()));
256   }
257   if(anEdge) {
258     anAxis = std::shared_ptr<GeomAPI_Ax1>(new GeomAPI_Ax1(anEdge->line()->location(),
259                                                           anEdge->line()->direction()));
260   }
261
262   // Getting number of copies int he angular direction.
263   int nbAngular =
264     integer(FeaturesPlugin_MultiRotation::NB_COPIES_ANGULAR_ID())->value();
265
266   if (nbAngular <=0) {
267     std::string aFeatureError = "Multirotation builder ";
268     aFeatureError+=":: the number of copies for the angular direction is null or negative.";
269     setError(aFeatureError);
270     return;
271   }
272
273   // Getting number of copies int he radial direction.
274   int nbRadial =
275     integer(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID())->value();
276
277   if (nbRadial <=0) {
278     std::string aFeatureError = "Multirotation builder ";
279     aFeatureError+=":: the number of copies for the radial direction is null or negative.";
280     setError(aFeatureError);
281     return;
282   }
283
284   // Getting angle
285   double anAngle;
286   std::string useAngularStep =
287     string(FeaturesPlugin_MultiRotation::USE_ANGULAR_STEP_ID())->value();
288   if (!useAngularStep.empty()) {
289     anAngle = real(FeaturesPlugin_MultiRotation::STEP_ANGULAR_ID())->value();
290   } else {
291     anAngle = 360./nbAngular;
292   }
293
294   // Getting step
295   double aStep = real(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID())->value();
296
297   // Moving each object.
298   int aResultIndex = 0;
299   std::list<ResultPtr>::iterator aContext = aContextes.begin();
300   for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
301         anObjectsIt++, aContext++) {
302     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
303     bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
304
305     std::shared_ptr<GeomAPI_Dir> aDir =
306       GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(aBaseShape, anAxis);
307     double x = aDir->x();
308     double y = aDir->y();
309     double z = aDir->z();
310     double norm = sqrt(x*x+y*y+z*z);
311
312     // Setting result.
313     if (isPart) {
314       /*ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
315       std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
316       for (int j=0; j<aSecondNbCopies; j++) {
317         for (int i=0; i<aFirstNbCopies; i++) {
318           double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
319           double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
320           double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
321           aTrsf->setTranslation(dx, dy, dz);
322           ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
323           aResultPart->setTrsf(*aContext, aTrsf);
324           setResult(aResultPart, aResultIndex);
325           aResultIndex++;
326         }
327       }*/
328     } else {
329       ListOfShape aListOfShape;
330       std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
331       std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
332       for (int j=0; j<nbRadial; j++) {
333         // Translation
334         double dx = j*aStep*x/norm;
335         double dy = j*aStep*y/norm;
336         double dz = j*aStep*z/norm;
337         std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
338           new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
339
340         if (!aTranslationAlgo->check()) {
341           setError(aTranslationAlgo->getError());
342           break;
343         }
344
345         aTranslationAlgo->build();
346
347         // Checking that the algorithm worked properly.
348         if (!aTranslationAlgo->isDone()) {
349           static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
350           setError(aFeatureError);
351           break;
352         }
353         if (aTranslationAlgo->shape()->isNull()) {
354           static const std::string aShapeError = "Error : Resulting shape is null.";
355           setError(aShapeError);
356           break;
357         }
358         if (!aTranslationAlgo->isValid()) {
359           static const std::string aFeatureError = "Error : Resulting shape in not valid.";
360           setError(aFeatureError);
361           break;
362         }
363         aListOfShape.push_back(aTranslationAlgo->shape());
364         aListOfTranslationAlgo.push_back(aTranslationAlgo);
365         for (int i=1; i<nbAngular; i++) {
366           std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
367             new GeomAlgoAPI_Rotation(aTranslationAlgo->shape(), anAxis, i*anAngle));
368           if (!aRotationnAlgo->check()) {
369             setError(aTranslationAlgo->getError());
370             break;
371           }
372           aRotationnAlgo->build();// Checking that the algorithm worked properly.
373           if (!aRotationnAlgo->isDone()) {
374             static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
375             setError(aFeatureError);
376             break;
377           }
378           if (aRotationnAlgo->shape()->isNull()) {
379             static const std::string aShapeError = "Error : Resulting shape is null.";
380             setError(aShapeError);
381             break;
382           }
383           if (!aRotationnAlgo->isValid()) {
384             static const std::string aFeatureError = "Error : Resulting shape in not valid.";
385             setError(aFeatureError);
386             break;
387           }
388           aListOfShape.push_back(aRotationnAlgo->shape());
389           aListOfRotationAlgo.push_back(aRotationnAlgo);
390         }
391       }
392       std::shared_ptr<GeomAPI_Shape> aCompound =
393         GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
394       ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
395       aResultBody->storeModified(aBaseShape, aCompound);
396
397       loadNamingDS2(aListOfTranslationAlgo, aResultBody, aBaseShape);
398       loadNamingDS3(aListOfRotationAlgo, aResultBody, aBaseShape, nbRadial);
399       setResult(aResultBody, aResultIndex);
400     }
401     aResultIndex++;
402   }
403
404   // Remove the rest results if there were produced in the previous pass.
405   removeResults(aResultIndex);
406 }
407
408 //=================================================================================================
409 void FeaturesPlugin_MultiRotation::loadNamingDS2(
410     std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
411     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
412     std::shared_ptr<GeomAPI_Shape> theBaseShape)
413 {
414   for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
415     theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
416     // naming of faces
417     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::FACE, "Rotated_Face");
418
419     // naming of edges
420     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::EDGE, "Rotated_Edge");
421
422     // naming of vertex
423     theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::VERTEX, "Rotated_Vertex");
424   }
425 }
426
427 //=================================================================================================
428 void FeaturesPlugin_MultiRotation::loadNamingDS3(
429     std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
430     std::shared_ptr<ModelAPI_ResultBody> theResultBody,
431     std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb)
432 {
433   int anIndex = nb+1;
434   std::string aRotatedName;
435
436   for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
437     theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
438
439     // naming of faces
440     int numFace = 1;
441     GeomAPI_ShapeExplorer anExp((*anIt)->shape(), GeomAPI_Shape::FACE);
442     for(; anExp.more(); anExp.next()) {
443        aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
444        aRotatedName = aRotatedName + "_" + std::to_string((long long) numFace);
445        theResultBody->generated(anExp.current(), aRotatedName);
446        ++numFace;
447     }
448     ++anIndex;
449   }
450 }
451 #endif
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 }