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