1 // File: SketchSolver_Constraint.cpp
2 // Created: 27 May 2014
3 // Author: Artem ZHIDKOV
5 #include "SketchSolver_Constraint.h"
6 #include <SketchSolver_Solver.h>
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>
18 #include <ModelAPI_AttributeRefAttr.h>
19 #include <ModelAPI_Data.h>
21 #include <GeomDataAPI_Point.h>
22 #include <GeomDataAPI_Point2D.h>
25 SketchSolver_Constraint::SketchSolver_Constraint()
26 : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
27 myType(SLVS_C_UNKNOWN),
32 SketchSolver_Constraint::SketchSolver_Constraint(
33 boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
34 : myConstraint(theConstraint),
37 myType = getType(myConstraint);
40 const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
42 myType = SLVS_C_UNKNOWN;
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());
51 const std::string& aConstraintKind = theConstraint->getKind();
52 // Constraint for coincidence of two points
53 if (aConstraintKind.compare("SketchConstraintCoincidence") == 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++)
61 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
62 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
63 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
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());
71 aPt2d |= (1 << indAttr);
72 myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
75 // Verify the attribute is a 3D point
76 boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
77 boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
80 aPt3d |= (1 << indAttr);
81 myAttributesList[anAttrPos++] = CONSTRAINT_ATTRIBUTES[indAttr];
84 // Attribute neither 2D nor 3D point is not supported by this type of constraint
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
95 // Constraint for distance between point and another entity
96 if (aConstraintKind.compare(SKETCH_CONSTRAINT_DISTANCE_KIND) == 0)
100 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
102 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
103 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
104 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
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)
113 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
116 else if(aKind.compare(SKETCH_LINE_KIND) == 0)
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;
126 // Verify the attribute is a 2D point
127 boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
128 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
131 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
134 // Verify the attribute is a 3D point
135 boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
136 boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
139 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
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;
152 // Constraint for the given length of a line
153 if (aConstraintKind.compare(SKETCH_CONSTRAINT_LENGTH_KIND) == 0)
156 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
158 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
159 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
160 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
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)
167 myAttributesList[aNbLines++] = CONSTRAINT_ATTRIBUTES[indAttr];
172 myType = SLVS_C_PT_PT_DISTANCE;
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)
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++)
184 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
185 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
186 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
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)
193 myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
197 if (aNbEntities == 4)
198 myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
202 // Constraint for radius of a circle or an arc of circle
203 if (aConstraintKind.compare(SKETCH_CONSTRAINT_RADIUS_KIND) == 0)
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++)
208 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
209 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
210 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
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)
217 myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
221 if (aNbEntities == 3)
222 myType = SLVS_C_DIAMETER;
226 /// \todo Implement other kind of constrtaints