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