Salome HOME
Refactoring: static constants are replaced by inline functions in:
[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(SketchPlugin_Constraint::ATTRIBUTE(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++] = SketchPlugin_Constraint::ATTRIBUTE(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++] = SketchPlugin_Constraint::ATTRIBUTE(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(SketchPlugin_ConstraintDistance::ID()) == 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(SketchPlugin_Constraint::ATTRIBUTE(indAttr))
105         );
106       if (!anAttr) continue;
107       if (anAttr->isFeature() && anAttr->feature())
108       { // verify posiible entities
109         const std::string& aKind = anAttr->feature()->getKind();
110         if (aKind.compare(SketchPlugin_Point::ID()) == 0)
111         {
112           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
113           continue;
114         }
115         else if(aKind.compare(SketchPlugin_Line::ID()) == 0)
116         {
117           // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
118           myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
119           myType = SLVS_C_PT_LINE_DISTANCE;
120           continue;
121         }
122       }
123       else
124       { // verify points
125         // Verify the attribute is a 2D point
126         boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
127           boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
128         if (aPoint2D)
129         {
130           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
131           continue;
132         }
133         // Verify the attribute is a 3D point
134         boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
135           boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
136         if (aPoint3D)
137         {
138           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
139           continue;
140         }
141       }
142     }
143     // Verify the correctness of constraint arguments
144     if (aNbPoints == 2 && aNbEntities ==0)
145       myType = SLVS_C_PT_PT_DISTANCE;
146     else if (aNbPoints == 1 && aNbEntities == 1)
147       myType = SLVS_C_UNKNOWN;
148     return getType();
149   }
150
151   // Constraint for the given length of a line
152   if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0)
153   {
154     int aNbLines = 0;
155     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
156     {
157       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
158         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
159           theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr))
160         );
161       if (!anAttr) continue;
162       if (anAttr->isFeature() && anAttr->feature() &&
163           anAttr->feature()->getKind().compare(SketchPlugin_Line::ID()) == 0)
164       {
165         myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
166         break;
167       }
168     }
169     if (aNbLines == 1)
170       myType = SLVS_C_PT_PT_DISTANCE;
171     return getType();
172   }
173
174   // Constraint for two parallel/perpendicular lines
175   bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
176   bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
177   if (isParallel || isPerpendicular)
178   {
179     int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
180     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
181     {
182       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
183         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
184           theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr))
185         );
186       if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue;
187       const std::string& aKind = anAttr->feature()->getKind();
188       if (aKind.compare(SketchPlugin_Line::ID()) == 0)
189       {
190         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
191         continue;
192       }
193     }
194     if (aNbEntities == 4)
195       myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
196     return getType();
197   }
198
199   // Constraint for radius of a circle or an arc of circle
200   if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0)
201   {
202     int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
203     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
204     {
205       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
206         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
207           theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr))
208         );
209       if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue;
210       const std::string& aKind = anAttr->feature()->getKind();
211       if (aKind.compare(SketchPlugin_Circle::ID()) == 0 || aKind.compare(SketchPlugin_Arc::ID()) == 0)
212       {
213         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
214         continue;
215       }
216     }
217     if (aNbEntities == 3)
218       myType = SLVS_C_DIAMETER;
219     return getType();
220   }
221
222   /// \todo Implement other kind of constrtaints
223
224   return getType();
225 }