Salome HOME
e8cb398bbaef07d497911473ee0dee53fcf3eb18
[modules/shaper.git] / src / FeaturesPlugin / FeaturesPlugin_Measurement.cpp
1 // Copyright (C) 2018-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_Measurement.h"
21
22 #include <ModelAPI_AttributeDoubleArray.h>
23 #include <ModelAPI_AttributeSelection.h>
24 #include <ModelAPI_AttributeString.h>
25 #include <ModelAPI_Data.h>
26 #include <ModelAPI_Session.h>
27
28 #include <GeomAPI_Angle.h>
29 #include <GeomAPI_Circ.h>
30 #include <GeomAPI_Edge.h>
31 #include <GeomAPI_Face.h>
32 #include <GeomAPI_Pnt.h>
33 #include <GeomAPI_Shape.h>
34 #include <GeomAPI_ShapeIterator.h>
35 #include <GeomAPI_Vertex.h>
36
37 #include <GeomAlgoAPI_ShapeTools.h>
38
39 #include <Config_PropManager.h>
40
41 #include <TopoDS.hxx>
42 #include <TopoDS_Edge.hxx>
43 #include <TopoDS_Shape.hxx>
44 #include <PrsDim_Dimension.hxx>
45 #include <PrsDim_LengthDimension.hxx>
46 #include <PrsDim_RadiusDimension.hxx>
47 #include <PrsDim_AngleDimension.hxx>
48 #include <BRepExtrema_DistShapeShape.hxx>
49
50 #include <iomanip>
51 #include <sstream>
52
53 FeaturesPlugin_Measurement::FeaturesPlugin_Measurement() : mySceenScale(1)
54 {
55 }
56
57 void FeaturesPlugin_Measurement::initAttributes()
58 {
59   data()->addAttribute(FeaturesPlugin_Measurement::MEASURE_KIND(),
60                        ModelAPI_AttributeString::typeId());
61
62   // attribute for length
63   data()->addAttribute(EDGE_FOR_LENGTH_ID(), ModelAPI_AttributeSelection::typeId());
64   // attributes for distance
65   data()->addAttribute(DISTANCE_FROM_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
66   data()->addAttribute(DISTANCE_TO_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
67   // attribute for radius
68   data()->addAttribute(CIRCULAR_OBJECT_ID(), ModelAPI_AttributeSelection::typeId());
69   // attributes for angle
70   data()->addAttribute(ANGLE_FROM_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
71   data()->addAttribute(ANGLE_TO_EDGE_ID(), ModelAPI_AttributeSelection::typeId());
72   // attributes for angle by 3 points
73   data()->addAttribute(ANGLE_POINT1_ID(), ModelAPI_AttributeSelection::typeId());
74   data()->addAttribute(ANGLE_POINT2_ID(), ModelAPI_AttributeSelection::typeId());
75   data()->addAttribute(ANGLE_POINT3_ID(), ModelAPI_AttributeSelection::typeId());
76   // attributes for result message and values
77   data()->addAttribute(RESULT_ID(), ModelAPI_AttributeString::typeId());
78   data()->addAttribute(RESULT_VALUES_ID(), ModelAPI_AttributeDoubleArray::typeId());
79 }
80
81 void FeaturesPlugin_Measurement::execute()
82 {
83 }
84
85 void FeaturesPlugin_Measurement::attributeChanged(const std::string& theID)
86 {
87   if (theID == MEASURE_KIND()) {
88     // clear results
89     string(RESULT_ID())->setValue("");
90     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(
91       attribute(RESULT_VALUES_ID()))->setSize(0);
92   }
93   if (theID != RESULT_ID()) {
94     std::string aKind = string(MEASURE_KIND())->value();
95     if (aKind == MEASURE_LENGTH())
96       computeLength();
97     else if (aKind == MEASURE_DISTANCE())
98       computeDistance();
99     else if (aKind == MEASURE_RADIUS())
100       computeRadius();
101     else if (aKind == MEASURE_ANGLE())
102       computeAngle();
103     else if (aKind == MEASURE_ANGLE_POINTS())
104       computeAngleByPoints();
105   }
106 }
107
108 void FeaturesPlugin_Measurement::computeLength()
109 {
110   AttributeSelectionPtr aSelectedFeature = selection(EDGE_FOR_LENGTH_ID());
111
112   GeomShapePtr aShape;
113   GeomEdgePtr anEdge;
114   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
115     aShape = aSelectedFeature->value();
116     if (!aShape && aSelectedFeature->context())
117       aShape = aSelectedFeature->context()->shape();
118   }
119   if (aShape && aShape->isEdge())
120     anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
121   if (!anEdge) {
122     string(RESULT_ID())->setValue("");
123     return;
124   }
125
126   std::ostringstream anOutput;
127   anOutput << "Length = " << std::setprecision(10) << anEdge->length();
128   if(anEdge->isLine())
129   {
130     auto point1 = anEdge->firstPoint();
131     auto point2 = anEdge->lastPoint();
132
133     anOutput <<"\n|dx| = " <<  std::setprecision(10) << std::abs(point2->x() - point1->x())
134         <<"\n|dy| = " <<  std::setprecision(10) << std::abs(point2->y() - point1->y())
135         <<"\n|dz| = " <<  std::setprecision(10) << std::abs(point2->z() - point1->z());
136   }
137   string(RESULT_ID())->setValue(anOutput.str());
138
139   AttributeDoubleArrayPtr aValues =
140       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
141   aValues->setSize(1);
142   aValues->setValue(0, anEdge->length());
143 }
144
145 void FeaturesPlugin_Measurement::computeDistance()
146 {
147   AttributeSelectionPtr aFirstFeature = selection(DISTANCE_FROM_OBJECT_ID());
148   GeomShapePtr aShape1;
149   if (aFirstFeature && aFirstFeature->isInitialized()) {
150     aShape1 = aFirstFeature->value();
151     if (!aShape1 && aFirstFeature->context())
152       aShape1 = aFirstFeature->context()->shape();
153   }
154
155   AttributeSelectionPtr aSecondFeature = selection(DISTANCE_TO_OBJECT_ID());
156   GeomShapePtr aShape2;
157   if (aSecondFeature && aSecondFeature->isInitialized()) {
158     aShape2 = aSecondFeature->value();
159     if (!aShape2 && aSecondFeature->context())
160       aShape2 = aSecondFeature->context()->shape();
161   }
162
163   if (!aShape1 || !aShape2) {
164     string(RESULT_ID())->setValue("");
165     return;
166   }
167
168   std::array<double, 3> fromShape1To2;
169   double aDistance = GeomAlgoAPI_ShapeTools::minimalDistance(aShape1, aShape2, fromShape1To2);
170
171   std::ostringstream anOutput;
172   anOutput << "Distance = " << std::setprecision(10) << aDistance
173            <<"\n|dx| = " <<  std::setprecision(10) << std::abs(fromShape1To2[0])
174       <<"\n|dy| = " <<  std::setprecision(10) << std::abs(fromShape1To2[1])
175       <<"\n|dz| = " <<  std::setprecision(10) << std::abs(fromShape1To2[2]);
176   string(RESULT_ID())->setValue(anOutput.str());
177
178   AttributeDoubleArrayPtr aValues =
179       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
180   aValues->setSize(1);
181   aValues->setValue(0, aDistance);
182 }
183
184 void FeaturesPlugin_Measurement::computeRadius()
185 {
186   AttributeSelectionPtr aSelectedFeature = selection(CIRCULAR_OBJECT_ID());
187
188   GeomShapePtr aShape;
189   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
190     aShape = aSelectedFeature->value();
191     if (!aShape && aSelectedFeature->context())
192       aShape = aSelectedFeature->context()->shape();
193   }
194
195   double aRadius = -1.0;
196   if (aShape) {
197     if (aShape->isEdge()) {
198       GeomEdgePtr anEdge(new GeomAPI_Edge(aShape));
199       if (anEdge->isCircle() || anEdge->isArc()) {
200         aRadius = anEdge->circle()->radius();
201       }
202     } else if (aShape->isFace()) {
203       GeomFacePtr aFace(new GeomAPI_Face(aShape));
204       aRadius = GeomAlgoAPI_ShapeTools::radius(aFace);
205     }
206   }
207
208   if (aRadius < 0.0) {
209     string(RESULT_ID())->setValue("");
210     return;
211   }
212
213   std::ostringstream anOutput;
214   anOutput << "Radius = " << std::setprecision(10) << aRadius;
215   string(RESULT_ID())->setValue(anOutput.str());
216
217   AttributeDoubleArrayPtr aValues =
218       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
219   aValues->setSize(1);
220   aValues->setValue(0, aRadius);
221 }
222
223 void FeaturesPlugin_Measurement::computeAngle()
224 {
225   AttributeSelectionPtr aFirstFeature = selection(ANGLE_FROM_EDGE_ID());
226   GeomShapePtr aShape1;
227   GeomEdgePtr anEdge1;
228   if (aFirstFeature && aFirstFeature->isInitialized()) {
229     aShape1 = aFirstFeature->value();
230     if (!aShape1 && aFirstFeature->context())
231       aShape1 = aFirstFeature->context()->shape();
232   }
233   if (aShape1 && aShape1->isEdge())
234     anEdge1 = GeomEdgePtr(new GeomAPI_Edge(aShape1));
235
236   AttributeSelectionPtr aSecondFeature = selection(ANGLE_TO_EDGE_ID());
237   GeomShapePtr aShape2;
238   GeomEdgePtr anEdge2;
239   if (aSecondFeature && aSecondFeature->isInitialized()) {
240     aShape2 = aSecondFeature->value();
241     if (!aShape2 && aSecondFeature->context())
242       aShape2 = aSecondFeature->context()->shape();
243   }
244   if (aShape2 && aShape2->isEdge())
245     anEdge2 = GeomEdgePtr(new GeomAPI_Edge(aShape2));
246
247   if (!anEdge1 || !anEdge2) {
248     string(RESULT_ID())->setValue("");
249     return;
250   }
251
252   GeomShapePtr anInter = anEdge1->intersect(anEdge2);
253
254   std::ostringstream anOutput;
255   anOutput << std::setprecision(10);
256   std::list<double> aValuesList;
257   if (anInter) {
258     if (anInter->isVertex()) {
259       std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(anInter));
260       std::shared_ptr<GeomAPI_Angle> anAngle(
261           new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
262       double anAngleValue = anAngle->angleDegree();
263       anOutput << "Angle = " << std::setprecision(10) << anAngleValue << std::endl;
264       aValuesList.push_back(anAngleValue);
265     }
266     else {
267       GeomAPI_ShapeIterator anIt(anInter);
268       for (int anIndex = 1; anIt.more(); anIt.next(), ++anIndex) {
269         GeomShapePtr aCurrent = anIt.current();
270         if (!aCurrent->isVertex())
271           continue;
272         std::shared_ptr<GeomAPI_Vertex> aVertex(new GeomAPI_Vertex(aCurrent));
273         std::shared_ptr<GeomAPI_Angle> anAngle(
274             new GeomAPI_Angle(anEdge1, anEdge2, aVertex->point()));
275         double anAngleValue = anAngle->angleDegree();
276         anOutput << "Angle" << anIndex << " = "
277                  << std::setprecision(10) << anAngleValue << std::endl;
278         aValuesList.push_back(anAngleValue);
279       }
280     }
281   }
282
283   string(RESULT_ID())->setValue(anOutput.str());
284
285   AttributeDoubleArrayPtr aValues =
286       std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
287   aValues->setSize((int)aValuesList.size());
288   int anIndex = 0;
289   for (std::list<double>::iterator anIt = aValuesList.begin(); anIt != aValuesList.end(); ++anIt)
290     aValues->setValue(anIndex++, *anIt);
291 }
292
293 static GeomVertexPtr selectionToVertex(const AttributeSelectionPtr& aSelection)
294 {
295   GeomShapePtr aShape;
296   GeomVertexPtr aVertex;
297   if (aSelection && aSelection->isInitialized()) {
298     aShape = aSelection->value();
299     if (!aShape && aSelection->context())
300       aShape = aSelection->context()->shape();
301   }
302   if (aShape && aShape->isVertex())
303     aVertex = GeomVertexPtr(new GeomAPI_Vertex(aShape));
304   return aVertex;
305 }
306
307 void FeaturesPlugin_Measurement::computeAngleByPoints()
308 {
309   GeomVertexPtr aVertex1 = selectionToVertex(selection(ANGLE_POINT1_ID()));
310   GeomVertexPtr aVertex2 = selectionToVertex(selection(ANGLE_POINT2_ID()));
311   GeomVertexPtr aVertex3 = selectionToVertex(selection(ANGLE_POINT3_ID()));
312
313   if (!aVertex1 || !aVertex2 || ! aVertex3) {
314     string(RESULT_ID())->setValue("");
315     return;
316   }
317
318   std::shared_ptr<GeomAPI_Angle> anAngle(
319       new GeomAPI_Angle(aVertex1->point(), aVertex2->point(), aVertex3->point()));
320   double anAngleValue = anAngle->angleDegree();
321
322   std::ostringstream anOutput;
323   anOutput << "Angle = " << std::setprecision(10) << anAngleValue;
324   string(RESULT_ID())->setValue(anOutput.str());
325
326   AttributeDoubleArrayPtr aValues =
327     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
328   aValues->setSize(1);
329   aValues->setValue(0, anAngleValue);
330 }
331
332 AISObjectPtr FeaturesPlugin_Measurement::getAISObject(AISObjectPtr thePrevious)
333 {
334   AttributeDoubleArrayPtr aValues =
335     std::dynamic_pointer_cast<ModelAPI_AttributeDoubleArray>(attribute(RESULT_VALUES_ID()));
336   if ((aValues->size() == 0) || (aValues->value(0) <= Precision::Confusion()))
337     return AISObjectPtr();
338
339   if (!myScreenPlane) {
340     // initialize a default plane for dimension
341     GeomPointPtr anOrigin(new GeomAPI_Pnt(0., 0., 0.));
342     GeomDirPtr aNormal(new GeomAPI_Dir(0., 0., 1.));
343     myScreenPlane = GeomPlanePtr(new GeomAPI_Pln(anOrigin, aNormal));
344   }
345
346   AISObjectPtr anAIS;
347   std::string aKind = string(MEASURE_KIND())->value();
348   if (aKind == MEASURE_LENGTH())
349     anAIS = lengthDimension(thePrevious);
350   else if (aKind == MEASURE_DISTANCE())
351     anAIS = distanceDimension(thePrevious);
352   else if (aKind == MEASURE_RADIUS())
353     anAIS = radiusDimension(thePrevious);
354   else if (aKind == MEASURE_ANGLE())
355     anAIS = angleDimension(thePrevious);
356   else if (aKind == MEASURE_ANGLE_POINTS())
357     anAIS = angleByPointsDimension(thePrevious);
358   setupDimension(anAIS);
359   return anAIS;
360 }
361
362 AISObjectPtr FeaturesPlugin_Measurement::lengthDimension(AISObjectPtr thePrevious)
363 {
364   AISObjectPtr aAISObj;
365
366   AttributeSelectionPtr aSelectedFeature = selection(EDGE_FOR_LENGTH_ID());
367
368   GeomShapePtr aShape;
369   GeomEdgePtr anEdge;
370   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
371     aShape = aSelectedFeature->value();
372     if (!aShape && aSelectedFeature->context())
373       aShape = aSelectedFeature->context()->shape();
374   }
375   if (aShape && aShape->isEdge())
376     anEdge = GeomEdgePtr(new GeomAPI_Edge(aShape));
377   if (anEdge) {
378     TopoDS_Edge aTEdge = TopoDS::Edge(anEdge->impl<TopoDS_Shape>());
379     GeomPointPtr aPoint1 = anEdge->firstPoint();
380     GeomPointPtr aPoint2 = anEdge->lastPoint();
381
382     gp_Pnt aPnt1(aPoint1->impl<gp_Pnt>());
383     gp_Pnt aPnt2(aPoint2->impl<gp_Pnt>());
384
385     double aLength = aPnt1.Distance(aPnt2);
386     if (aLength > 0) {
387       gp_Pln aPlane = myScreenPlane->impl<gp_Pln>(); // gce_MP.Value();
388       aPlane.SetLocation(aPnt1);
389
390       gp_XYZ aNormal = aPlane.Axis().Direction().XYZ();
391       gp_XYZ aVec(aPnt2.X() - aPnt1.X(), aPnt2.Y() - aPnt1.Y(), aPnt2.Z() - aPnt1.Z());
392       double aDot = aNormal.Dot(aVec);
393       if (fabs(aDot - aLength) <= Precision::Confusion()) {
394         aPlane = gp_Pln(aPnt1, aPlane.XAxis().Direction());
395       }
396
397       Handle(PrsDim_LengthDimension) aDim;
398       if (thePrevious.get()) {
399         aAISObj = thePrevious;
400         Handle(AIS_InteractiveObject) aAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
401         aDim = Handle(PrsDim_LengthDimension)::DownCast(aAIS);
402         if (aDim.IsNull()) {
403           aDim = new PrsDim_LengthDimension(aTEdge, aPlane);
404           aAISObj = AISObjectPtr(new GeomAPI_AISObject());
405           aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
406         }
407         else {
408           aDim->SetMeasuredGeometry(aTEdge, aPlane);
409         }
410       }
411       else {
412         aDim = new PrsDim_LengthDimension(aTEdge, aPlane);
413         aAISObj = AISObjectPtr(new GeomAPI_AISObject());
414         aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
415       }
416       aDim->SetFlyout(aLength / 3.);
417     }
418   }
419   return aAISObj;
420 }
421
422 AISObjectPtr FeaturesPlugin_Measurement::distanceDimension(AISObjectPtr thePrevious)
423 {
424   AISObjectPtr aAISObj;
425
426   AttributeSelectionPtr aFirstFeature = selection(DISTANCE_FROM_OBJECT_ID());
427   AttributeSelectionPtr aSecondFeature = selection(DISTANCE_TO_OBJECT_ID());
428   if (aFirstFeature.get() && aSecondFeature.get()) {
429     GeomShapePtr aShape1;
430     GeomShapePtr aShape2;
431     if (aFirstFeature->isInitialized() && aSecondFeature->isInitialized()) {
432       aShape1 = aFirstFeature->value();
433       if (!aShape1 && aFirstFeature->context())
434         aShape1 = aFirstFeature->context()->shape();
435       aShape2 = aSecondFeature->value();
436       if (!aShape2 && aSecondFeature->context())
437         aShape2 = aSecondFeature->context()->shape();
438     }
439
440     if (aShape1 && aShape2) {
441       const TopoDS_Shape& aShp1 = aShape1->impl<TopoDS_Shape>();
442       const TopoDS_Shape& aShp2 = aShape2->impl<TopoDS_Shape>();
443       BRepExtrema_DistShapeShape aDist(aShp1, aShp2);
444       aDist.Perform();
445       if (aDist.IsDone()) {
446         gp_Pnt aPnt1 = aDist.PointOnShape1(1);
447         gp_Pnt aPnt2 = aDist.PointOnShape2(1);
448         double aDistance = aDist.Value();
449         if (aDistance > 0) {
450           gp_Pln aPlane = myScreenPlane->impl<gp_Pln>();
451           aPlane.SetLocation(aPnt1);
452
453           gp_XYZ aNormal = aPlane.Axis().Direction().XYZ();
454           gp_XYZ aVec(aPnt2.X() - aPnt1.X(), aPnt2.Y() - aPnt1.Y(), aPnt2.Z() - aPnt1.Z());
455           double aDot = aNormal.Dot(aVec);
456           if (fabs(aDot - aDistance) <= Precision::Confusion()) {
457             aPlane = gp_Pln(aPnt1, aPlane.XAxis().Direction());
458           }
459
460           Handle(PrsDim_LengthDimension) aDim;
461           if (thePrevious.get()) {
462             aAISObj = thePrevious;
463             Handle(AIS_InteractiveObject) aAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
464             aDim = Handle(PrsDim_LengthDimension)::DownCast(aAIS);
465             if (aDim.IsNull()) {
466               aDim = new PrsDim_LengthDimension(aPnt1, aPnt2, aPlane);
467               aAISObj = AISObjectPtr(new GeomAPI_AISObject());
468               aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
469             }
470             else {
471               aDim->SetMeasuredGeometry(aPnt1, aPnt2, aPlane);
472               aDim->SetFlyout(aDistance / 3.);
473             }
474           }
475           else {
476             aAISObj = AISObjectPtr(new GeomAPI_AISObject());
477             aDim = new PrsDim_LengthDimension(aPnt1, aPnt2, aPlane);
478             aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
479           }
480           aDim->SetFlyout(aDistance / 3.);
481         }
482       }
483     }
484   }
485   return aAISObj;
486 }
487
488 AISObjectPtr FeaturesPlugin_Measurement::radiusDimension(AISObjectPtr thePrevious)
489 {
490   AISObjectPtr aAISObj;
491   AttributeSelectionPtr aSelectedFeature = selection(CIRCULAR_OBJECT_ID());
492
493   GeomShapePtr aShape;
494   if (aSelectedFeature && aSelectedFeature->isInitialized()) {
495     aShape = aSelectedFeature->value();
496     if (!aShape && aSelectedFeature->context())
497       aShape = aSelectedFeature->context()->shape();
498   }
499   if (aShape.get()) {
500     TopoDS_Shape aShp = aShape->impl<TopoDS_Shape>();
501     if (thePrevious.get()) {
502       aAISObj = thePrevious;
503       Handle(AIS_InteractiveObject) aAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
504       Handle(PrsDim_RadiusDimension) aDim = Handle(PrsDim_RadiusDimension)::DownCast(aAIS);
505       if (aDim.IsNull()) {
506         aDim = new PrsDim_RadiusDimension(aShp);
507         aAISObj = AISObjectPtr(new GeomAPI_AISObject());
508         aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
509       } else
510         aDim->SetMeasuredGeometry(aShp);
511     } else {
512       aAISObj = AISObjectPtr(new GeomAPI_AISObject());
513       Handle(PrsDim_RadiusDimension) aDim = new PrsDim_RadiusDimension(aShp);
514       aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
515     }
516   }
517   return aAISObj;
518 }
519
520 AISObjectPtr FeaturesPlugin_Measurement::angleDimension(AISObjectPtr thePrevious)
521 {
522   AISObjectPtr aAISObj;
523   AttributeSelectionPtr aFirstFeature = selection(ANGLE_FROM_EDGE_ID());
524   GeomShapePtr aShape1;
525   GeomEdgePtr anEdge1;
526   if (aFirstFeature && aFirstFeature->isInitialized()) {
527     aShape1 = aFirstFeature->value();
528     if (!aShape1 && aFirstFeature->context())
529       aShape1 = aFirstFeature->context()->shape();
530   }
531   if (aShape1 && aShape1->isEdge())
532     anEdge1 = GeomEdgePtr(new GeomAPI_Edge(aShape1));
533
534   AttributeSelectionPtr aSecondFeature = selection(ANGLE_TO_EDGE_ID());
535   GeomShapePtr aShape2;
536   GeomEdgePtr anEdge2;
537   if (aSecondFeature && aSecondFeature->isInitialized()) {
538     aShape2 = aSecondFeature->value();
539     if (!aShape2 && aSecondFeature->context())
540       aShape2 = aSecondFeature->context()->shape();
541   }
542   if (aShape2 && aShape2->isEdge())
543     anEdge2 = GeomEdgePtr(new GeomAPI_Edge(aShape2));
544
545   if (anEdge1.get() && anEdge2.get()) {
546     TopoDS_Edge aTEdge1 = TopoDS::Edge(anEdge1->impl<TopoDS_Shape>());
547     TopoDS_Edge aTEdge2 = TopoDS::Edge(anEdge2->impl<TopoDS_Shape>());
548
549     Handle(PrsDim_AngleDimension) aDim;
550     if (thePrevious.get()) {
551       aAISObj = thePrevious;
552       Handle(AIS_InteractiveObject) aAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
553       aDim = Handle(PrsDim_AngleDimension)::DownCast(aAIS);
554       if (aDim.IsNull()) {
555         aDim = new PrsDim_AngleDimension(aTEdge1, aTEdge2);
556         aAISObj = AISObjectPtr(new GeomAPI_AISObject());
557         aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
558       } else
559         aDim->SetMeasuredGeometry(aTEdge1, aTEdge2);
560     } else {
561       aAISObj = AISObjectPtr(new GeomAPI_AISObject());
562       aDim = new PrsDim_AngleDimension(aTEdge1, aTEdge2);
563       aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
564     }
565   }
566   return aAISObj;
567 }
568
569 AISObjectPtr FeaturesPlugin_Measurement::angleByPointsDimension(AISObjectPtr thePrevious)
570 {
571   AISObjectPtr aAISObj;
572   GeomVertexPtr aVertex1 = selectionToVertex(selection(ANGLE_POINT1_ID()));
573   GeomVertexPtr aVertex2 = selectionToVertex(selection(ANGLE_POINT2_ID()));
574   GeomVertexPtr aVertex3 = selectionToVertex(selection(ANGLE_POINT3_ID()));
575
576   if (aVertex1.get() && aVertex2.get() && aVertex3.get()) {
577     GeomPointPtr aPoint1 = aVertex1->point();
578     GeomPointPtr aPoint2 = aVertex2->point();
579     GeomPointPtr aPoint3 = aVertex3->point();
580     gp_Pnt aPnt1(aPoint1->impl<gp_Pnt>());
581     gp_Pnt aPnt2(aPoint2->impl<gp_Pnt>());
582     gp_Pnt aPnt3(aPoint3->impl<gp_Pnt>());
583
584     if (aPnt1.IsEqual(aPnt2, Precision::Confusion()) ||
585       aPnt1.IsEqual(aPnt3, Precision::Confusion()) ||
586       aPnt2.IsEqual(aPnt3, Precision::Confusion()))
587       return thePrevious;
588
589     if (thePrevious.get()) {
590       aAISObj = thePrevious;
591       Handle(AIS_InteractiveObject) aAIS = aAISObj->impl<Handle(AIS_InteractiveObject)>();
592       Handle(PrsDim_AngleDimension) aDim = Handle(PrsDim_AngleDimension)::DownCast(aAIS);
593       if (aDim.IsNull()) {
594         aDim = new PrsDim_AngleDimension(aPnt1, aPnt2, aPnt3);
595         aAISObj = AISObjectPtr(new GeomAPI_AISObject());
596         aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
597       } else
598         aDim->SetMeasuredGeometry(aPnt1, aPnt2, aPnt3);
599     } else {
600       Handle(PrsDim_AngleDimension) aDim = new PrsDim_AngleDimension(aPnt1, aPnt2, aPnt3);
601       aAISObj = AISObjectPtr(new GeomAPI_AISObject());
602       aAISObj->setImpl(new Handle(AIS_InteractiveObject)(aDim));
603     }
604   }
605   return aAISObj;
606 }
607
608
609 void FeaturesPlugin_Measurement::setupDimension(AISObjectPtr theDim)
610 {
611   if (theDim.get()) {
612     Handle(AIS_InteractiveObject) aAIS = theDim->impl<Handle(AIS_InteractiveObject)>();
613     Handle(PrsDim_Dimension) aDim = Handle(PrsDim_Dimension)::DownCast(aAIS);
614     int aSize = Config_PropManager::integer("Visualization", "dimension_arrow_size");
615     int aTextSize = Config_PropManager::integer("Visualization", "dimension_value_size");
616     std::string aFont = Config_PropManager::string("Visualization", "dimension_font");
617
618     Handle(Prs3d_DimensionAspect) anAspect = aDim->DimensionAspect();
619     anAspect->MakeArrows3d(false);
620     anAspect->MakeText3d(false);
621     anAspect->MakeTextShaded(false);
622     anAspect->MakeUnitsDisplayed(false);
623     anAspect->MakeUnitsDisplayed(false);
624     anAspect->TextAspect()->SetFont(aFont.c_str());
625     anAspect->TextAspect()->SetHeight(aTextSize);
626     anAspect->ArrowAspect()->SetLength(aSize / mySceenScale);
627     anAspect->SetExtensionSize((aTextSize / mySceenScale + aSize) / 2.0);
628     aDim->SetDimensionAspect(anAspect);
629
630     aDim->SetZLayer(Graphic3d_ZLayerId_Top);
631     std::vector<int> aColor = Config_PropManager::color("Visualization", "sketch_dimension_color");
632     theDim->setColor(aColor[0], aColor[1], aColor[2]);
633   }
634 }