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_ConstraintEqual.h>
17 #include <SketchPlugin_ConstraintHorizontal.h>
18 #include <SketchPlugin_ConstraintLength.h>
19 #include <SketchPlugin_ConstraintParallel.h>
20 #include <SketchPlugin_ConstraintPerpendicular.h>
21 #include <SketchPlugin_ConstraintRadius.h>
22 #include <SketchPlugin_ConstraintRigid.h>
23 #include <SketchPlugin_ConstraintTangent.h>
24 #include <SketchPlugin_ConstraintVertical.h>
26 #include <ModelAPI_AttributeRefAttr.h>
27 #include <ModelAPI_Data.h>
28 #include <ModelAPI_Document.h>
29 #include <ModelAPI_Object.h>
30 #include <ModelAPI_ResultConstruction.h>
32 #include <GeomDataAPI_Point.h>
33 #include <GeomDataAPI_Point2D.h>
34 #include <GeomAPI_Edge.h>
35 #include <GeomAPI_Shape.h>
37 /// Possible types of attributes (used to determine constraint type)
40 UNKNOWN, // Something wrong during type determination
48 /// Calculate type of the attribute
49 static AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute);
51 SketchSolver_Constraint::SketchSolver_Constraint()
52 : myConstraint(std::shared_ptr<SketchPlugin_Constraint>()),
53 myType(SLVS_C_UNKNOWN),
58 SketchSolver_Constraint::SketchSolver_Constraint(
59 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
60 : myConstraint(theConstraint),
63 myType = getType(myConstraint);
66 const int& SketchSolver_Constraint::getType(
67 std::shared_ptr<SketchPlugin_Constraint> theConstraint)
69 myType = SLVS_C_UNKNOWN;
73 DataPtr aConstrData = theConstraint->data();
74 if (!aConstrData || !aConstrData->isValid())
77 // Assign empty names of attributes
78 myAttributesList.clear();
79 for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
80 myAttributesList.push_back(std::string());
82 const std::string& aConstraintKind = theConstraint->getKind();
83 // Constraint for coincidence of two points
84 if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) {
86 // Verify the constraint has only two attributes and they are points
87 int aPt2d = 0; // bit-mapped field, each bit indicates whether the attribute is 2D point
88 int aPt3d = 0; // bit-mapped field, the same information for 3D points
89 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
90 std::shared_ptr<ModelAPI_Attribute> anAttr =
91 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
94 switch (typeOfAttribute(anAttr)) {
95 case POINT2D: // the attribute is a 2D point
96 aPt2d |= (1 << indAttr);
97 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
99 case POINT3D: // the attribute is a 3D point
100 aPt3d |= (1 << indAttr);
101 myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
104 // Attribute neither 2D nor 3D point is not supported by this type of constraint
108 // The constrained points should be in first and second positions,
109 // so the expected value of aPt2d or aPt3d is 3
110 if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3))
111 myType = SLVS_C_POINTS_COINCIDENT;
112 // Constraint parameters are wrong
116 // Constraint for distance between point and another entity
117 if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0) {
120 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
121 std::shared_ptr<ModelAPI_Attribute> anAttr =
122 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
123 switch (typeOfAttribute(anAttr)) {
126 myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
129 // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
130 myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
131 myType = SLVS_C_PT_LINE_DISTANCE;
135 // Verify the correctness of constraint arguments
136 if (aNbPoints == 2 && aNbEntities == 0)
137 myType = SLVS_C_PT_PT_DISTANCE;
138 else if (aNbPoints != 1 || aNbEntities != 1)
139 myType = SLVS_C_UNKNOWN;
143 // Constraint for the given length of a line
144 if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) {
146 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
147 std::shared_ptr<ModelAPI_Attribute> anAttr =
148 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
149 if (typeOfAttribute(anAttr) == LINE)
150 myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
153 myType = SLVS_C_PT_PT_DISTANCE;
157 // Constraint for two parallel/perpendicular lines
158 bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
159 bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
160 if (isParallel || isPerpendicular) {
161 int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
162 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
163 std::shared_ptr<ModelAPI_Attribute> anAttr =
164 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
165 if (typeOfAttribute(anAttr) == LINE)
166 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
168 if (aNbEntities == 4)
169 myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
173 // Constraint for radius of a circle or an arc of circle
174 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++) {
177 std::shared_ptr<ModelAPI_Attribute> anAttr =
178 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
179 AttrType aType = typeOfAttribute(anAttr);
180 if (aType == CIRCLE || aType == ARC)
181 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
183 if (aNbEntities == 3)
184 myType = SLVS_C_DIAMETER;
188 // Constraint for fixed entity
189 if (aConstraintKind.compare(SketchPlugin_ConstraintRigid::ID()) == 0) {
190 // Verify that only one entity is filled
192 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
193 std::shared_ptr<ModelAPI_Attribute> anAttr =
194 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
195 AttrType aType = typeOfAttribute(anAttr);
196 if (aType != UNKNOWN)
197 myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
200 myType = SLVS_C_WHERE_DRAGGED;
204 // Constraint for horizontal/vertical line
205 bool isHorizontal = (aConstraintKind.compare(SketchPlugin_ConstraintHorizontal::ID()) == 0);
206 bool isVertical = (aConstraintKind.compare(SketchPlugin_ConstraintVertical::ID()) == 0);
207 if (isHorizontal || isVertical) {
208 int aNbEntities = 2; // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
209 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
210 std::shared_ptr<ModelAPI_Attribute> anAttr =
211 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
212 if (typeOfAttribute(anAttr) == LINE)
213 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
215 if (aNbEntities == 3)
216 myType = isHorizontal ? SLVS_C_HORIZONTAL : SLVS_C_VERTICAL;
220 if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0)
222 static const int aConstrType[3] = {
224 SLVS_C_EQUAL_LINE_ARC_LEN,
225 SLVS_C_EQUAL_LENGTH_LINES
228 int aNbEntities = 2; // lines and circles in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
229 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
230 std::shared_ptr<ModelAPI_Attribute> anAttr =
231 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
232 AttrType aType = typeOfAttribute(anAttr);
234 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
237 else if (aType == CIRCLE || aType == ARC)
238 myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
240 if (aNbEntities == 4)
241 myType = aConstrType[aNbLines];
245 if (aConstraintKind.compare(SketchPlugin_ConstraintTangent::ID()) == 0)
247 static const int anArcPosDefault = 2;
248 static const int aLinePosDefault = 3;
249 int anArcPos = anArcPosDefault; // arc in tangency constraint should be placed before line
250 int aLinePos = aLinePosDefault;
251 for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
252 std::shared_ptr<ModelAPI_Attribute> anAttr =
253 aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
254 AttrType aType = typeOfAttribute(anAttr);
255 if (aType == LINE && aLinePos < CONSTRAINT_ATTR_SIZE)
256 myAttributesList[aLinePos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
257 else if (aType == ARC)
258 myAttributesList[anArcPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
260 if (anArcPos - anArcPosDefault + aLinePos - aLinePosDefault == 2)
261 myType = aLinePos > 3 ? SLVS_C_ARC_LINE_TANGENT : SLVS_C_CURVE_CURVE_TANGENT;
265 /// \todo Implement other kind of constraints
270 // ================= Auxiliary functions ==============================
271 AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute)
273 std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef = std::dynamic_pointer_cast<
274 ModelAPI_AttributeRefAttr>(theAttribute);
278 if (anAttrRef->isObject()) {
279 ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
280 anAttrRef->object());
281 if (!aRC || !aRC->shape())
284 if (aRC->shape()->isVertex())
286 else if (aRC->shape()->isEdge()) {
287 std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(
289 if (anEdge->isLine())
291 else if (anEdge->isCircle())
293 else if (anEdge->isArc())
297 if (anAttrRef->attr().get() != NULL) {
298 const std::string aType = anAttrRef->attr()->attributeType();
299 if (aType == GeomDataAPI_Point2D::type())
301 if (aType == GeomDataAPI_Point2D::type())