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