]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchPlugin/SketchPlugin_ConstraintDistance.cpp
Salome HOME
Set the orientation of the Distance constraint
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintDistance.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 "SketchPlugin_ConstraintDistance.h"
22 #include <SketchPlugin_Point.h>
23 #include <SketchPlugin_Circle.h>
24 #include <SketchPlugin_Line.h>
25
26 #include <SketcherPrs_Tools.h>
27 #include <SketcherPrs_Factory.h>
28
29 #include <GeomAPI_Dir2d.h>
30 #include <GeomAPI_Lin2d.h>
31 #include <GeomAPI_Pnt2d.h>
32 #include <GeomAPI_XY.h>
33 #include <GeomDataAPI_Point2D.h>
34
35 #include <ModelAPI_AttributeDouble.h>
36 #include <ModelAPI_Data.h>
37
38 #include <Config_PropManager.h>
39
40 #include <math.h>
41
42 const double tolerance = 1e-7;
43
44
45 SketchPlugin_ConstraintDistance::SketchPlugin_ConstraintDistance()
46 {
47   myFlyoutUpdate = false;
48 }
49
50 //*************************************************************************************
51 void SketchPlugin_ConstraintDistance::initAttributes()
52 {
53   data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
54   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
55   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
56   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
57   data()->addAttribute(SIGNED(), ModelAPI_AttributeBoolean::typeId());
58 }
59
60 void SketchPlugin_ConstraintDistance::colorConfigInfo(std::string& theSection, std::string& theName,
61                                                       std::string& theDefault)
62 {
63   theSection = "Visualization";
64   theName = "sketch_dimension_color";
65   theDefault = SKETCH_DIMENSION_COLOR;
66 }
67
68 //*************************************************************************************
69 void SketchPlugin_ConstraintDistance::execute()
70 {
71   std::shared_ptr<ModelAPI_Data> aData = data();
72   AttributeDoublePtr anAttrValue = std::dynamic_pointer_cast<ModelAPI_AttributeDouble>(
73       aData->attribute(SketchPlugin_Constraint::VALUE()));
74
75   if(anAttrValue->isInitialized())
76     return;
77
78   double aDistance = calculateCurrentDistance();
79   if(aDistance >= 0)
80     anAttrValue->setValue(aDistance);
81 }
82
83 //*************************************************************************************
84 AISObjectPtr SketchPlugin_ConstraintDistance::getAISObject(AISObjectPtr thePrevious)
85 {
86   if (!sketch())
87     return thePrevious;
88
89   AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
90                                                                       sketch()->coordinatePlane(),
91                                                                       thePrevious);
92   return anAIS;
93 }
94
95 //*************************************************************************************
96 void SketchPlugin_ConstraintDistance::move(double theDeltaX, double theDeltaY)
97 {
98   std::shared_ptr<ModelAPI_Data> aData = data();
99   if (!aData->isValid())
100     return;
101
102   // Recalculate a shift of flyout point in terms of local coordinates
103   std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
104   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
105   std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
106       data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
107   std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
108       data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
109
110   std::shared_ptr<GeomAPI_XY> aStartPnt;
111   std::shared_ptr<GeomAPI_XY> aEndPnt;
112   if (aPointA && aPointB) {
113     aStartPnt = aPointA->pnt()->xy();
114     aEndPnt = aPointB->pnt()->xy();
115   } else if (aPointA) {
116     FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
117         SketchPlugin_Constraint::ENTITY_B());
118     if (!aLine)
119       return;
120     std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointA->pnt();
121     aStartPnt = aPoint->xy();
122     aEndPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
123   } else if (aPointB) {
124     FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
125         SketchPlugin_Constraint::ENTITY_A());
126     if (!aLine)
127       return;
128     std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointB->pnt();
129     aStartPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
130     aEndPnt = aPoint->xy();
131   } else
132     return;
133
134   std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
135   double dX = aDir->dot(aLineDir->xy());
136   double dY = -aDir->cross(aLineDir->xy());
137
138   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
139       aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
140   myFlyoutUpdate = true;
141   if (aPoint->isInitialized()) {
142     aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
143   } else {
144     aPoint->setValue(dX, dY);
145   }
146   myFlyoutUpdate = false;
147 }
148
149 double SketchPlugin_ConstraintDistance::calculateCurrentDistance()
150 {
151   double aDistance = -1.;
152
153   std::shared_ptr<ModelAPI_Data> aData = data();
154   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
155   std::shared_ptr<GeomDataAPI_Point2D> aPointA =
156     SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
157   std::shared_ptr<GeomDataAPI_Point2D> aPointB =
158       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
159
160   if (aPointA.get() && aPointB.get()) {  // both points
161     aDistance = aPointA->pnt()->distance(aPointB->pnt());
162   } else {
163     FeaturePtr aLineFeature;
164     std::shared_ptr<SketchPlugin_Line> aLine;
165     if (!aPointA.get() && aPointB.get()) {  //Line and point
166       aLineFeature = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
167       aLine = std::dynamic_pointer_cast<SketchPlugin_Line>(aLineFeature);
168       if (aLine.get()) {
169         aDistance = aLine->distanceToPoint(aPointB->pnt());
170       }
171     } else if (aPointA.get() && !aPointB.get()) {  // Point and line
172       aLineFeature = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
173       aLine = std::dynamic_pointer_cast<SketchPlugin_Line>(aLineFeature);
174       if (aLine.get()) {
175         aDistance = aLine->distanceToPoint(aPointA->pnt());
176       }
177     }
178   }
179   return aDistance;
180 }
181
182 bool SketchPlugin_ConstraintDistance::areAttributesInitialized()
183 {
184   std::shared_ptr<ModelAPI_Data> aData = data();
185   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
186   std::shared_ptr<GeomDataAPI_Point2D> aPointA =
187       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
188   std::shared_ptr<GeomDataAPI_Point2D> aPointB =
189       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
190
191   if (!aPointA && !aPointB)
192     return false;
193   else if (aPointA || aPointB) {
194     FeaturePtr aLine;
195     if (!aPointA)
196       aLine = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_A());
197     else if (!aPointB)
198       aLine = SketcherPrs_Tools::getFeatureLine(aData, SketchPlugin_Constraint::ENTITY_B());
199     else // both points are initialized
200       return true;
201
202     if (!aLine || aLine->getKind() != SketchPlugin_Line::ID())
203       return false;
204   }
205   return true;
206 }
207
208 void SketchPlugin_ConstraintDistance::attributeChanged(const std::string& theID)
209 {
210   if (theID == SketchPlugin_Constraint::ENTITY_A() ||
211       theID == SketchPlugin_Constraint::ENTITY_B())
212   {
213     std::shared_ptr<ModelAPI_AttributeDouble> aValueAttr = std::dynamic_pointer_cast<
214         ModelAPI_AttributeDouble>(data()->attribute(SketchPlugin_Constraint::VALUE()));
215     if (!aValueAttr->isInitialized()) {
216       // only if it is not initialized, try to compute the current value
217       double aDistance = calculateCurrentDistance();
218       if (aDistance > 0) { // set as value the length of updated references
219         aValueAttr->setValue(aDistance);
220       }
221     }
222   } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
223     myFlyoutUpdate = true;
224     // Recalculate flyout point in local coordinates of the distance constraint:
225     // the X coordinate is a length of projection of the flyout point on the
226     //                  line binding two distanced points
227     //                  or a line of projection of the distanced point onto the distanced segment
228     // the Y coordinate is a distance from the flyout point to the line
229     std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
230         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
231         attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
232     std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
233
234     std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
235     std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
236         data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
237     std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
238         data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
239
240     std::shared_ptr<GeomAPI_XY> aStartPnt;
241     std::shared_ptr<GeomAPI_XY> aEndPnt;
242     if (aPointA && aPointB) {
243       aStartPnt = aPointA->pnt()->xy();
244       aEndPnt = aPointB->pnt()->xy();
245     } else if (aPointA) {
246       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
247           SketchPlugin_Constraint::ENTITY_B());
248       if (!aLine)
249         return;
250       std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointA->pnt();
251       aStartPnt = aPoint->xy();
252       aEndPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
253     } else if (aPointB) {
254       FeaturePtr aLine = SketcherPrs_Tools::getFeatureLine(data(),
255           SketchPlugin_Constraint::ENTITY_A());
256       if (!aLine)
257         return;
258       std::shared_ptr<GeomAPI_Pnt2d> aPoint = aPointB->pnt();
259       aStartPnt = SketcherPrs_Tools::getProjectionPoint(aLine, aPoint)->xy();
260       aEndPnt = aPoint->xy();
261     } else
262       return;
263
264     if (aEndPnt->distance(aStartPnt) < tolerance)
265       return;
266
267     std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
268     std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
269
270     double X = aFlyoutDir->dot(aLineDir->xy());
271     double Y = -aFlyoutDir->cross(aLineDir->xy());
272     aFlyoutAttr->setValue(X, Y);
273     myFlyoutUpdate = false;
274   }
275 }
276