Salome HOME
Updated copyright comment
[modules/shaper.git] / src / SketcherPrs / SketcherPrs_LengthDimension.cpp
1 // Copyright (C) 2014-2024  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 "SketcherPrs_LengthDimension.h"
21 #include "SketcherPrs_Tools.h"
22 #include "SketcherPrs_DimensionStyle.h"
23
24 #include <SketchPlugin_Constraint.h>
25 #include <SketchPlugin_ConstraintLength.h>
26 #include <SketchPlugin_ConstraintDistance.h>
27 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
28 #include <SketchPlugin_ConstraintDistanceVertical.h>
29 #include <SketchPlugin_Line.h>
30 #include <SketchPlugin_Point.h>
31 #include <SketchPlugin_Circle.h>
32
33 #include <GeomDataAPI_Point2D.h>
34 #include <GeomAPI_Pnt.h>
35 #include <GeomAPI_XYZ.h>
36 #include <GeomAPI_Pnt2d.h>
37 #include <GeomAPI_Lin2d.h>
38
39 #include <ModelAPI_Data.h>
40 #include <ModelAPI_AttributeDouble.h>
41 #include <ModelAPI_AttributeInteger.h>
42
43
44 #define OCCT_28850_FIXED
45
46 /// Creates an aspect to be shown in length/radius dimension presentations
47 /// \return an instance of aspect
48 Handle(Prs3d_DimensionAspect) createDimensionAspect()
49 {
50   Handle(Prs3d_DimensionAspect) anAspect = new Prs3d_DimensionAspect();
51   anAspect->MakeArrows3d(false);
52   anAspect->MakeText3d(false);
53   anAspect->MakeTextShaded(false);
54   anAspect->MakeUnitsDisplayed(false);
55   anAspect->TextAspect()->SetHeight(SketcherPrs_Tools::getConfigTextHeight());
56   anAspect->ArrowAspect()->SetLength(SketcherPrs_Tools::getArrowSize());
57
58   return anAspect;
59 }
60
61 /// Update variable aspect parameters (depending on viewer scale)
62 /// \param theDimAspect an aspect to be changed
63 /// \param theDimValue an arrow value
64 /// \param theTextSize an arrow value
65 void updateArrows(Handle(Prs3d_DimensionAspect) theDimAspect,
66   double theDimValue, double theTextSize, SketcherPrs_Tools::LocationType theLocationType)
67 {
68   if (theLocationType == SketcherPrs_Tools::LOCATION_AUTOMATIC) {
69     double anArrowLength = theDimAspect->ArrowAspect()->Length();
70      // This is not realy correct way to get viewer scale.
71     double aViewerScale = (double) SketcherPrs_Tools::getConfigArrowSize() / anArrowLength;
72
73     if(theTextSize > ((theDimValue - 3 * SketcherPrs_Tools::getArrowSize()) * aViewerScale)) {
74       theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Left);
75       theDimAspect->SetArrowOrientation(Prs3d_DAO_External);
76       theDimAspect->SetExtensionSize(
77         (theTextSize / aViewerScale + SketcherPrs_Tools::getArrowSize()) / 2.0);
78     } else {
79       theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Center);
80       theDimAspect->SetArrowOrientation(Prs3d_DAO_Internal);
81     }
82   }
83   else if (theLocationType == SketcherPrs_Tools::LOCATION_RIGHT ||
84            theLocationType == SketcherPrs_Tools::LOCATION_LEFT) {
85     theDimAspect->SetTextHorizontalPosition(
86       theLocationType == SketcherPrs_Tools::LOCATION_LEFT ? Prs3d_DTHP_Left : Prs3d_DTHP_Right);
87     theDimAspect->SetArrowOrientation(Prs3d_DAO_External);
88
89     double anArrowLength = theDimAspect->ArrowAspect()->Length();
90     // This is not realy correct way to get viewer scale.
91     double aViewerScale = (double) SketcherPrs_Tools::getConfigArrowSize() / anArrowLength;
92     theDimAspect->SetExtensionSize(
93         (theTextSize / aViewerScale + SketcherPrs_Tools::getArrowSize()) / 2.0);
94   }
95   theDimAspect->TextAspect()->SetFont(Config_PropManager::string("Visualization",
96                                       "dimension_font").c_str());
97
98   theDimAspect->SetArrowTailSize(theDimAspect->ArrowAspect()->Length());
99   // The value of vertical aligment is sometimes changed
100   theDimAspect->TextAspect()->SetVerticalJustification(Graphic3d_VTA_CENTER);
101 }
102
103
104 static const gp_Pnt MyDefStart(0,0,0);
105 static const gp_Pnt MyDefEnd(1,0,0);
106 static const gp_Pln MyDefPln(gp_Pnt(0,0,0), gp_Dir(0,0,1));
107
108 IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_LengthDimension, PrsDim_LengthDimension);
109
110 SketcherPrs_LengthDimension::SketcherPrs_LengthDimension(ModelAPI_Feature* theConstraint,
111   SketchPlugin_Sketch* theSketcher)
112 : PrsDim_LengthDimension(MyDefStart, MyDefEnd, MyDefPln),
113   myConstraint(theConstraint),
114   mySketcher(theSketcher),
115   myFirstPoint(MyDefStart),
116   mySecondPoint(MyDefEnd),
117   myPlane(MyDefPln),
118   myDistance(1),
119   myValue(0., false, "")
120 {
121   SetDimensionAspect(createDimensionAspect());
122   myStyleListener = new SketcherPrs_DimensionStyle();
123
124   setDirection(theConstraint, plane());
125 }
126
127 SketcherPrs_LengthDimension::~SketcherPrs_LengthDimension()
128 {
129   delete myStyleListener;
130 }
131
132 bool SketcherPrs_LengthDimension::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
133                                          const std::shared_ptr<GeomAPI_Ax3>& thePlane)
134 {
135   gp_Pnt2d aPnt1, aPnt2;
136   return readyToDisplay(theConstraint, thePlane, aPnt1, aPnt2);
137 }
138
139 static bool isEqualPoints(ModelAPI_Feature* theConstraint,
140   const gp_Pnt2d& theP1, const gp_Pnt2d& theP2)
141 {
142   bool isEqual = false;
143   if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
144     isEqual = Abs(theP1.X() - theP2.X()) < Precision::Confusion();
145   else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
146     isEqual = Abs(theP1.Y() - theP2.Y()) < Precision::Confusion();
147   else {
148     isEqual = theP1.SquareDistance(theP2) < Precision::SquareConfusion();
149   }
150   return isEqual;
151 }
152
153 void SketcherPrs_LengthDimension::Compute(
154   const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
155   const Handle(Prs3d_Presentation)& thePresentation,
156   const Standard_Integer theMode)
157 {
158   if (!plane().get())
159     return;
160   gp_Pnt2d aP1, aP2;
161   bool aReadyToDisplay = readyToDisplay(myConstraint, plane(), aP1, aP2);
162   if (aReadyToDisplay) {
163     if (isEqualPoints(myConstraint, aP1, aP2)) {
164       // adjust points to draw the dimension presentation
165       std::shared_ptr<GeomDataAPI_Dir> aDirAttr = std::dynamic_pointer_cast<GeomDataAPI_Dir>(
166           myConstraint->attribute(SketchPlugin_ConstraintDistance::DIRECTION_ID()));
167       double x = 0.0, y = 0.0;
168       if (aDirAttr && aDirAttr->isInitialized()) {
169         x = aDirAttr->x();
170         y = aDirAttr->y();
171         if (x == 0.0 && y == 0.0)
172           x = 1.0;
173       }
174       else if (myConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
175         y = 1.0;
176       else
177         x = 1.0;
178
179       gp_XY aDir(x, y);
180       aP1.ChangeCoord().Add(aDir * (-Precision::Confusion()));
181       aP2.ChangeCoord().Add(aDir * Precision::Confusion());
182     }
183
184     myFirstPoint = plane()->to3D(aP1.X(), aP1.Y())->impl<gp_Pnt>();
185     mySecondPoint = plane()->to3D(aP2.X(), aP2.Y())->impl<gp_Pnt>();
186
187     myDistance = SketcherPrs_Tools::getFlyoutDistance(myConstraint);
188     myPlane = gp_Pln(plane()->impl<gp_Ax3>());
189
190     DataPtr aData = myConstraint->data();
191     AttributeDoublePtr anAttributeValue;
192     if (myConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
193         myConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
194       anAttributeValue = aData->real(SketchPlugin_ConstraintDistanceAlongDir::DISTANCE_VALUE_ID());
195     else
196       anAttributeValue = aData->real(SketchPlugin_Constraint::VALUE());
197     myValue.init(anAttributeValue);
198
199     setDirection(myConstraint, plane());
200   }
201
202   // compute flyout distance
203   SetFlyout(myDistance);
204   SetMeasuredGeometry(myFirstPoint, mySecondPoint, myPlane);
205
206   // Update variable aspect parameters (depending on viewer scale)
207   double aTextSize = 0.0;
208   GetValueString(aTextSize);
209
210   std::string aLocationAttribute;
211   std::string aConstraintKind = myConstraint->getKind();
212   if (aConstraintKind == SketchPlugin_ConstraintLength::ID())
213     aLocationAttribute = SketchPlugin_ConstraintLength::LOCATION_TYPE_ID();
214   else if (aConstraintKind == SketchPlugin_ConstraintDistance::ID())
215     aLocationAttribute = SketchPlugin_ConstraintDistance::LOCATION_TYPE_ID();
216   else if (aConstraintKind == SketchPlugin_ConstraintDistanceHorizontal::ID())
217     aLocationAttribute = SketchPlugin_ConstraintDistanceHorizontal::LOCATION_TYPE_ID();
218   else if (aConstraintKind == SketchPlugin_ConstraintDistanceVertical::ID())
219     aLocationAttribute = SketchPlugin_ConstraintDistanceVertical::LOCATION_TYPE_ID();
220
221   AttributeIntegerPtr aLocAttr = std::dynamic_pointer_cast<ModelAPI_AttributeInteger>
222     (myConstraint->data()->attribute(aLocationAttribute));
223   SketcherPrs_Tools::LocationType aLocationType = aLocAttr->isInitialized() ?
224     (SketcherPrs_Tools::LocationType)(aLocAttr->value()) : SketcherPrs_Tools::LOCATION_AUTOMATIC;
225   updateArrows(DimensionAspect(), GetValue(), aTextSize, aLocationType);
226
227   // Update text visualization: parameter value or parameter text
228   myStyleListener->updateDimensions(this, myValue);
229
230   PrsDim_LengthDimension::Compute(thePresentationManager, thePresentation, theMode);
231
232   if (!aReadyToDisplay)
233     SketcherPrs_Tools::sendEmptyPresentationError(myConstraint,
234                               "An empty AIS presentation: SketcherPrs_LengthDimension");
235 }
236
237 bool SketcherPrs_LengthDimension::readyToDisplay(ModelAPI_Feature* theConstraint,
238                                                  const std::shared_ptr<GeomAPI_Ax3>& thePlane,
239                                                  gp_Pnt2d& thePnt1, gp_Pnt2d& thePnt2)
240 {
241   if (!thePlane)
242     return false;
243
244   DataPtr aData = theConstraint->data();
245   if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
246     // The constraint is length
247     std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
248       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
249       (aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
250     if (!anAttr)
251       return false;
252
253     FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object());
254     if (!aFeature || aFeature->getKind() != SketchPlugin_Line::ID())
255       return false;
256
257     // Get geometry of the object
258     DataPtr aLineData = aFeature->data();
259     std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
260       std::dynamic_pointer_cast<GeomDataAPI_Point2D>
261       (aLineData->attribute(SketchPlugin_Line::START_ID()));
262     std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
263       std::dynamic_pointer_cast<GeomDataAPI_Point2D>
264       (aLineData->attribute(SketchPlugin_Line::END_ID()));
265     thePnt1 = gp_Pnt2d(aStartPoint->x(), aStartPoint->y());
266     thePnt2 = gp_Pnt2d(aEndPoint->x(), aEndPoint->y());
267     return true;
268
269   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
270              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
271              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
272     // The constraint is distance
273     std::shared_ptr<GeomDataAPI_Point2D> aPoint_A = SketcherPrs_Tools::getFeaturePoint(
274         aData, SketchPlugin_Constraint::ENTITY_A(), thePlane);
275     std::shared_ptr<GeomDataAPI_Point2D> aPoint_B = SketcherPrs_Tools::getFeaturePoint(
276         aData, SketchPlugin_Constraint::ENTITY_B(), thePlane);
277
278     std::shared_ptr<GeomAPI_Pnt2d> aPnt_A;
279     std::shared_ptr<GeomAPI_Pnt2d> aPnt_B;
280     if (aPoint_A && aPoint_B) {
281       // Both objects are points
282       aPnt_A = aPoint_A->pnt();
283       aPnt_B = aPoint_B->pnt();
284     } else if (!aPoint_A && aPoint_B) {
285       // First object is line
286       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
287           aData, SketchPlugin_Constraint::ENTITY_A());
288       if (aLine) {
289         aPnt_B = aPoint_B->pnt();
290         aPnt_A = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_B);
291       }
292     } else if (aPoint_A && !aPoint_B) {
293       // Second object is line
294       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
295           aData, SketchPlugin_Constraint::ENTITY_B());
296       if (aLine) {
297         aPnt_A = aPoint_A->pnt();
298         aPnt_B = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_A);
299       }
300     }
301     if (!aPnt_A || !aPnt_B) // Objects not found
302       return false;
303
304     // Get points from these object
305     thePnt1 = gp_Pnt2d(aPnt_A->x(), aPnt_A->y());
306     thePnt2 = gp_Pnt2d(aPnt_B->x(), aPnt_B->y());
307     return true;
308   }
309   return false;
310 }
311
312
313
314 void SketcherPrs_LengthDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
315                                                    const Standard_Integer theMode)
316 {
317   // Map the application selection modes to standard ones
318   Standard_Integer aMode;
319   switch (theMode) {
320   case 0: // we should use selection of all objects
321     aMode = 0;
322     break;
323   case SketcherPrs_Tools::Sel_Dimension_All:
324     aMode = 0;
325     break;
326   case SketcherPrs_Tools::Sel_Dimension_Line:
327     aMode = 1;
328     break;
329   case SketcherPrs_Tools::Sel_Dimension_Text:
330     aMode = 2;
331     break;
332   default: {
333     // there are own selection modes, so the others should be ignored
334     // otherwise, the text selection appears in the viewer
335     return;
336   }
337   }
338   SetSelToleranceForText2d(SketcherPrs_Tools::getArrowSize()/5.);
339   PrsDim_LengthDimension::ComputeSelection(aSelection, aMode);
340 }
341
342 void SketcherPrs_LengthDimension::setDirection(ModelAPI_Feature* theConstraint,
343                                                const std::shared_ptr<GeomAPI_Ax3>& thePlane)
344 {
345 #ifdef OCCT_28850_FIXED
346   if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID())
347     SetDirection(thePlane->dirX()->impl<gp_Dir>(), true);
348   else if (theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID())
349     SetDirection(thePlane->dirY()->impl<gp_Dir>(), true);
350 #endif
351 }