Salome HOME
Task 2.7. Horizontal and Vertical Distance constraint
[modules/shaper.git] / src / SketchPlugin / SketchPlugin_ConstraintDistanceHorizontal.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D -->
2
3 // File:    SketchPlugin_ConstraintDistanceHorizontal.cpp
4 // Created: 2 May 2017
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchPlugin_ConstraintDistanceHorizontal.h>
8
9 #include <SketcherPrs_Tools.h>
10 #include <SketcherPrs_Factory.h>
11
12 #include <GeomAPI_Dir2d.h>
13 #include <GeomAPI_XY.h>
14 #include <GeomDataAPI_Point2D.h>
15
16 #include <ModelAPI_AttributeDouble.h>
17
18 const double tolerance = 1e-7;
19
20
21 SketchPlugin_ConstraintDistanceHorizontal::SketchPlugin_ConstraintDistanceHorizontal()
22   : SketchPlugin_ConstraintDistance()
23 {
24 }
25
26 //*************************************************************************************
27 void SketchPlugin_ConstraintDistanceHorizontal::initAttributes()
28 {
29   data()->addAttribute(SketchPlugin_Constraint::VALUE(), ModelAPI_AttributeDouble::typeId());
30   data()->addAttribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT(), GeomDataAPI_Point2D::typeId());
31   data()->addAttribute(SketchPlugin_Constraint::ENTITY_A(), ModelAPI_AttributeRefAttr::typeId());
32   data()->addAttribute(SketchPlugin_Constraint::ENTITY_B(), ModelAPI_AttributeRefAttr::typeId());
33 }
34
35 //*************************************************************************************
36 void SketchPlugin_ConstraintDistanceHorizontal::execute()
37 {
38   AttributeDoublePtr anAttrValue = real(SketchPlugin_Constraint::VALUE());
39   if (anAttrValue->isInitialized() || !areAttributesInitialized())
40     return;
41
42   double aDistance = calculateCurrentDistance();
43   anAttrValue->setValue(aDistance);
44 }
45
46 //*************************************************************************************
47 AISObjectPtr SketchPlugin_ConstraintDistanceHorizontal::getAISObject(AISObjectPtr thePrevious)
48 {
49   if (!sketch())
50     return thePrevious;
51
52   AISObjectPtr anAIS = SketcherPrs_Factory::lengthDimensionConstraint(this,
53                                                                       sketch()->coordinatePlane(),
54                                                                       thePrevious);
55   return anAIS;
56 }
57
58 //*************************************************************************************
59 void SketchPlugin_ConstraintDistanceHorizontal::move(double theDeltaX, double theDeltaY)
60 {
61   std::shared_ptr<ModelAPI_Data> aData = data();
62   if (!aData->isValid())
63     return;
64
65   // Recalculate a shift of flyout point in terms of local coordinates
66   std::shared_ptr<GeomAPI_XY> aDir(new GeomAPI_XY(theDeltaX, theDeltaY));
67   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
68   std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
69       data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
70   std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
71       data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
72
73   if (!aPointA || !aPointB)
74     return;
75
76   std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
77   std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
78
79   std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
80   double dX = aDir->dot(aLineDir->xy());
81   double dY = -aDir->cross(aLineDir->xy());
82
83   std::shared_ptr<GeomDataAPI_Point2D> aPoint = std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
84       aData->attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
85   myFlyoutUpdate = true;
86   if (aPoint->isInitialized()) {
87     aPoint->setValue(aPoint->x() + dX, aPoint->y() + dY);
88   } else {
89     aPoint->setValue(dX, dY);
90   }
91   myFlyoutUpdate = false;
92 }
93
94 double SketchPlugin_ConstraintDistanceHorizontal::calculateCurrentDistance()
95 {
96   std::shared_ptr<ModelAPI_Data> aData = data();
97   std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
98   std::shared_ptr<GeomDataAPI_Point2D> aPointA =
99     SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_A(), aPlane);
100   std::shared_ptr<GeomDataAPI_Point2D> aPointB =
101       SketcherPrs_Tools::getFeaturePoint(aData, SketchPlugin_Constraint::ENTITY_B(), aPlane);
102
103   return aPointB->x() - aPointA->x();
104 }
105
106 void SketchPlugin_ConstraintDistanceHorizontal::attributeChanged(const std::string& theID)
107 {
108   if (theID == SketchPlugin_Constraint::ENTITY_A() ||
109       theID == SketchPlugin_Constraint::ENTITY_B())
110   {
111     AttributeDoublePtr aValueAttr = real(SketchPlugin_Constraint::VALUE());
112     if (!aValueAttr->isInitialized() && areAttributesInitialized()) {
113       // only if it is not initialized, try to compute the current value
114       double aDistance = calculateCurrentDistance();
115       aValueAttr->setValue(aDistance);
116     }
117   } else if (theID == SketchPlugin_Constraint::FLYOUT_VALUE_PNT() && !myFlyoutUpdate) {
118     myFlyoutUpdate = true;
119     // Recalculate flyout point in local coordinates of the distance constraint:
120     // the X coordinate is a length of projection of the flyout point on the
121     //                  line binding two distanced points
122     //                  or a line of projection of the distanced point onto the distanced segment
123     // the Y coordinate is a distance from the flyout point to the line
124     std::shared_ptr<GeomDataAPI_Point2D> aFlyoutAttr =
125         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(
126         attribute(SketchPlugin_Constraint::FLYOUT_VALUE_PNT()));
127     std::shared_ptr<GeomAPI_Pnt2d> aFlyoutPnt = aFlyoutAttr->pnt();
128
129     std::shared_ptr<GeomAPI_Ax3> aPlane = SketchPlugin_Sketch::plane(sketch());
130     std::shared_ptr<GeomDataAPI_Point2D> aPointA = SketcherPrs_Tools::getFeaturePoint(
131         data(), SketchPlugin_Constraint::ENTITY_A(), aPlane);
132     std::shared_ptr<GeomDataAPI_Point2D> aPointB = SketcherPrs_Tools::getFeaturePoint(
133         data(), SketchPlugin_Constraint::ENTITY_B(), aPlane);
134
135     std::shared_ptr<GeomAPI_XY> aStartPnt = aPointA->pnt()->xy();
136     std::shared_ptr<GeomAPI_XY> aEndPnt = aPointB->pnt()->xy();
137
138     if (aEndPnt->distance(aStartPnt) < tolerance)
139       return;
140
141     std::shared_ptr<GeomAPI_Dir2d> aLineDir(new GeomAPI_Dir2d(aEndPnt->decreased(aStartPnt)));
142     std::shared_ptr<GeomAPI_XY> aFlyoutDir = aFlyoutPnt->xy()->decreased(aStartPnt);
143
144     double X = aFlyoutDir->dot(aLineDir->xy());
145     double Y = -aFlyoutDir->cross(aLineDir->xy());
146     aFlyoutAttr->setValue(X, Y);
147     myFlyoutUpdate = false;
148   }
149 }