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->isFeature() && anAttr->feature())
108 { // verify posiible entities
109 const std::string& aKind = anAttr->feature()->getKind();
110 if (aKind.compare(SKETCH_POINT_KIND) == 0)
112 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
115 else if(aKind.compare(SKETCH_LINE_KIND) == 0)
117 // entities are placed starting from CONSTRAINT_ATTR_ENTITY_C attribute
118 myAttributesList[2 + aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
119 myType = SLVS_C_PT_LINE_DISTANCE;
125 // Verify the attribute is a 2D point
126 boost::shared_ptr<GeomDataAPI_Point2D> aPoint2D =
127 boost::dynamic_pointer_cast<GeomDataAPI_Point2D>(anAttr->attr());
130 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
133 // Verify the attribute is a 3D point
134 boost::shared_ptr<GeomDataAPI_Point> aPoint3D =
135 boost::dynamic_pointer_cast<GeomDataAPI_Point>(anAttr->attr());
138 myAttributesList[aNbPoints++] = CONSTRAINT_ATTRIBUTES[indAttr];
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;
151 // Constraint for the given length of a line
152 if (aConstraintKind.compare(SKETCH_CONSTRAINT_LENGTH_KIND) == 0)
155 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
157 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
158 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
159 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
161 if (!anAttr) continue;
162 if (anAttr->isFeature() && anAttr->feature() &&
163 anAttr->feature()->getKind().compare(SKETCH_LINE_KIND) == 0)
165 myAttributesList[aNbLines++] = CONSTRAINT_ATTRIBUTES[indAttr];
170 myType = SLVS_C_PT_PT_DISTANCE;
174 // Constraint for two parallel/perpendicular lines
175 bool isParallel = (aConstraintKind.compare(SKETCH_CONSTRAINT_PARALLEL_KIND) == 0);
176 bool isPerpendicular = (aConstraintKind.compare(SKETCH_CONSTRAINT_PERPENDICULAR_KIND) == 0);
177 if (isParallel || isPerpendicular)
179 int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
180 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
182 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
183 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
184 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
186 if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue;
187 const std::string& aKind = anAttr->feature()->getKind();
188 if (aKind.compare(SKETCH_LINE_KIND) == 0)
190 myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
194 if (aNbEntities == 4)
195 myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
199 // Constraint for radius of a circle or an arc of circle
200 if (aConstraintKind.compare(SKETCH_CONSTRAINT_RADIUS_KIND) == 0)
202 int aNbEntities = 2; // lines in SolveSpace constraints should started from CONSTRAINT_ATTR_ENTITY_C attribute
203 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
205 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttr =
206 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(
207 theConstraint->data()->attribute(CONSTRAINT_ATTRIBUTES[indAttr])
209 if (!anAttr || !anAttr->isFeature() || !anAttr->feature()) continue;
210 const std::string& aKind = anAttr->feature()->getKind();
211 if (aKind.compare(SKETCH_CIRCLE_KIND) == 0 || aKind.compare(SKETCH_ARC_KIND) == 0)
213 myAttributesList[aNbEntities++] = CONSTRAINT_ATTRIBUTES[indAttr];
217 if (aNbEntities == 3)
218 myType = SLVS_C_DIAMETER;
222 /// \todo Implement other kind of constrtaints