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_ConstraintCoincidence.h>
13 #include <SketchPlugin_ConstraintDistance.h>
14 #include <SketchPlugin_ConstraintLength.h>
15 #include <SketchPlugin_ConstraintParallel.h>
16 #include <SketchPlugin_ConstraintPerpendicular.h>
17 #include <SketchPlugin_ConstraintRadius.h>
19 #include <ModelAPI_AttributeRefAttr.h>
20 #include <ModelAPI_Data.h>
21 #include <ModelAPI_Document.h>
22 #include <ModelAPI_Object.h>
23 #include <ModelAPI_ResultConstruction.h>
25 #include <GeomDataAPI_Point.h>
26 #include <GeomDataAPI_Point2D.h>
27 #include <GeomAPI_Edge.h>
28 #include <GeomAPI_Shape.h>
30 /// Possible types of attributes (used to determine constraint type)
33 UNKNOWN, // Something wrong during type determination
41 /// Calculate type of the attribute
42 static AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute);
46 SketchSolver_Constraint::SketchSolver_Constraint()
47 : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
48 myType(SLVS_C_UNKNOWN),
53 SketchSolver_Constraint::SketchSolver_Constraint(
54 boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
55 : myConstraint(theConstraint),
58 myType = getType(myConstraint);
61 const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
63 myType = SLVS_C_UNKNOWN;
67 // Assign empty names of attributes
68 myAttributesList.clear();
69 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
70 myAttributesList.push_back(std::string());
72 const std::string& aConstraintKind = theConstraint->getKind();
73 // Constraint for coincidence of two points
74 if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0)
77 // Verify the constraint has only two attributes and they are points
78 int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point
79 int aPt3d = 0; // bit-mapped field, the same information for 3D points
80 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
82 boost::shared_ptr<ModelAPI_Attribute> anAttr =
83 theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
84 if (!anAttr) continue;
85 switch (typeOfAttribute(anAttr))
87 case POINT2D: // the attribute is a 2D point
88 aPt2d |= (1 << indAttr);
89 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
91 case POINT3D: // the attribute is a 3D point
92 aPt3d |= (1 << indAttr);
93 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
96 // Attribute neither 2D nor 3D point is not supported by this type of constraint
100 // The constrained points should be in first and second positions,
101 // so the expected value of aPt2d or aPt3d is 3
102 if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3))
103 myType = SLVS_C_POINTS_COINCIDENT;
104 // Constraint parameters are wrong
108 // Constraint for distance between point and another entity
109 if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0)
113 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
115 boost::shared_ptr<ModelAPI_Attribute> anAttr =
116 theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
117 switch (typeOfAttribute(anAttr))
121 myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
124 // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
125 myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
126 myType = SLVS_C_PT_LINE_DISTANCE;
130 // Verify the correctness of constraint arguments
131 if (aNbPoints == 2 && aNbEntities ==0)
132 myType = SLVS_C_PT_PT_DISTANCE;
133 else if (aNbPoints != 1 || aNbEntities != 1)
134 myType = SLVS_C_UNKNOWN;
138 // Constraint for the given length of a line
139 if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0)
142 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
144 boost::shared_ptr<ModelAPI_Attribute> anAttr =
145 theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
146 if (typeOfAttribute(anAttr) == LINE)
147 myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
150 myType = SLVS_C_PT_PT_DISTANCE;
154 // Constraint for two parallel/perpendicular lines
155 bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
156 bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
157 if (isParallel || isPerpendicular)
159 int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
160 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
162 boost::shared_ptr<ModelAPI_Attribute> anAttr =
163 theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
164 if (typeOfAttribute(anAttr) == LINE)
165 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
167 if (aNbEntities == 4)
168 myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
172 // Constraint for radius of a circle or an arc of circle
173 if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0)
175 int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
176 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
178 boost::shared_ptr<ModelAPI_Attribute> anAttr =
179 theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
180 AttrType aType = typeOfAttribute(anAttr);
181 if (aType == CIRCLE || aType == ARC)
182 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
184 if (aNbEntities == 3)
185 myType = SLVS_C_DIAMETER;
189 /// \todo Implement other kind of constraints
195 // ================= Auxiliary functions ==============================
196 AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute)
198 boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef =
199 boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
200 if (!anAttrRef) return UNKNOWN;
202 if (anAttrRef->isObject())
204 ResultConstructionPtr aRC =
205 boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anAttrRef->object());
206 if (!aRC) return UNKNOWN;
208 if (aRC->shape()->isVertex())
210 else if (aRC->shape()->isEdge())
212 boost::shared_ptr<GeomAPI_Edge> anEdge =
213 boost::dynamic_pointer_cast<GeomAPI_Edge>(aRC->shape());
214 if (anEdge->isLine())
216 else if (anEdge->isCircle())
218 else if (anEdge->isArc())
224 const std::string aType = anAttrRef->attr()->attributeType();
225 if (aType == GeomDataAPI_Point2D::type())
227 if (aType == GeomDataAPI_Point2D::type())