Salome HOME
Update constraints defined by parameters (issue #976)
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintParametric.cpp
1 #include <SketchSolver_ConstraintParametric.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Group.h>
4
5 #include <GeomDataAPI_Point2D.h>
6
7 SketchSolver_ConstraintParametric::SketchSolver_ConstraintParametric(AttributePtr theAttribute)
8   : SketchSolver_ConstraintRigid(ConstraintPtr()),
9     myBaseAttribute(theAttribute)
10 {
11   process();
12 }
13
14 void SketchSolver_ConstraintParametric::process()
15 {
16   cleanErrorMsg();
17   if (!myBaseAttribute || !myStorage || myGroup == 0) {
18     /// TODO: Put error message here
19     return;
20   }
21   if (!mySlvsConstraints.empty()) // some data is changed, update constraint
22     update(myBaseConstraint);
23
24   Slvs_hEntity anAttrID;
25   getAttributes(anAttrID);
26   if (!myErrorMsg.empty() || (myFeatureMap.empty() && myAttributeMap.empty()))
27     return;
28
29   myHorizLineID = SLVS_E_UNKNOWN;
30   myVertLineID = SLVS_E_UNKNOWN;
31
32   std::shared_ptr<GeomDataAPI_Point2D> aPoint =
33       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
34   if (!aPoint)
35     return;
36   if (!aPoint->textX().empty()) {
37     // Create vertical line with fixed boundary point
38     Slvs_Entity aLine = createLine(aPoint->x(), -100.0, aPoint->x(), 100.0);
39     fixPoint(aLine.point[0]);
40     Slvs_Constraint aVertConstr = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
41         SLVS_C_VERTICAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
42         aLine.h, SLVS_E_UNKNOWN);
43     myStorage->addConstraint(aVertConstr);
44     // Place point on line
45     Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
46         SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
47         aLine.h, SLVS_E_UNKNOWN);
48     aConstraint.h = myStorage->addConstraint(aConstraint);
49     mySlvsConstraints.push_back(aConstraint.h);
50     myVertLineID = aLine.h;
51     myX = aPoint->x();
52   }
53   if (!aPoint->textY().empty()) {
54     // Create horizontal line with fixed boundary points
55     Slvs_Entity aLine = createLine(-100.0, aPoint->y(), 100.0, aPoint->y());
56     fixPoint(aLine.point[0]);
57     Slvs_Constraint aHorizConstr = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
58         SLVS_C_HORIZONTAL, myGroup->getWorkplaneId(), 0.0, SLVS_E_UNKNOWN, SLVS_E_UNKNOWN,
59         aLine.h, SLVS_E_UNKNOWN);
60     myStorage->addConstraint(aHorizConstr);
61     // Place point on line
62     Slvs_Constraint aConstraint = Slvs_MakeConstraint(SLVS_C_UNKNOWN, myGroup->getId(),
63         SLVS_C_PT_ON_LINE, myGroup->getWorkplaneId(), 0.0, anAttrID, SLVS_E_UNKNOWN,
64         aLine.h, SLVS_E_UNKNOWN);
65     aConstraint.h = myStorage->addConstraint(aConstraint);
66     mySlvsConstraints.push_back(aConstraint.h);
67     myHorizLineID = aLine.h;
68     myY = aPoint->y();
69   }
70 }
71
72
73 void SketchSolver_ConstraintParametric::getAttributes(Slvs_hEntity& theAttributeID)
74 {
75   int aType = SLVS_E_UNKNOWN; // type of created entity
76   theAttributeID = SLVS_E_UNKNOWN;
77   theAttributeID = myGroup->getAttributeId(myBaseAttribute);
78   if (theAttributeID == SLVS_E_UNKNOWN) {
79     theAttributeID = changeEntity(myBaseAttribute, aType);
80     if (theAttributeID == SLVS_E_UNKNOWN) {
81       myErrorMsg = SketchSolver_Error::NOT_INITIALIZED();
82       return;
83     }
84   }
85   else
86      myAttributeMap[myBaseAttribute] = theAttributeID;
87 }
88
89
90 void SketchSolver_ConstraintParametric::update(ConstraintPtr theConstraint)
91 {
92   cleanErrorMsg();
93   if (!theConstraint || theConstraint == myBaseConstraint) {
94     std::shared_ptr<GeomDataAPI_Point2D> aPoint =
95         std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
96     if (aPoint && ((!aPoint->textX().empty() && myVertLineID != SLVS_E_UNKNOWN) || 
97         (!aPoint->textY().empty() && myHorizLineID != SLVS_E_UNKNOWN))) {
98       remove();
99       process();
100       return;
101     }
102   }
103   adjustConstraint();
104 }
105
106 void SketchSolver_ConstraintParametric::refresh()
107 {
108   Slvs_hEntity aBasePointID = myAttributeMap[myBaseAttribute];
109   const Slvs_Entity& aBasePoint = myStorage->getEntity(aBasePointID);
110   double aXY[2];
111   aXY[0] = myVertLineID  != SLVS_E_UNKNOWN ? myX : myStorage->getParameter(aBasePoint.param[0]).val;
112   aXY[1] = myHorizLineID != SLVS_E_UNKNOWN ? myY : myStorage->getParameter(aBasePoint.param[1]).val;
113
114   std::list<Slvs_Constraint> aCoincidence = myStorage->getConstraintsByType(SLVS_C_POINTS_COINCIDENT);
115   std::list<Slvs_Constraint>::const_iterator aCIt = aCoincidence.begin();
116   for (; aCIt != aCoincidence.end(); ++aCIt) {
117     if (aCIt->ptA != aBasePointID && aCIt->ptB != aBasePointID)
118       continue;
119     Slvs_hEntity anOtherPointID = aCIt->ptA == aBasePointID ? aCIt->ptB : aCIt->ptA;
120     const Slvs_Entity& aPoint = myStorage->getEntity(anOtherPointID);
121     for (int i = 0; i < 2; i++) {
122       Slvs_Param aParam = myStorage->getParameter(aPoint.param[i]);
123       aParam.val = aXY[i];
124       myStorage->updateParameter(aParam);
125     }
126   }
127 }
128
129 void SketchSolver_ConstraintParametric::adjustConstraint()
130 {
131   std::shared_ptr<GeomDataAPI_Point2D> aPoint =
132       std::dynamic_pointer_cast<GeomDataAPI_Point2D>(myBaseAttribute);
133   if (!aPoint)
134     return;
135
136   if (!aPoint->textX().empty()) {
137     const Slvs_Entity& aLine = myStorage->getEntity(myVertLineID);
138     const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
139     Slvs_Param aParX = myStorage->getParameter(aStartPoint.param[0]);
140     aParX.val = aPoint->x();
141     myStorage->updateParameter(aParX);
142     myX = aParX.val;
143   }
144   if (!aPoint->textY().empty()) {
145     const Slvs_Entity& aLine = myStorage->getEntity(myHorizLineID);
146     const Slvs_Entity& aStartPoint = myStorage->getEntity(aLine.point[0]);
147     Slvs_Param aParY = myStorage->getParameter(aStartPoint.param[1]);
148     aParY.val = aPoint->y();
149     myStorage->updateParameter(aParY);
150     myY = aParY.val;
151   }
152 }
153
154
155 Slvs_Entity SketchSolver_ConstraintParametric::createLine(
156     double theStartX, double theStartY, double theEndX, double theEndY)
157 {
158   // Start point
159   Slvs_Param aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), theStartX);
160   Slvs_Param aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), theStartY);
161   aParX.h = myStorage->addParameter(aParX);
162   aParY.h = myStorage->addParameter(aParY);
163   Slvs_Entity aStartPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
164     myGroup->getWorkplaneId(), aParX.h, aParY.h);
165   aStartPoint.h = myStorage->addEntity(aStartPoint);
166
167   // End point
168   aParX = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), theEndX);
169   aParY = Slvs_MakeParam(SLVS_E_UNKNOWN, myGroup->getId(), theEndY);
170   aParX.h = myStorage->addParameter(aParX);
171   aParY.h = myStorage->addParameter(aParY);
172   Slvs_Entity aEndPoint = Slvs_MakePoint2d(SLVS_E_UNKNOWN, myGroup->getId(),
173     myGroup->getWorkplaneId(), aParX.h, aParY.h);
174   aEndPoint.h = myStorage->addEntity(aEndPoint);
175
176   // Line
177   Slvs_Entity aLine = Slvs_MakeLineSegment(SLVS_E_UNKNOWN, myGroup->getId(),
178     myGroup->getWorkplaneId(), aStartPoint.h, aEndPoint.h);
179   aLine.h = myStorage->addEntity(aLine);
180   return aLine;
181 }