]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Constraint.cpp
Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom into Dev_1.1.0
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_Constraint.cpp
4 // Created: 27 May 2014
5 // Author:  Artem ZHIDKOV
6
7 #include "SketchSolver_Constraint.h"
8 #include <SketchSolver_Solver.h>
9
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_ConstraintVertical.h>
24
25 #include <ModelAPI_AttributeRefAttr.h>
26 #include <ModelAPI_Data.h>
27 #include <ModelAPI_Document.h>
28 #include <ModelAPI_Object.h>
29 #include <ModelAPI_ResultConstruction.h>
30
31 #include <GeomDataAPI_Point.h>
32 #include <GeomDataAPI_Point2D.h>
33 #include <GeomAPI_Edge.h>
34 #include <GeomAPI_Shape.h>
35
36 /// Possible types of attributes (used to determine constraint type)
37 enum AttrType
38 {
39   UNKNOWN,  // Something wrong during type determination
40   POINT2D,
41   POINT3D,
42   LINE,
43   CIRCLE,
44   ARC
45 };
46
47 /// Calculate type of the attribute
48 static AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute);
49
50 SketchSolver_Constraint::SketchSolver_Constraint()
51     : myConstraint(std::shared_ptr<SketchPlugin_Constraint>()),
52       myType(SLVS_C_UNKNOWN),
53       myAttributesList()
54 {
55 }
56
57 SketchSolver_Constraint::SketchSolver_Constraint(
58     std::shared_ptr<SketchPlugin_Constraint> theConstraint)
59     : myConstraint(theConstraint),
60       myAttributesList()
61 {
62   myType = getType(myConstraint);
63 }
64
65 const int& SketchSolver_Constraint::getType(
66     std::shared_ptr<SketchPlugin_Constraint> theConstraint)
67 {
68   myType = SLVS_C_UNKNOWN;
69   if (!theConstraint)
70     return getType();
71
72   DataPtr aConstrData = theConstraint->data();
73   if (!aConstrData || !aConstrData->isValid())
74     return getType();
75
76   // Assign empty names of attributes
77   myAttributesList.clear();
78   for (int i = 0; i < CONSTRAINT_ATTR_SIZE; i++)
79     myAttributesList.push_back(std::string());
80
81   const std::string& aConstraintKind = theConstraint->getKind();
82   // Constraint for coincidence of two points
83   if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0) {
84     int anAttrPos = 0;
85     // Verify the constraint has only two attributes and they are points
86     int aPt2d = 0;  // bit-mapped field, each bit indicates whether the attribute is 2D point
87     int aPt3d = 0;  // bit-mapped field, the same information for 3D points
88     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
89       std::shared_ptr<ModelAPI_Attribute> anAttr = 
90           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
91       if (!anAttr)
92         continue;
93       switch (typeOfAttribute(anAttr)) {
94         case POINT2D:  // the attribute is a 2D point
95           aPt2d |= (1 << indAttr);
96           myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
97           break;
98         case POINT3D:  // the attribute is a 3D point
99           aPt3d |= (1 << indAttr);
100           myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
101           break;
102         default:
103           // Attribute neither 2D nor 3D point is not supported by this type of constraint
104           return getType();
105       }
106     }
107     // The constrained points should be in first and second positions,
108     // so the expected value of aPt2d or aPt3d is 3
109     if ((aPt2d == 3 && aPt3d == 0) || (aPt2d == 0 && aPt3d == 3))
110       myType = SLVS_C_POINTS_COINCIDENT;
111     // Constraint parameters are wrong
112     return getType();
113   }
114
115   // Constraint for distance between point and another entity
116   if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0) {
117     int aNbPoints = 0;
118     int aNbEntities = 0;
119     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
120       std::shared_ptr<ModelAPI_Attribute> anAttr = 
121           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
122       switch (typeOfAttribute(anAttr)) {
123         case POINT2D:
124         case POINT3D:
125           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
126           break;
127         case LINE:
128           // entities are placed starting from SketchPlugin_Constraint::ENTITY_C() attribute
129           myAttributesList[2 + aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
130           myType = SLVS_C_PT_LINE_DISTANCE;
131           break;
132       }
133     }
134     // Verify the correctness of constraint arguments
135     if (aNbPoints == 2 && aNbEntities == 0)
136       myType = SLVS_C_PT_PT_DISTANCE;
137     else if (aNbPoints != 1 || aNbEntities != 1)
138       myType = SLVS_C_UNKNOWN;
139     return getType();
140   }
141
142   // Constraint for the given length of a line
143   if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0) {
144     int aNbLines = 0;
145     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
146       std::shared_ptr<ModelAPI_Attribute> anAttr = 
147           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
148       if (typeOfAttribute(anAttr) == LINE)
149         myAttributesList[aNbLines++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
150     }
151     if (aNbLines == 1)
152       myType = SLVS_C_PT_PT_DISTANCE;
153     return getType();
154   }
155
156   // Constraint for two parallel/perpendicular lines
157   bool isParallel = (aConstraintKind.compare(SketchPlugin_ConstraintParallel::ID()) == 0);
158   bool isPerpendicular = (aConstraintKind.compare(SketchPlugin_ConstraintPerpendicular::ID()) == 0);
159   if (isParallel || isPerpendicular) {
160     int aNbEntities = 2;  // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
161     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
162       std::shared_ptr<ModelAPI_Attribute> anAttr = 
163           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
164       if (typeOfAttribute(anAttr) == LINE)
165         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
166     }
167     if (aNbEntities == 4)
168       myType = isParallel ? SLVS_C_PARALLEL : SLVS_C_PERPENDICULAR;
169     return getType();
170   }
171
172   // Constraint for radius of a circle or an arc of circle
173   if (aConstraintKind.compare(SketchPlugin_ConstraintRadius::ID()) == 0) {
174     int aNbEntities = 2;  // lines in SolveSpace constraints should started from SketchPlugin_Constraint::ENTITY_C() attribute
175     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
176       std::shared_ptr<ModelAPI_Attribute> anAttr = 
177           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
178       AttrType aType = typeOfAttribute(anAttr);
179       if (aType == CIRCLE || aType == ARC)
180         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
181     }
182     if (aNbEntities == 3)
183       myType = SLVS_C_DIAMETER;
184     return getType();
185   }
186
187   // Constraint for fixed entity
188   if (aConstraintKind.compare(SketchPlugin_ConstraintRigid::ID()) == 0) {
189     // Verify that only one entity is filled
190     int aNbAttrs = 0;
191     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
192       std::shared_ptr<ModelAPI_Attribute> anAttr = 
193           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
194       AttrType aType = typeOfAttribute(anAttr);
195       if (aType != UNKNOWN)
196         myAttributesList[aNbAttrs++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
197     }
198     if (aNbAttrs == 1)
199       myType = SLVS_C_WHERE_DRAGGED;
200     return getType();
201   }
202
203   // Constraint for horizontal/vertical line
204   bool isHorizontal = (aConstraintKind.compare(SketchPlugin_ConstraintHorizontal::ID()) == 0);
205   bool isVertical = (aConstraintKind.compare(SketchPlugin_ConstraintVertical::ID()) == 0);
206   if (isHorizontal || isVertical) {
207     int aNbEntities = 2;  // lines in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
208     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
209       std::shared_ptr<ModelAPI_Attribute> anAttr = 
210           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
211       if (typeOfAttribute(anAttr) == LINE)
212         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
213     }
214     if (aNbEntities == 3)
215       myType = isHorizontal ? SLVS_C_HORIZONTAL : SLVS_C_VERTICAL;
216     return getType();
217   }
218
219   if (aConstraintKind.compare(SketchPlugin_ConstraintEqual::ID()) == 0)
220   {
221     static const int aConstrType[3] = {
222         SLVS_C_EQUAL_RADIUS,
223         SLVS_C_EQUAL_LINE_ARC_LEN,
224         SLVS_C_EQUAL_LENGTH_LINES
225     };
226     int aNbLines = 0;
227     int aNbEntities = 2;  // lines and circles in SolveSpace constraints should start from SketchPlugin_Constraint::ENTITY_C() attribute
228     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++) {
229       std::shared_ptr<ModelAPI_Attribute> anAttr = 
230           aConstrData->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
231       AttrType aType = typeOfAttribute(anAttr);
232       if (aType == LINE)
233       {
234         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
235         aNbLines++;
236       }
237       else if (aType == CIRCLE || aType == ARC)
238         myAttributesList[aNbEntities++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
239     }
240     if (aNbEntities == 4)
241       myType = aConstrType[aNbLines];
242     return getType();
243   }
244
245   /// \todo Implement other kind of constraints
246
247   return getType();
248 }
249
250 // ================= Auxiliary functions ==============================
251 AttrType typeOfAttribute(std::shared_ptr<ModelAPI_Attribute> theAttribute)
252 {
253   std::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef = std::dynamic_pointer_cast<
254       ModelAPI_AttributeRefAttr>(theAttribute);
255   if (!anAttrRef)
256     return UNKNOWN;
257
258   if (anAttrRef->isObject()) {
259     ResultConstructionPtr aRC = std::dynamic_pointer_cast<ModelAPI_ResultConstruction>(
260         anAttrRef->object());
261     if (!aRC || !aRC->shape())
262       return UNKNOWN;
263
264     if (aRC->shape()->isVertex())
265       return POINT3D;
266     else if (aRC->shape()->isEdge()) {
267       std::shared_ptr<GeomAPI_Edge> anEdge = std::dynamic_pointer_cast<GeomAPI_Edge>(
268           aRC->shape());
269       if (anEdge->isLine())
270         return LINE;
271       else if (anEdge->isCircle())
272         return CIRCLE;
273       else if (anEdge->isArc())
274         return ARC;
275     }
276   } else {
277     if (anAttrRef->attr().get() != NULL) {
278       const std::string aType = anAttrRef->attr()->attributeType();
279       if (aType == GeomDataAPI_Point2D::type())
280         return POINT2D;
281       if (aType == GeomDataAPI_Point2D::type())
282         return POINT2D;
283     }
284   }
285
286   return UNKNOWN;
287 }
288