1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: SketchSolver_Constraint.cpp
4 // Created: 27 May 2014
5 // Author: Artem ZHIDKOV
7 #include "SketchSolver_Constraint.h"
8 #include <SketchSolver_Solver.h>
10 #include <SketchPlugin_Line.h>
11 #include <SketchPlugin_Point.h>
12 #include <SketchPlugin_Circle.h>
13 #include <SketchPlugin_Arc.h>
14 #include <SketchPlugin_ConstraintCoincidence.h>
15 #include <SketchPlugin_ConstraintDistance.h>
16 #include <SketchPlugin_ConstraintLength.h>
17 #include <SketchPlugin_ConstraintParallel.h>
18 #include <SketchPlugin_ConstraintPerpendicular.h>
19 #include <SketchPlugin_ConstraintRadius.h>
20 #include <SketchPlugin_ConstraintRigid.h>
22 #include <ModelAPI_AttributeRefAttr.h>
23 #include <ModelAPI_Data.h>
24 #include <ModelAPI_Document.h>
25 #include <ModelAPI_Object.h>
26 #include <ModelAPI_ResultConstruction.h>
28 #include <GeomDataAPI_Point.h>
29 #include <GeomDataAPI_Point2D.h>
30 #include <GeomAPI_Edge.h>
31 #include <GeomAPI_Shape.h>
33 /// Possible types of attributes (used to determine constraint type)
36 UNKNOWN, // Something wrong during type determination
44 /// Calculate type of the attribute
45 static AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute);
47 SketchSolver_Constraint::SketchSolver_Constraint()
48 : myConstraint(std::shared_ptr<SketchPlugin_Constraint>()),
49 myType(SLVS_C_UNKNOWN),
54 SketchSolver_Constraint::SketchSolver_Constraint(
55 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
56 : myConstraint(theConstraint),
59 myType = getType(myConstraint);
62 const int& SketchSolver_Constraint::getType(
63 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
65 myType = SLVS_C_UNKNOWN;
69 DataPtr aConstrData = theConstraint->data();
70 if (!aConstrData || !aConstrData->isValid())
73 // Assign empty names of attributes
74 myAttributesList.clear();
75 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
76 myAttributesList.push_back(std::string());
78 const std::string& aConstraintKind = theConstraint->getKind();
79 // Constraint for coincidence of two points
80 if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) {
82 // Verify the constraint has only two attributes and they are points
83 int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point
84 int aPt3d = 0; // bit-mapped field, the same information for 3D points
85 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
86 std::shared_ptr<ModelAPI_Attribute> anAttr =
87 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
90 switch (typeOfAttribute(anAttr)) {
91 case POINT2D: // the attribute is a 2D point
92 aPt2d |= (1 << indAttr);
93 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
95 case POINT3D: // the attribute is a 3D point
96 aPt3d |= (1 << indAttr);
97 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
100 // Attribute neither 2D nor 3D point is not supported by this type of constraint
104 // The constrained points should be in first and second positions,
105 // so the expected value of aPt2d or aPt3d is 3
106 if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3))
107 myType = SLVS_C_POINTS_COINCIDENT;
108 // Constraint parameters are wrong
112 // Constraint for distance between point and another entity
113 if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0) {
116 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
117 std::shared_ptr<ModelAPI_Attribute> anAttr =
118 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
119 switch (typeOfAttribute(anAttr)) {
122 myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
125 // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
126 myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
127 myType = SLVS_C_PT_LINE_DISTANCE;
131 // Verify the correctness of constraint arguments
132 if (aNbPoints == 2 && aNbEntities == 0)
133 myType = SLVS_C_PT_PT_DISTANCE;
134 else if (aNbPoints != 1 || aNbEntities != 1)
135 myType = SLVS_C_UNKNOWN;
139 // Constraint for the given length of a line
140 if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) {
142 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
143 std::shared_ptr<ModelAPI_Attribute> anAttr =
144 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
145 if (typeOfAttribute(anAttr) == LINE)
146 myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
149 myType = SLVS_C_PT_PT_DISTANCE;
153 // Constraint for two parallel/perpendicular lines
154 bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
155 bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
156 if (isParallel || isPerpendicular) {
157 int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
158 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
159 std::shared_ptr<ModelAPI_Attribute> anAttr =
160 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
161 if (typeOfAttribute(anAttr) == LINE)
162 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
164 if (aNbEntities == 4)
165 myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
169 // Constraint for radius of a circle or an arc of circle
170 if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0) {
171 int aNbEntities = 2; // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
172 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
173 std::shared_ptr<ModelAPI_Attribute> anAttr =
174 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
175 AttrType aType = typeOfAttribute(anAttr);
176 if (aType == CIRCLE || aType == ARC)
177 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
179 if (aNbEntities == 3)
180 myType = SLVS_C_DIAMETER;
184 // Constraint for fixed entity
185 if (aConstraintKind.compare(SketchPlugin_ConstraintRigid::ID()) == 0) {
186 // Verify that only one entity is filled
188 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
189 std::shared_ptr<ModelAPI_Attribute> anAttr =
190 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
191 AttrType aType = typeOfAttribute(anAttr);
192 if (aType != UNKNOWN)
193 myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
196 myType = SLVS_C_WHERE_DRAGGED;
200 /// \todo Implement other kind of constraints
205 // ================= Auxiliary functions ==============================
206 AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute)
208 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef = std::dynamic_pointer_cast<
209 ModelAPI_AttributeRefAttr>(theAttribute);
213 if (anAttrRef->isObject()) {
214 ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
215 anAttrRef->object());
216 if (!aRC || !aRC->shape())
219 if (aRC->shape()->isVertex())
221 else if (aRC->shape()->isEdge()) {
222 std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(
224 if (anEdge->isLine())
226 else if (anEdge->isCircle())
228 else if (anEdge->isArc())
232 const std::string aType = anAttrRef->attr()->attributeType();
233 if (aType == GeomDataAPI_Point2D::type())
235 if (aType == GeomDataAPI_Point2D::type())