]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Constraint.cpp
Salome HOME
2bfd8e697780bd2265b8c903347d3d017870868d
[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 two parallel/perpendicular lines
142   bool isParallel = (aConstraintKind.compare("SketchConstraintParallel") == 0);
143   bool isPerpendicular = (aConstraintKind.compare("SketchConstraintPerpendicular") == 0);
144   if (isParallel || isPerpendicular)
145   {
146     int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
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 || !anAttr->isFeature()) continue;
154       const std::string& aKind = anAttr->feature()->getKind();
155       if (aKind.compare("SketchLine") == 0)
156       {
157         myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
158         continue;
159       }
160     }
161     if (aNbEntities == 4)
162       myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
163     return getType();
164   }
165
166   // Constraint for diameter of a circle
167   if (aConstraintKind.compare("SketchConstraintDiameter") == 0)
168   {
169     int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
170     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
171     {
172       boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
173         boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
174           theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
175         );
176       if (!anAttr || !anAttr->isFeature()) continue;
177       const std::string& aKind = anAttr->feature()->getKind();
178       if (aKind.compare("SketchCircle") == 0)
179       {
180         myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
181         continue;
182       }
183     }
184     if (aNbEntities == 3)
185       myType = SLVS_C_DIAMETER;
186     return getType();
187   }
188
189   /// \todo Implement other kind of constrtaints
190
191   return getType();
192 }