Salome HOME
Merge branch 'BR_EDF_2018_Lot1'
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Measurement.cpp
1 // Copyright (C) 2018-20xx  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "FeaturesPlugin_Measurement.h"
22
23 #include <ModelAPI_AttributeDoubleArray.h>
24 #include <ModelAPI_AttributeSelection.h>
25 #include <ModelAPI_AttributeString.h>
26 #include <ModelAPI_Data.h>
27 #include <ModelAPI_Session.h>
28
29 #include <GeomAPI_Angle.h>
30 #include <GeomAPI_Circ.h>
31 #include <GeomAPI_Edge.h>
32 #include <GeomAPI_Face.h>
33 #include <GeomAPI_Pnt.h>
34 #include <GeomAPI_Shape.h>
35 #include <GeomAPI_ShapeIterator.h>
36 #include <GeomAPI_Vertex.h>
37
38 #include <GeomAlgoAPI_ShapeTools.h>
39
40 #include <iomanip>
41 #include <sstream>
42
43 FeaturesPlugin_Measurement::FeaturesPlugin_Measurement()
44 {
45 }
46
47 void FeaturesPlugin_Measurement::initAttributes()
48 {
49   data()->addAttribute(FeaturesPlugin_Measurement::MEASURE_KIND(),
50                        ModelAPI_AttributeString::typeId());
51
52   // attribute for length
53   data()->addAttribute(EDGE_FOR_LENGTH_ID(), ModelAPI_AttributeSelection::typeId());
54   // attributes for distance
55   data()->addAttribute(DISTANCE_FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
56   data()->addAttribute(DISTANCE_TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
57   // attribute for radius
58   data()->addAttribute(CIRCULAR_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
59   // attributes for angle
60   data()->addAttribute(ANGLE_FROM_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
61   data()->addAttribute(ANGLE_TO_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
62   // attributes for angle by 3 points
63   data()->addAttribute(ANGLE_POINT1_ID(), ModelAPI_AttributeSelection::typeId());
64   data()->addAttribute(ANGLE_POINT2_ID(), ModelAPI_AttributeSelection::typeId());
65   data()->addAttribute(ANGLE_POINT3_ID(), ModelAPI_AttributeSelection::typeId());
66   // attributes for result message and values
67   data()->addAttribute(RESULT_ID(), ModelAPI_AttributeString::typeId());
68   data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
69 }
70
71 void FeaturesPlugin_Measurement::execute()
72 {
73 }
74
75 void FeaturesPlugin_Measurement::attributeChanged(const std::string& theID)
76 {
77   if (theID == MEASURE_KIND()) {
78     // clear results
79     string(RESULT_ID())->setValue("");
80     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
81       attribute(RESULT_VALUES_ID()))->setSize(0);
82   }
83   if (theID != RESULT_ID()) {
84     std::string aKind = string(MEASURE_KIND())->value();
85     if (aKind == MEASURE_LENGTH())
86       computeLength();
87     else if (aKind == MEASURE_DISTANCE())
88       computeDistance();
89     else if (aKind == MEASURE_RADIUS())
90       computeRadius();
91     else if (aKind == MEASURE_ANGLE())
92       computeAngle();
93     else if (aKind == MEASURE_ANGLE_POINTS())
94       computeAngleByPoints();
95   }
96 }
97
98 void FeaturesPlugin_Measurement::computeLength()
99 {
100   AttributeSelectionPtr aSelectedFeature = selection(EDGE_FOR_LENGTH_ID());
101
102   GeomShapePtr aShape;
103   GeomEdgePtr anEdge;
104   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
105     aShape = aSelectedFeature->value();
106     if (!aShape && aSelectedFeature->context())
107       aShape = aSelectedFeature->context()->shape();
108   }
109   if (aShape && aShape->isEdge())
110     anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
111   if (!anEdge) {
112     string(RESULT_ID())->setValue("");
113     return;
114   }
115
116   std::ostringstream anOutput;
117   anOutput << "Length = " << std::setprecision(10) << anEdge->length();
118   string(RESULT_ID())->setValue(anOutput.str());
119
120   AttributeDoubleArrayPtr aValues =
121       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
122   aValues->setSize(1);
123   aValues->setValue(0, anEdge->length());
124 }
125
126 void FeaturesPlugin_Measurement::computeDistance()
127 {
128   AttributeSelectionPtr aFirstFeature = selection(DISTANCE_FROM_OBJECT_ID());
129   GeomShapePtr aShape1;
130   if (aFirstFeature && aFirstFeature->isInitialized()) {
131     aShape1 = aFirstFeature->value();
132     if (!aShape1 && aFirstFeature->context())
133       aShape1 = aFirstFeature->context()->shape();
134   }
135
136   AttributeSelectionPtr aSecondFeature = selection(DISTANCE_TO_OBJECT_ID());
137   GeomShapePtr aShape2;
138   if (aSecondFeature && aSecondFeature->isInitialized()) {
139     aShape2 = aSecondFeature->value();
140     if (!aShape2 && aSecondFeature->context())
141       aShape2 = aSecondFeature->context()->shape();
142   }
143
144   if (!aShape1 || !aShape2) {
145     string(RESULT_ID())->setValue("");
146     return;
147   }
148
149   double aDistance = GeomAlgoAPI_ShapeTools::minimalDistance(aShape1, aShape2);
150
151   std::ostringstream anOutput;
152   anOutput << "Distance = " << std::setprecision(10) << aDistance;
153   string(RESULT_ID())->setValue(anOutput.str());
154
155   AttributeDoubleArrayPtr aValues =
156       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
157   aValues->setSize(1);
158   aValues->setValue(0, aDistance);
159 }
160
161 void FeaturesPlugin_Measurement::computeRadius()
162 {
163   AttributeSelectionPtr aSelectedFeature = selection(CIRCULAR_OBJECT_ID());
164
165   GeomShapePtr aShape;
166   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
167     aShape = aSelectedFeature->value();
168     if (!aShape && aSelectedFeature->context())
169       aShape = aSelectedFeature->context()->shape();
170   }
171
172   double aRadius = -1.0;
173   if (aShape) {
174     if (aShape->isEdge()) {
175       GeomEdgePtr anEdge(new GeomAPI_Edge(aShape));
176       if (anEdge->isCircle() || anEdge->isArc()) {
177         aRadius = anEdge->circle()->radius();
178       }
179     } else if (aShape->isFace()) {
180       GeomFacePtr aFace(new GeomAPI_Face(aShape));
181       aRadius = GeomAlgoAPI_ShapeTools::radius(aFace);
182     }
183   }
184
185   if (aRadius < 0.0) {
186     string(RESULT_ID())->setValue("");
187     return;
188   }
189
190   std::ostringstream anOutput;
191   anOutput << "Radius = " << std::setprecision(10) << aRadius;
192   string(RESULT_ID())->setValue(anOutput.str());
193
194   AttributeDoubleArrayPtr aValues =
195       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
196   aValues->setSize(1);
197   aValues->setValue(0, aRadius);
198 }
199
200 void FeaturesPlugin_Measurement::computeAngle()
201 {
202   AttributeSelectionPtr aFirstFeature = selection(ANGLE_FROM_EDGE_ID());
203   GeomShapePtr aShape1;
204   GeomEdgePtr anEdge1;
205   if (aFirstFeature && aFirstFeature->isInitialized()) {
206     aShape1 = aFirstFeature->value();
207     if (!aShape1 && aFirstFeature->context())
208       aShape1 = aFirstFeature->context()->shape();
209   }
210   if (aShape1 && aShape1->isEdge())
211     anEdge1 = GeomEdgePtr(new GeomAPI_Edge(aShape1));
212
213   AttributeSelectionPtr aSecondFeature = selection(ANGLE_TO_EDGE_ID());
214   GeomShapePtr aShape2;
215   GeomEdgePtr anEdge2;
216   if (aSecondFeature && aSecondFeature->isInitialized()) {
217     aShape2 = aSecondFeature->value();
218     if (!aShape2 && aSecondFeature->context())
219       aShape2 = aSecondFeature->context()->shape();
220   }
221   if (aShape2 && aShape2->isEdge())
222     anEdge2 = GeomEdgePtr(new GeomAPI_Edge(aShape2));
223
224   if (!anEdge1 || !anEdge2) {
225     string(RESULT_ID())->setValue("");
226     return;
227   }
228
229   GeomShapePtr anInter = anEdge1->intersect(anEdge2);
230
231   std::ostringstream anOutput;
232   anOutput << std::setprecision(10);
233   std::list<double> aValuesList;
234   if (anInter) {
235     if (anInter->isVertex()) {
236       std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
237       std::shared_ptr<GeomAPI_Angle> anAngle(
238           new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
239       double anAngleValue = anAngle->angleDegree();
240       anOutput << "Angle = " << std::setprecision(10) << anAngleValue << std::endl;
241       aValuesList.push_back(anAngleValue);
242     }
243     else {
244       GeomAPI_ShapeIterator anIt(anInter);
245       for (int anIndex = 1; anIt.more(); anIt.next(), ++anIndex) {
246         GeomShapePtr aCurrent = anIt.current();
247         if (!aCurrent->isVertex())
248           continue;
249         std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
250         std::shared_ptr<GeomAPI_Angle> anAngle(
251             new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
252         double anAngleValue = anAngle->angleDegree();
253         anOutput << "Angle" << anIndex << " = "
254                  << std::setprecision(10) << anAngleValue << std::endl;
255         aValuesList.push_back(anAngleValue);
256       }
257     }
258   }
259
260   string(RESULT_ID())->setValue(anOutput.str());
261
262   AttributeDoubleArrayPtr aValues =
263       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
264   aValues->setSize((int)aValuesList.size());
265   int anIndex = 0;
266   for (std::list<double>::iterator anIt = aValuesList.begin(); anIt != aValuesList.end(); ++anIt)
267     aValues->setValue(anIndex++, *anIt);
268 }
269
270 static GeomVertexPtr selectionToVertex(const AttributeSelectionPtr& aSelection)
271 {
272   GeomShapePtr aShape;
273   GeomVertexPtr aVertex;
274   if (aSelection && aSelection->isInitialized()) {
275     aShape = aSelection->value();
276     if (!aShape && aSelection->context())
277       aShape = aSelection->context()->shape();
278   }
279   if (aShape && aShape->isVertex())
280     aVertex = GeomVertexPtr(new GeomAPI_Vertex(aShape));
281   return aVertex;
282 }
283
284 void FeaturesPlugin_Measurement::computeAngleByPoints()
285 {
286   GeomVertexPtr aVertex1 = selectionToVertex(selection(ANGLE_POINT1_ID()));
287   GeomVertexPtr aVertex2 = selectionToVertex(selection(ANGLE_POINT2_ID()));
288   GeomVertexPtr aVertex3 = selectionToVertex(selection(ANGLE_POINT3_ID()));
289
290   if (!aVertex1 || !aVertex2 || ! aVertex3) {
291     string(RESULT_ID())->setValue("");
292     return;
293   }
294
295   std::shared_ptr<GeomAPI_Angle> anAngle(
296       new GeomAPI_Angle(aVertex1->point(), aVertex2->point(), aVertex3->point()));
297   double anAngleValue = anAngle->angleDegree();
298
299   std::ostringstream anOutput;
300   anOutput << "Angle = " << std::setprecision(10) << anAngleValue;
301   string(RESULT_ID())->setValue(anOutput.str());
302
303   AttributeDoubleArrayPtr aValues =
304     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
305   aValues->setSize(1);
306   aValues->setValue(0, anAngleValue);
307 }