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