Salome HOME
1490a091cc6403b7bde5b41d86ca58c4666fc316
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
1 // File:    SketchSolver_Constraint.cpp
2 // Created: 27 May 2014
3 // Author:  Artem ZHIDKOV
4
5 #include "SketchSolver_Constraint.h"
6 #include <SketchSolver_Solver.h>
7
8 #include <SketchPlugin_Line.h>
9 #include <SketchPlugin_Point.h>
10 #include <SketchPlugin_Circle.h>
11 #include <SketchPlugin_Arc.h>
12 #include <SketchPlugin_ConstraintDistance.h>
13 #include <SketchPlugin_ConstraintLength.h>
14 #include <SketchPlugin_ConstraintParallel.h>
15 #include <SketchPlugin_ConstraintPerpendicular.h>
16 #include <SketchPlugin_ConstraintRadius.h>
17
18 #include <ModelAPI_AttributeRefAttr.h>
19 #include <ModelAPI_Data.h>
20
21 #include <GeomDataAPI_Point.h>
22 #include <GeomDataAPI_Point2D.h>
23
24
25 SketchSolver_Constraint::SketchSolver_Constraint()
26   : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
27     myType(SLVS_C_UNKNOWN),
28     myAttributesList()
29 {
30 }
31
32 SketchSolver_Constraint::SketchSolver_Constraint(
33                 boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
34   : myConstraint(theConstraint),
35     myAttributesList()
36 {
37   myType = getType(myConstraint);
38 }
39
40 const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
41 {
42   myType = SLVS_C_UNKNOWN;
43   if (!theConstraint)
44     return getType();
45
46   // Assign empty names of attributes
47   myAttributesList.clear();
48   for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
49     myAttributesList.push_back(std::string());
50
51   const std::string& aConstraintKind = theConstraint->getKind();
52   // Constraint for coincidence of two points
53   if (aConstraintKind.compare("SketchConstraintCoincidence") == 0)
54   {
55     int anAttrPos = 0;
56     // Verify the constraint has only two attributes and they are points
57     int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point
58     int aPt3d = 0; // bit-mapped field, the same information for 3D points
59     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
60     {
61       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
62         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
63           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
64         );
65       if (!anAttr) continue;
66       // Verify the attribute is a 2D point
67       boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
68         boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
69       if (aPoint2D)
70       {
71         aPt2d |= (1 << indAttr);
72         myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
73         continue;
74       }
75       // Verify the attribute is a 3D point
76       boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
77         boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
78       if (aPoint3D)
79       {
80         aPt3d |= (1 << indAttr);
81         myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
82         continue;
83       }
84       // Attribute neither 2D nor 3D point is not supported by this type of constraint
85       return getType();
86     }
87     // The constrained points should be in first and second positions,
88     // so the expected value of aPt2d or aPt3d is 3
89     if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3))
90       myType = SLVS_C_POINTS_COINCIDENT;
91     // Constraint parameters are wrong
92     return getType();
93   }
94
95   // Constraint for distance between point and another entity
96   if (aConstraintKind.compare(SKETCH_CONSTRAINT_DISTANCE_KIND) == 0)
97   {
98     int aNbPoints = 0;
99     int aNbEntities = 0;
100     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
101     {
102       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
103         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
104           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
105         );
106       if (!anAttr) continue;
107       if (anAttr->isObject() && anAttr->object())
108       { // verify posiible entities
109         const std::string& aKind = boost::dynamic_pointer_cast<ModelAPI_Feature>
110           (anAttr->object())->getKind();
111         if (aKind.compare(SKETCH_POINT_KIND) == 0)
112         {
113           myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
114           continue;
115         }
116         else if(aKind.compare(SKETCH_LINE_KIND) == 0)
117         {
118           // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute
119           myAttributesList[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
120           myType = SLVS_C_PT_LINE_DISTANCE;
121           continue;
122         }
123       }
124       else
125       { // verify points
126         // Verify the attribute is a 2D point
127         boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
128           boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
129         if (aPoint2D)
130         {
131           myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
132           continue;
133         }
134         // Verify the attribute is a 3D point
135         boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
136           boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
137         if (aPoint3D)
138         {
139           myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
140           continue;
141         }
142       }
143     }
144     // Verify the correctness of constraint arguments
145     if (aNbPoints == 2 && aNbEntities ==0)
146       myType = SLVS_C_PT_PT_DISTANCE;
147     else if (aNbPoints == 1 && aNbEntities == 1)
148       myType = SLVS_C_UNKNOWN;
149     return getType();
150   }
151
152   // Constraint for the given length of a line
153   if (aConstraintKind.compare(SKETCH_CONSTRAINT_LENGTH_KIND) == 0)
154   {
155     int aNbLines = 0;
156     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
157     {
158       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
159         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
160           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
161         );
162       if (!anAttr) continue;
163       if (anAttr->isObject() && anAttr->object() &&
164         boost::dynamic_pointer_cast<ModelAPI_Feature>(anAttr->object())->getKind().
165         compare(SKETCH_LINE_KIND) == 0)
166       {
167         myAttributesList[aNbLines++] = CONSTRAINT_ATTRIBUTES[indAttr];
168         break;
169       }
170     }
171     if (aNbLines == 1)
172       myType = SLVS_C_PT_PT_DISTANCE;
173     return getType();
174   }
175
176   // Constraint for two parallel/perpendicular lines
177   bool isParallel = (aConstraintKind.compare(SKETCH_CONSTRAINT_PARALLEL_KIND) == 0);
178   bool isPerpendicular = (aConstraintKind.compare(SKETCH_CONSTRAINT_PERPENDICULAR_KIND) == 0);
179   if (isParallel || isPerpendicular)
180   {
181     int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
182     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
183     {
184       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
185         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
186           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
187         );
188       if (!anAttr || !anAttr->isObject() || !anAttr->object()) continue;
189       const std::string& aKind = boost::dynamic_pointer_cast<ModelAPI_Feature>
190         (anAttr->object())->getKind();
191       if (aKind.compare(SKETCH_LINE_KIND) == 0)
192       {
193         myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
194         continue;
195       }
196     }
197     if (aNbEntities == 4)
198       myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
199     return getType();
200   }
201
202   // Constraint for radius of a circle or an arc of circle
203   if (aConstraintKind.compare(SKETCH_CONSTRAINT_RADIUS_KIND) == 0)
204   {
205     int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
206     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
207     {
208       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
209         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
210           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
211         );
212       if (!anAttr || !anAttr->isObject() || !anAttr->object()) continue;
213       const std::string& aKind = boost::dynamic_pointer_cast<ModelAPI_Feature>
214         (anAttr->object())->getKind();
215       if (aKind.compare(SKETCH_CIRCLE_KIND) == 0 || aKind.compare(SKETCH_ARC_KIND) == 0)
216       {
217         myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
218         continue;
219       }
220     }
221     if (aNbEntities == 3)
222       myType = SLVS_C_DIAMETER;
223     return getType();
224   }
225
226   /// \todo Implement other kind of constrtaints
227
228   return getType();
229 }