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