Salome HOME
Merge branch 'master' into cgt/devCEA
[modules/shaper.git] / src / SketcherPrs / SketcherPrs_LengthDimension.cpp
1 // Copyright (C) 2014-2017  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
18 // email : webmaster.salome@opencascade.com<mailto:webmaster.salome@opencascade.com>
19 //
20
21 #include "SketcherPrs_LengthDimension.h"
22 #include "SketcherPrs_Tools.h"
23 #include "SketcherPrs_DimensionStyleListener.h"
24
25 #include <SketchPlugin_Constraint.h>
26 #include <SketchPlugin_ConstraintLength.h>
27 #include <SketchPlugin_ConstraintDistance.h>
28 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
29 #include <SketchPlugin_ConstraintDistanceVertical.h>
30 #include <SketchPlugin_Line.h>
31 #include <SketchPlugin_Point.h>
32 #include <SketchPlugin_Circle.h>
33
34 #include <GeomDataAPI_Point2D.h>
35 #include <GeomAPI_Pnt.h>
36 #include <GeomAPI_XYZ.h>
37 #include <GeomAPI_Pnt2d.h>
38 #include <GeomAPI_Lin2d.h>
39
40 #include <ModelAPI_Data.h>
41 #include <ModelAPI_AttributeDouble.h>
42
43 #include <AIS_DisplaySpecialSymbol.hxx>
44
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::getDefaultTextHeight());
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)
67 {
68   double anArrowLength = theDimAspect->ArrowAspect()->Length();
69    // This is not realy correct way to get viewer scale.
70   double aViewerScale = (double) SketcherPrs_Tools::getDefaultArrowSize() / anArrowLength;
71
72   if(theTextSize > ((theDimValue - 3 * SketcherPrs_Tools::getArrowSize()) * aViewerScale)) {
73     theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Left);
74     theDimAspect->SetArrowOrientation(Prs3d_DAO_External);
75     theDimAspect->SetExtensionSize(
76       (theTextSize / aViewerScale + SketcherPrs_Tools::getArrowSize()) / 2.0);
77   } else {
78     theDimAspect->SetTextHorizontalPosition(Prs3d_DTHP_Center);
79     theDimAspect->SetArrowOrientation(Prs3d_DAO_Internal);
80   }
81   theDimAspect->SetArrowTailSize(theDimAspect->ArrowAspect()->Length());
82   // The value of vertical aligment is sometimes changed
83   theDimAspect->TextAspect()->SetVerticalJustification(Graphic3d_VTA_CENTER);
84 }
85
86
87 static const gp_Pnt MyDefStart(0,0,0);
88 static const gp_Pnt MyDefEnd(1,0,0);
89 static const gp_Pln MyDefPln(gp_Pnt(0,0,0), gp_Dir(0,0,1));
90
91 IMPLEMENT_STANDARD_RTTIEXT(SketcherPrs_LengthDimension, AIS_LengthDimension);
92
93 SketcherPrs_LengthDimension::SketcherPrs_LengthDimension(ModelAPI_Feature* theConstraint,
94                                               const std::shared_ptr<GeomAPI_Ax3>& thePlane)
95 : AIS_LengthDimension(MyDefStart, MyDefEnd, MyDefPln),
96   myConstraint(theConstraint),
97   mySketcherPlane(thePlane),
98   myFirstPoint(MyDefStart),
99   mySecondPoint(MyDefEnd),
100   myPlane(MyDefPln),
101   myDistance(1),
102   myValue(0., false, "")
103 {
104   SetDimensionAspect(createDimensionAspect());
105   myStyleListener = new SketcherPrs_DimensionStyleListener();
106 }
107
108 SketcherPrs_LengthDimension::~SketcherPrs_LengthDimension()
109 {
110   delete myStyleListener;
111 }
112
113 bool SketcherPrs_LengthDimension::IsReadyToDisplay(ModelAPI_Feature* theConstraint,
114                                          const std::shared_ptr<GeomAPI_Ax3>& thePlane)
115 {
116   gp_Pnt aPnt1, aPnt2;
117   return readyToDisplay(theConstraint, thePlane, aPnt1, aPnt2);
118 }
119
120 void SketcherPrs_LengthDimension::Compute(
121   const Handle(PrsMgr_PresentationManager3d)& thePresentationManager,
122   const Handle(Prs3d_Presentation)& thePresentation,
123   const Standard_Integer theMode)
124 {
125   gp_Pnt aPnt1, aPnt2;
126   bool aReadyToDisplay = readyToDisplay(myConstraint, mySketcherPlane, aPnt1, aPnt2);
127   if (aReadyToDisplay) {
128     myFirstPoint = aPnt1;
129     mySecondPoint = aPnt2;
130
131     myDistance = SketcherPrs_Tools::getFlyoutDistance(myConstraint);
132     myPlane = gp_Pln(mySketcherPlane->impl<gp_Ax3>());
133
134     DataPtr aData = myConstraint->data();
135     AttributeDoublePtr anAttributeValue = aData->real(SketchPlugin_Constraint::VALUE());
136     myValue.init(anAttributeValue);
137   }
138
139   // compute flyout distance
140   SetFlyout(myDistance);
141   SetMeasuredGeometry(myFirstPoint, mySecondPoint, myPlane);
142
143   // Update variable aspect parameters (depending on viewer scale)
144   double aTextSize = 0.0;
145   GetValueString(aTextSize);
146
147   updateArrows(DimensionAspect(), GetValue(), aTextSize);
148
149   // Update text visualization: parameter value or parameter text
150   myStyleListener->updateDimensions(this, myValue);
151
152   AIS_LengthDimension::Compute(thePresentationManager, thePresentation, theMode);
153
154   if (!aReadyToDisplay)
155     SketcherPrs_Tools::sendEmptyPresentationError(myConstraint,
156                               "An empty AIS presentation: SketcherPrs_LengthDimension");
157 }
158
159 bool SketcherPrs_LengthDimension::readyToDisplay(ModelAPI_Feature* theConstraint,
160                                                  const std::shared_ptr<GeomAPI_Ax3>& thePlane,
161                                                  gp_Pnt& thePnt1, gp_Pnt& thePnt2)
162 {
163   DataPtr aData = theConstraint->data();
164   if (theConstraint->getKind() == SketchPlugin_ConstraintLength::ID()) {
165     // The constraint is length
166     std::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
167       std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>
168       (aData->attribute(SketchPlugin_Constraint::ENTITY_A()));
169     if (!anAttr)
170       return false;
171
172     FeaturePtr aFeature = ModelAPI_Feature::feature(anAttr->object());
173     if (!aFeature || aFeature->getKind() != SketchPlugin_Line::ID())
174       return false;
175
176     // Get geometry of the object
177     DataPtr aLineData = aFeature->data();
178     std::shared_ptr<GeomDataAPI_Point2D> aStartPoint =
179       std::dynamic_pointer_cast<GeomDataAPI_Point2D>
180       (aLineData->attribute(SketchPlugin_Line::START_ID()));
181     std::shared_ptr<GeomDataAPI_Point2D> aEndPoint =
182       std::dynamic_pointer_cast<GeomDataAPI_Point2D>
183       (aLineData->attribute(SketchPlugin_Line::END_ID()));
184     thePnt1 = thePlane->to3D(aStartPoint->x(), aStartPoint->y())->impl<gp_Pnt>();
185     thePnt2 = thePlane->to3D(aEndPoint->x(), aEndPoint->y())->impl<gp_Pnt>();
186     return true;
187
188   } else if (theConstraint->getKind() == SketchPlugin_ConstraintDistance::ID() ||
189              theConstraint->getKind() == SketchPlugin_ConstraintDistanceHorizontal::ID() ||
190              theConstraint->getKind() == SketchPlugin_ConstraintDistanceVertical::ID()) {
191     // The constraint is distance
192     std::shared_ptr<GeomDataAPI_Point2D> aPoint_A = SketcherPrs_Tools::getFeaturePoint(
193         aData, SketchPlugin_Constraint::ENTITY_A(), thePlane);
194     std::shared_ptr<GeomDataAPI_Point2D> aPoint_B = SketcherPrs_Tools::getFeaturePoint(
195         aData, SketchPlugin_Constraint::ENTITY_B(), thePlane);
196
197     std::shared_ptr<GeomAPI_Pnt2d> aPnt_A;
198     std::shared_ptr<GeomAPI_Pnt2d> aPnt_B;
199     if (aPoint_A && aPoint_B) {
200       // Both objects are points
201       aPnt_A = aPoint_A->pnt();
202       aPnt_B = aPoint_B->pnt();
203     } else if (!aPoint_A && aPoint_B) {
204       // First object is line
205       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
206           aData, SketchPlugin_Constraint::ENTITY_A());
207       if (aLine) {
208         aPnt_B = aPoint_B->pnt();
209         aPnt_A = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_B);
210       }
211     } else if (aPoint_A && !aPoint_B) {
212       // Second object is line
213       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(
214           aData, SketchPlugin_Constraint::ENTITY_B());
215       if (aLine) {
216         aPnt_A = aPoint_A->pnt();
217         aPnt_B = SketcherPrs_Tools::getProjectionPoint(aLine, aPnt_A);
218       }
219     }
220     if (!aPnt_A || !aPnt_B) // Objects not found
221       return false;
222
223     // Get points from these object
224     std::shared_ptr<GeomAPI_Pnt> aPoint1 = thePlane->to3D(aPnt_A->x(), aPnt_A->y());
225     std::shared_ptr<GeomAPI_Pnt> aPoint2 = thePlane->to3D(aPnt_B->x(), aPnt_B->y());
226     thePnt1 = aPoint1->impl<gp_Pnt>();
227     thePnt2 = aPoint2->impl<gp_Pnt>();
228     return true;
229   }
230   return false;
231 }
232
233
234
235 void SketcherPrs_LengthDimension::ComputeSelection(const Handle(SelectMgr_Selection)& aSelection,
236                                                    const Standard_Integer theMode)
237 {
238   // Map the application selection modes to standard ones
239   Standard_Integer aMode;
240   switch (theMode) {
241   case 0: // we should use selection of all objects
242     aMode = 0;
243     break;
244   case SketcherPrs_Tools::Sel_Dimension_All:
245     aMode = 0;
246     break;
247   case SketcherPrs_Tools::Sel_Dimension_Line:
248     aMode = 1;
249     break;
250   case SketcherPrs_Tools::Sel_Dimension_Text:
251     aMode = 2;
252     break;
253   default: {
254     // there are own selection modes, so the others should be ignored
255     // otherwise, the text selection appears in the viewer
256     return;
257   }
258   }
259   SetSelToleranceForText2d(SketcherPrs_Tools::getTextHeight());
260   AIS_LengthDimension::ComputeSelection(aSelection, aMode);
261 }