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