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