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