1 // Copyright (C) 2017-2022 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 // File: FeaturesPlugin_MultiRotation.cpp
21 // Created: 30 Jan 2017
22 // Author: Clarisse Genrault (CEA)
24 #include <FeaturesPlugin_MultiRotation.h>
25 #include <FeaturesPlugin_Tools.h>
27 #include <GeomAlgoAPI_CompoundBuilder.h>
28 #include <GeomAlgoAPI_MakeShapeSet.h>
29 #include <GeomAlgoAPI_ShapeTools.h>
30 #include <GeomAlgoAPI_Tools.h>
31 #include <GeomAlgoAPI_Translation.h>
33 #include <GeomAPI_ShapeExplorer.h>
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>
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>
52 static const std::string MULTIROTATION_VERSION_1("v9.5");
54 //=================================================================================================
55 FeaturesPlugin_MultiRotation::FeaturesPlugin_MultiRotation()
59 //=================================================================================================
60 void FeaturesPlugin_MultiRotation::initAttributes()
62 AttributeSelectionListPtr aSelection =
63 std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
64 FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID(),
65 ModelAPI_AttributeSelectionList::typeId()));
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());
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());
85 if (!aSelection->isInitialized()) {
86 // new feature, not read from file
87 data()->setVersion(MULTIROTATION_VERSION_1);
91 //=================================================================================================
92 void FeaturesPlugin_MultiRotation::execute()
94 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
95 std::string useRadialDir = string(FeaturesPlugin_MultiRotation::USE_RADIAL_DIR_ID())->value();
96 if (useRadialDir.empty()) {
106 //=================================================================================================
107 bool FeaturesPlugin_MultiRotation::paramsOfRotation(std::shared_ptr<GeomAPI_Ax1>& theAxis,
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();
118 setError(aSelectionError);
123 if (aShape->isEdge())
124 anEdge = aShape->edge();
125 else if (aShape->isCompound()) {
126 GeomAPI_ShapeIterator anIt(aShape);
127 anEdge = anIt.current()->edge();
131 setError(aSelectionError);
135 theAxis.reset(new GeomAPI_Ax1(anEdge->line()->location(), anEdge->line()->direction()));
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);
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();
152 theAngle = 360. / theQuantity;
156 //=================================================================================================
157 void FeaturesPlugin_MultiRotation::performRotation1D()
159 bool isKeepSubShapes = data()->version() == MULTIROTATION_VERSION_1;
162 AttributeSelectionListPtr anObjectsSelList = selectionList(OBJECTS_LIST_ID());
163 if (anObjectsSelList->size() == 0) {
164 setError("Error: empty selection list");
168 GeomAPI_ShapeHierarchy anObjects;
169 std::list<ResultPtr> aParts;
170 ResultPtr aTextureSource;
171 if (!FeaturesPlugin_Tools::shapesFromSelectionList
172 (anObjectsSelList, isKeepSubShapes, anObjects, aParts, aTextureSource))
175 // Parameters of rotation.
176 std::shared_ptr<GeomAPI_Ax1> anAxis;
177 double anAngle = 0.0;
179 if (!paramsOfRotation(anAxis, anAngle, nbCopies))
184 int aResultIndex = 0;
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++);
197 // Collect transformations for each object in a part.
198 std::shared_ptr<GeomAlgoAPI_MakeShapeSet> aMakeShapeList(new GeomAlgoAPI_MakeShapeSet);
199 for (GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
200 anObjectsIt != anObjects.end(); anObjectsIt++) {
201 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
202 ListOfShape aListOfShape;
204 for (int i = 0; i < nbCopies; i++) {
205 std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
206 new GeomAlgoAPI_Rotation(aBaseShape, anAxis, i * anAngle));
208 // Checking that the algorithm worked properly.
209 if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aRotationnAlgo, getKind(), anError)) {
213 aListOfShape.push_back(aRotationnAlgo->shape());
214 aMakeShapeList->appendAlgo(aRotationnAlgo);
217 GeomShapePtr aCompound = GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
218 anObjects.markModified(aBaseShape, aCompound);
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 // Copy image data, if any
230 ModelAPI_Tools::copyImageAttribute(aTextureSource, aResultBody);
231 setResult(aResultBody, aResultIndex++);
234 // Remove the rest results if there were produced in the previous pass.
235 removeResults(aResultIndex);
238 //=================================================================================================
239 #ifdef FEATURE_MULTIROTATION_TWO_DIRECTIONS
240 void FeaturesPlugin_MultiRotation::performRotation2D()
243 ListOfShape anObjects;
244 std::list<ResultPtr> aContextes;
245 AttributeSelectionListPtr anObjectsSelList =
246 selectionList(FeaturesPlugin_MultiRotation::OBJECTS_LIST_ID());
247 if (anObjectsSelList->size() == 0) {
250 for(int anObjectsIndex = 0; anObjectsIndex < anObjectsSelList->size(); anObjectsIndex++) {
251 std::shared_ptr<ModelAPI_AttributeSelection> anObjectAttr =
252 anObjectsSelList->value(anObjectsIndex);
253 std::shared_ptr<GeomAPI_Shape> anObject = anObjectAttr->value();
254 if(!anObject.get()) { // may be for not-activated parts
257 anObjects.push_back(anObject);
258 aContextes.push_back(anObjectAttr->context());
261 // Parameters of rotation.
262 std::shared_ptr<GeomAPI_Ax1> anAxis;
263 double anAngle = 0.0;
265 if (!paramsOfRotation(anAxis, anAngle, nbCopies))
269 // Getting number of copies int he radial direction.
271 integer(FeaturesPlugin_MultiRotation::NB_COPIES_RADIAL_ID())->value();
274 std::string aFeatureError = "Multirotation builder ";
275 aFeatureError+=":: the number of copies for the radial direction is null or negative.";
276 setError(aFeatureError);
281 double aStep = real(FeaturesPlugin_MultiRotation::STEP_RADIAL_ID())->value();
283 // Moving each object.
284 int aResultIndex = 0;
285 std::list<ResultPtr>::iterator aContext = aContextes.begin();
286 for(ListOfShape::iterator anObjectsIt = anObjects.begin(); anObjectsIt != anObjects.end();
287 anObjectsIt++, aContext++) {
288 std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
289 bool isPart = aContext->get() && (*aContext)->groupName() == ModelAPI_ResultPart::group();
291 std::shared_ptr<GeomAPI_Dir> aDir =
292 GeomAlgoAPI_ShapeTools::buildDirFromAxisAndShape(aBaseShape, anAxis);
293 double x = aDir->x();
294 double y = aDir->y();
295 double z = aDir->z();
296 double norm = sqrt(x*x+y*y+z*z);
300 /*ResultPartPtr anOrigin = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aContext);
301 std::shared_ptr<GeomAPI_Trsf> aTrsf(new GeomAPI_Trsf());
302 for (int j=0; j<aSecondNbCopies; j++) {
303 for (int i=0; i<aFirstNbCopies; i++) {
304 double dx = i*aFirstStep*x1/norm1+j*aSecondStep*x2/norm2;
305 double dy = i*aFirstStep*y1/norm1+j*aSecondStep*y2/norm2;
306 double dz = i*aFirstStep*z1/norm1+j*aSecondStep*z2/norm2;
307 aTrsf->setTranslation(dx, dy, dz);
308 ResultPartPtr aResultPart = document()->copyPart(anOrigin, data(), aResultIndex);
309 aResultPart->setTrsf(*aContext, aTrsf);
310 setResult(aResultPart, aResultIndex);
315 ListOfShape aListOfShape;
316 std::list<std::shared_ptr<GeomAlgoAPI_Translation> > aListOfTranslationAlgo;
317 std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > aListOfRotationAlgo;
318 for (int j=0; j<nbRadial; j++) {
320 double dx = j*aStep*x/norm;
321 double dy = j*aStep*y/norm;
322 double dz = j*aStep*z/norm;
323 std::shared_ptr<GeomAlgoAPI_Translation> aTranslationAlgo(
324 new GeomAlgoAPI_Translation(aBaseShape, dx, dy, dz));
326 if (!aTranslationAlgo->check()) {
327 setError(aTranslationAlgo->getError());
331 aTranslationAlgo->build();
333 // Checking that the algorithm worked properly.
334 if (!aTranslationAlgo->isDone()) {
335 static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
336 setError(aFeatureError);
339 if (aTranslationAlgo->shape()->isNull()) {
340 static const std::string aShapeError = "Error : Resulting shape is null.";
341 setError(aShapeError);
344 if (!aTranslationAlgo->isValid()) {
345 static const std::string aFeatureError = "Error : Resulting shape in not valid.";
346 setError(aFeatureError);
349 aListOfShape.push_back(aTranslationAlgo->shape());
350 aListOfTranslationAlgo.push_back(aTranslationAlgo);
351 for (int i=1; i<nbAngular; i++) {
352 std::shared_ptr<GeomAlgoAPI_Rotation> aRotationnAlgo(
353 new GeomAlgoAPI_Rotation(aTranslationAlgo->shape(), anAxis, i*anAngle));
354 if (!aRotationnAlgo->check()) {
355 setError(aTranslationAlgo->getError());
358 aRotationnAlgo->build();// Checking that the algorithm worked properly.
359 if (!aRotationnAlgo->isDone()) {
360 static const std::string aFeatureError = "Error : Multirotation algorithm failed.";
361 setError(aFeatureError);
364 if (aRotationnAlgo->shape()->isNull()) {
365 static const std::string aShapeError = "Error : Resulting shape is null.";
366 setError(aShapeError);
369 if (!aRotationnAlgo->isValid()) {
370 static const std::string aFeatureError = "Error : Resulting shape in not valid.";
371 setError(aFeatureError);
374 aListOfShape.push_back(aRotationnAlgo->shape());
375 aListOfRotationAlgo.push_back(aRotationnAlgo);
378 std::shared_ptr<GeomAPI_Shape> aCompound =
379 GeomAlgoAPI_CompoundBuilder::compound(aListOfShape);
380 ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
381 aResultBody->storeModified(aBaseShape, aCompound);
383 loadNamingDS2(aListOfTranslationAlgo, aResultBody, aBaseShape);
384 loadNamingDS3(aListOfRotationAlgo, aResultBody, aBaseShape, nbRadial);
385 setResult(aResultBody, aResultIndex);
390 // Remove the rest results if there were produced in the previous pass.
391 removeResults(aResultIndex);
394 //=================================================================================================
395 void FeaturesPlugin_MultiRotation::loadNamingDS2(
396 std::list<std::shared_ptr<GeomAlgoAPI_Translation> > theListOfTranslationAlgo,
397 std::shared_ptr<ModelAPI_ResultBody> theResultBody,
398 std::shared_ptr<GeomAPI_Shape> theBaseShape)
400 for (std::list<std::shared_ptr<GeomAlgoAPI_Translation> >::const_iterator anIt =
401 theListOfTranslationAlgo.begin(); anIt != theListOfTranslationAlgo.cend(); ++anIt) {
403 theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::FACE, "Rotated_Face");
406 theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::EDGE, "Rotated_Edge");
409 theResultBody->loadModifiedShapes(*anIt, theBaseShape, GeomAPI_Shape::VERTEX, "Rotated_Vertex");
413 //=================================================================================================
414 void FeaturesPlugin_MultiRotation::loadNamingDS3(
415 std::list<std::shared_ptr<GeomAlgoAPI_Rotation> > theListOfRotationAlgo,
416 std::shared_ptr<ModelAPI_ResultBody> theResultBody,
417 std::shared_ptr<GeomAPI_Shape> theBaseShape, int nb)
420 std::string aRotatedName;
422 for (std::list<std::shared_ptr<GeomAlgoAPI_Rotation> >::const_iterator anIt =
423 theListOfRotationAlgo.begin(); anIt != theListOfRotationAlgo.cend(); ++anIt) {
427 GeomAPI_ShapeExplorer anExp((*anIt)->shape(), GeomAPI_Shape::FACE);
428 for(; anExp.more(); anExp.next()) {
429 aRotatedName = "Rotated_Face_" + std::to_string((long long) anIndex);
430 aRotatedName = aRotatedName + "_" + std::to_string((long long) numFace);
431 theResultBody->generated(anExp.current(), aRotatedName);