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