]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Constraint.cpp
Salome HOME
Merge branch 'master' of newgeom:newgeom.git
[modules/shaper.git] / src / SketchSolver / SketchSolver_Constraint.cpp
1 // File:    SketchSolver_Constraint.cpp
2 // Created: 27 May 2014
3 // Author:  Artem ZHIDKOV
4
5 #include "SketchSolver_Constraint.h"
6 #include <SketchSolver_Solver.h>
7
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>
18
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>
24
25 #include <GeomDataAPI_Point.h>
26 #include <GeomDataAPI_Point2D.h>
27 #include <GeomAPI_Edge.h>
28 #include <GeomAPI_Shape.h>
29
30 /// Possible types of attributes (used to determine constraint type)
31 enum AttrType
32 {
33   UNKNOWN, // Something wrong during type determination
34   POINT2D,
35   POINT3D,
36   LINE,
37   CIRCLE,
38   ARC
39 };
40
41 /// Calculate type of the attribute
42 static AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute);
43
44
45
46 SketchSolver_Constraint::SketchSolver_Constraint()
47   : myConstraint(boost::shared_ptr<SketchPlugin_Constraint>()),
48     myType(SLVS_C_UNKNOWN),
49     myAttributesList()
50 {
51 }
52
53 SketchSolver_Constraint::SketchSolver_Constraint(
54                 boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
55   : myConstraint(theConstraint),
56     myAttributesList()
57 {
58   myType = getType(myConstraint);
59 }
60
61 const int& SketchSolver_Constraint::getType(boost::shared_ptr<SketchPlugin_Constraint> theConstraint)
62 {
63   myType = SLVS_C_UNKNOWN;
64   if (!theConstraint)
65     return getType();
66
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());
71
72   const std::string& aConstraintKind = theConstraint->getKind();
73   // Constraint for coincidence of two points
74   if (aConstraintKind.compare(SketchPlugin_ConstraintCoincidence::ID()) == 0)
75   {
76     int anAttrPos = 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++)
81     {
82       boost::shared_ptr<ModelAPI_Attribute> anAttr =
83         theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
84       if (!anAttr) continue;
85       switch (typeOfAttribute(anAttr))
86       {
87       case POINT2D: // the attribute is a 2D point
88         aPt2d |= (1 << indAttr);
89         myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
90         break;
91       case POINT3D: // the attribute is a 3D point
92         aPt3d |= (1 << indAttr);
93         myAttributesList[anAttrPos++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
94         break;
95       default:
96         // Attribute neither 2D nor 3D point is not supported by this type of constraint
97         return getType();
98       }
99     }
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
105     return getType();
106   }
107
108   // Constraint for distance between point and another entity
109   if (aConstraintKind.compare(SketchPlugin_ConstraintDistance::ID()) == 0)
110   {
111     int aNbPoints = 0;
112     int aNbEntities = 0;
113     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
114     {
115       boost::shared_ptr<ModelAPI_Attribute> anAttr =
116         theConstraint->data()->attribute(SketchPlugin_Constraint::ATTRIBUTE(indAttr));
117       switch (typeOfAttribute(anAttr))
118       {
119       case POINT2D:
120       case POINT3D:
121           myAttributesList[aNbPoints++] = SketchPlugin_Constraint::ATTRIBUTE(indAttr);
122           break;
123       case LINE:
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;
127           break;
128       }
129     }
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;
135     return getType();
136   }
137
138   // Constraint for the given length of a line
139   if (aConstraintKind.compare(SketchPlugin_ConstraintLength::ID()) == 0)
140   {
141     int aNbLines = 0;
142     for (unsigned int indAttr = 0; indAttr < CONSTRAINT_ATTR_SIZE; indAttr++)
143     {
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);
148     }
149     if (aNbLines == 1)
150       myType = SLVS_C_PT_PT_DISTANCE;
151     return getType();
152   }
153
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)
158   {
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++)
161     {
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);
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   {
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     {
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);
183     }
184     if (aNbEntities == 3)
185       myType = SLVS_C_DIAMETER;
186     return getType();
187   }
188
189   /// \todo Implement other kind of constraints
190
191   return getType();
192 }
193
194
195 // ================= Auxiliary functions ==============================
196 AttrType typeOfAttribute(boost::shared_ptr<ModelAPI_Attribute> theAttribute)
197 {
198   boost::shared_ptr<ModelAPI_AttributeRefAttr> anAttrRef =
199     boost::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
200   if (!anAttrRef) return UNKNOWN;
201
202   if (anAttrRef->isObject())
203   {
204     ResultConstructionPtr aRC = 
205       boost::dynamic_pointer_cast<ModelAPI_ResultConstruction>(anAttrRef->object());
206     if (!aRC) return UNKNOWN;
207
208     if (aRC->shape()->isVertex())
209       return POINT3D;
210     else if (aRC->shape()->isEdge())
211     {
212       boost::shared_ptr<GeomAPI_Edge> anEdge = 
213         boost::dynamic_pointer_cast<GeomAPI_Edge>(aRC->shape());
214       if (anEdge->isLine())
215         return LINE;
216       else if (anEdge->isCircle())
217         return CIRCLE;
218       else if (anEdge->isArc())
219         return ARC;
220     }
221   }
222   else
223   {
224     const std::string aType = anAttrRef->attr()->attributeType();
225     if (aType == GeomDataAPI_Point2D::type())
226       return POINT2D;
227     if (aType == GeomDataAPI_Point2D::type())
228       return POINT2D;
229   }
230
231   return UNKNOWN;
232 }
233