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