Salome HOME
Copyright update 2021
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Rotation.cpp
1 // Copyright (C) 2014-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 #include <FeaturesPlugin_Rotation.h>
21
22 #include <ModelAPI_AttributeDouble.h>
23 #include <ModelAPI_AttributeSelectionList.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_ResultBody.h>
26 #include <ModelAPI_ResultPart.h>
27
28 #include <GeomAlgoAPI_MakeShapeList.h>
29 #include <GeomAlgoAPI_PointBuilder.h>
30 #include <GeomAlgoAPI_Rotation.h>
31 #include <GeomAlgoAPI_Tools.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_ShapeHierarchy.h>
38 #include <GeomAPI_Trsf.h>
39
40 #include <FeaturesPlugin_Tools.h>
41
42 static const std::string ROTATION_VERSION_1("v9.5");
43
44 //=================================================================================================
45 FeaturesPlugin_Rotation::FeaturesPlugin_Rotation()
46 {
47 }
48
49 //=================================================================================================
50 void FeaturesPlugin_Rotation::initAttributes()
51 {
52   data()->addAttribute(FeaturesPlugin_Rotation::CREATION_METHOD(),
53                        ModelAPI_AttributeString::typeId());
54
55   AttributeSelectionListPtr aSelection =
56     std::dynamic_pointer_cast<ModelAPI_AttributeSelectionList>(data()->addAttribute(
57     FeaturesPlugin_Rotation::OBJECTS_LIST_ID(), ModelAPI_AttributeSelectionList::typeId()));
58
59   data()->addAttribute(FeaturesPlugin_Rotation::AXIS_OBJECT_ID(),
60                        ModelAPI_AttributeSelection::typeId());
61   data()->addAttribute(FeaturesPlugin_Rotation::ANGLE_ID(), ModelAPI_AttributeDouble::typeId());
62
63   data()->addAttribute(FeaturesPlugin_Rotation::CENTER_POINT_ID(),
64                        ModelAPI_AttributeSelection::typeId());
65   data()->addAttribute(FeaturesPlugin_Rotation::START_POINT_ID(),
66                        ModelAPI_AttributeSelection::typeId());
67   data()->addAttribute(FeaturesPlugin_Rotation::END_POINT_ID(),
68                        ModelAPI_AttributeSelection::typeId());
69
70   if (!aSelection->isInitialized()) {
71     // new feature, not read from file
72     data()->setVersion(ROTATION_VERSION_1);
73   }
74 }
75
76 //=================================================================================================
77 void FeaturesPlugin_Rotation::execute()
78 {
79   AttributeStringPtr aMethodTypeAttr = string(FeaturesPlugin_Rotation::CREATION_METHOD());
80   std::string aMethodType = aMethodTypeAttr->value();
81
82   GeomTrsfPtr aTrsf;
83   if (aMethodType == CREATION_METHOD_BY_ANGLE())
84     aTrsf = rotationByAxisAndAngle();
85   else if (aMethodType == CREATION_METHOD_BY_THREE_POINTS())
86     aTrsf = rotationByThreePoints();
87
88   performRotation(aTrsf);
89 }
90
91 //=================================================================================================
92 GeomTrsfPtr FeaturesPlugin_Rotation::rotationByAxisAndAngle()
93 {
94   //Getting axis.
95   static const std::string aSelectionError = "Error: The axis shape selection is bad.";
96   AttributeSelectionPtr anObjRef = selection(AXIS_OBJECT_ID());
97   GeomShapePtr aShape = anObjRef->value();
98   if (!aShape.get()) {
99     if (anObjRef->context().get()) {
100       aShape = anObjRef->context()->shape();
101     }
102   }
103   if (!aShape.get()) {
104     setError(aSelectionError);
105     return GeomTrsfPtr();
106   }
107
108   GeomEdgePtr anEdge;
109   if (aShape->isEdge())
110   {
111     anEdge = aShape->edge();
112   }
113   else if (aShape->isCompound())
114   {
115     GeomAPI_ShapeIterator anIt(aShape);
116     anEdge = anIt.current()->edge();
117   }
118
119   if (!anEdge.get())
120   {
121     setError(aSelectionError);
122     return GeomTrsfPtr();
123   }
124
125   std::shared_ptr<GeomAPI_Ax1> anAxis (new GeomAPI_Ax1(anEdge->line()->location(),
126                                                        anEdge->line()->direction()));
127   double anAngle = real(FeaturesPlugin_Rotation::ANGLE_ID())->value();
128
129   GeomTrsfPtr aTrsf(new GeomAPI_Trsf());
130   aTrsf->setRotation(anAxis, anAngle);
131   return aTrsf;
132 }
133
134 //=================================================================================================
135 GeomTrsfPtr FeaturesPlugin_Rotation::rotationByThreePoints()
136 {
137   // Getting the center point and two points (start and end)
138   std::shared_ptr<GeomAPI_Pnt> aCenterPoint;
139   std::shared_ptr<GeomAPI_Pnt> aStartPoint;
140   std::shared_ptr<GeomAPI_Pnt> anEndPoint;
141   std::shared_ptr<ModelAPI_AttributeSelection> aCenterRef =
142     selection(FeaturesPlugin_Rotation::CENTER_POINT_ID());
143   std::shared_ptr<ModelAPI_AttributeSelection> aStartPointRef =
144     selection(FeaturesPlugin_Rotation::START_POINT_ID());
145   std::shared_ptr<ModelAPI_AttributeSelection> anEndPointRef =
146     selection(FeaturesPlugin_Rotation::END_POINT_ID());
147   if ((aCenterRef.get() != NULL) &&
148       (aStartPointRef.get() != NULL) &&
149       (anEndPointRef.get() != NULL)) {
150     GeomShapePtr aCenterShape = aCenterRef->value();
151     if (!aCenterShape.get() && aCenterRef->context().get())
152       aCenterShape = aCenterRef->context()->shape();
153     GeomShapePtr aStartShape = aStartPointRef->value();
154     if (!aStartShape.get() && aStartPointRef->context().get())
155       aStartShape = aStartPointRef->context()->shape();
156     GeomShapePtr anEndShape = anEndPointRef->value();
157     if (!anEndShape.get() && anEndPointRef->context().get())
158       anEndShape = anEndPointRef->context()->shape();
159     if (aStartShape && anEndShape && aCenterShape) {
160       aCenterPoint = GeomAlgoAPI_PointBuilder::point(aCenterShape);
161       aStartPoint = GeomAlgoAPI_PointBuilder::point(aStartShape);
162       anEndPoint = GeomAlgoAPI_PointBuilder::point(anEndShape);
163     }
164
165     if (!aCenterPoint || !aStartPoint || !anEndPoint)
166       return GeomTrsfPtr();
167   }
168
169   GeomTrsfPtr aTrsf(new GeomAPI_Trsf());
170   aTrsf->setRotation(aCenterPoint, aStartPoint, anEndPoint);
171   return aTrsf;
172 }
173
174 //=================================================================================================
175 void FeaturesPlugin_Rotation::performRotation(const GeomTrsfPtr& theTrsf)
176 {
177   if (!theTrsf) {
178     setError("Invalid transformation.");
179     return;
180   }
181
182   bool isKeepSubShapes = data()->version() == ROTATION_VERSION_1;
183
184   // Getting objects.
185   GeomAPI_ShapeHierarchy anObjects;
186   std::list<ResultPtr> aParts;
187   AttributeSelectionListPtr anObjSelList = selectionList(OBJECTS_LIST_ID());
188   if (!FeaturesPlugin_Tools::shapesFromSelectionList(
189        anObjSelList, isKeepSubShapes, anObjects, aParts))
190     return;
191
192   std::string anError;
193   int aResultIndex = 0;
194   // Rotating each part.
195   for (std::list<ResultPtr>::iterator aPRes = aParts.begin(); aPRes != aParts.end(); ++aPRes) {
196     ResultPartPtr anOriginal = std::dynamic_pointer_cast<ModelAPI_ResultPart>(*aPRes);
197     ResultPartPtr aResultPart = document()->copyPart(anOriginal, data(), aResultIndex);
198     aResultPart->setTrsf(anOriginal, theTrsf);
199     setResult(aResultPart, aResultIndex++);
200   }
201
202   // Collect transformations for each object in a part.
203   std::shared_ptr<GeomAlgoAPI_MakeShapeList> aMakeShapeList(new GeomAlgoAPI_MakeShapeList);
204   for(GeomAPI_ShapeHierarchy::iterator anObjectsIt = anObjects.begin();
205       anObjectsIt != anObjects.end(); ++anObjectsIt) {
206     std::shared_ptr<GeomAPI_Shape> aBaseShape = *anObjectsIt;
207     std::shared_ptr<GeomAlgoAPI_Transform> aRotationAlgo(
208         new GeomAlgoAPI_Transform(aBaseShape, theTrsf));
209
210     // Checking that the algorithm worked properly.
211     if (GeomAlgoAPI_Tools::AlgoError::isAlgorithmFailed(aRotationAlgo, getKind(), anError)) {
212       setError(anError);
213       break;
214     }
215
216     anObjects.markModified(aBaseShape, aRotationAlgo->shape());
217     aMakeShapeList->appendAlgo(aRotationAlgo);
218   }
219
220   // Build results of the rotation.
221   const ListOfShape& anOriginalShapes = anObjects.objects();
222   ListOfShape aTopLevel;
223   anObjects.topLevelObjects(aTopLevel);
224   for (ListOfShape::iterator anIt = aTopLevel.begin(); anIt != aTopLevel.end(); ++anIt) {
225     ResultBodyPtr aResultBody = document()->createBody(data(), aResultIndex);
226     FeaturesPlugin_Tools::loadModifiedShapes(aResultBody, anOriginalShapes, ListOfShape(),
227                                              aMakeShapeList, *anIt, "Rotated");
228     setResult(aResultBody, aResultIndex++);
229   }
230
231   // Remove the rest results if there were produced in the previous pass.
232   removeResults(aResultIndex);
233 }