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