]> SALOME platform Git repositories - modules/shaper.git/blob - src/SketchSolver/SketchSolver_Storage.cpp
Salome HOME
SketchSolver library refactoring
[modules/shaper.git] / src / SketchSolver / SketchSolver_Storage.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    SketchSolver_Storage.cpp
4 // Created: 18 Mar 2015
5 // Author:  Artem ZHIDKOV
6
7 #include <SketchSolver_Storage.h>
8
9 /** \brief Search the entity/parameter with specified ID in the list of elements
10  *  \param[in] theEntityID unique ID of the element
11  *  \param[in] theEntities list of elements
12  *  \return position of the found element or -1 if the element is not found
13  */
14 template<typename T>
15 static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
16
17 /// \brief Compare two parameters to be different
18 static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
19 /// \brief Compare two entities to be different
20 static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
21 /// \brief Compare two constriants to be different
22 static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
23
24
25 SketchSolver_Storage::SketchSolver_Storage()
26   : myParamMaxID(SLVS_E_UNKNOWN),
27     myEntityMaxID(SLVS_E_UNKNOWN),
28     myConstrMaxID(SLVS_C_UNKNOWN),
29     myNeedToResolve(false)
30 {
31 }
32
33 Slvs_hParam SketchSolver_Storage::addParameter(const Slvs_Param& theParam)
34 {
35   if (theParam.h > 0 && theParam.h <= myParamMaxID) {
36     // parameter is already used, rewrite it
37     return updateParameter(theParam);
38   }
39
40   Slvs_Param aParam = theParam;
41   if (aParam.h > myParamMaxID)
42     myParamMaxID = aParam.h;
43   else
44     aParam.h = ++myParamMaxID;
45   myParameters.push_back(aParam);
46   myNeedToResolve = true;
47   return aParam.h;
48 }
49
50 Slvs_hParam SketchSolver_Storage::updateParameter(const Slvs_Param& theParam)
51 {
52   if (theParam.h > 0 && theParam.h <= myParamMaxID) {
53     // parameter already used, rewrite it
54     int aPos = Search(theParam.h, myParameters);
55     if (aPos >= 0 && aPos < (int)myParameters.size()) {
56       myNeedToResolve = myNeedToResolve || IsNotEqual(myParameters[aPos], theParam);
57       myParameters[aPos] = theParam;
58       return theParam.h;
59     }
60   }
61
62   // Parameter is not found, add new one
63   Slvs_Param aParam = theParam;
64   aParam.h = 0;
65   return addParameter(aParam);
66 }
67
68 bool SketchSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
69 {
70   int aPos = Search(theParamID, myParameters);
71   if (aPos >= 0 && aPos < (int)myParameters.size()) {
72     // Firstly, search the parametes is not used elsewhere
73     std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
74     for (; anEntIter != myEntities.end(); anEntIter++) {
75       for (int i = 0; i < 4; i++)
76         if (anEntIter->param[i] == theParamID)
77           return false;
78     }
79     // Remove parameter
80     myParameters.erase(myParameters.begin() + aPos);
81     myNeedToResolve = true;
82     myRemovedParameters.insert(theParamID);
83     return true;
84   }
85   return false;
86 }
87
88 const Slvs_Param& SketchSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
89 {
90   int aPos = Search(theParamID, myParameters);
91   if (aPos >= 0 && aPos < (int)myParameters.size())
92     return myParameters[aPos];
93
94   // Parameter is not found, return empty object
95   static Slvs_Param aDummy;
96   aDummy.h = 0;
97   return aDummy;
98 }
99
100
101 Slvs_hEntity SketchSolver_Storage::addEntity(const Slvs_Entity& theEntity)
102 {
103   if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
104     // Entity is already used, rewrite it
105     return updateEntity(theEntity);
106   }
107
108   Slvs_Entity aEntity = theEntity;
109   if (aEntity.h > myEntityMaxID)
110     myEntityMaxID = aEntity.h;
111   else
112     aEntity.h = ++myEntityMaxID;
113   myEntities.push_back(aEntity);
114   myNeedToResolve = true;
115   return aEntity.h;
116 }
117
118 Slvs_hEntity SketchSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
119 {
120   if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
121     // Entity already used, rewrite it
122     int aPos = Search(theEntity.h, myEntities);
123     if (aPos >= 0 && aPos < (int)myEntities.size()) {
124       myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
125       myEntities[aPos] = theEntity;
126       return theEntity.h;
127     }
128   }
129
130   // Entity is not found, add new one
131   Slvs_Entity aEntity = theEntity;
132   aEntity.h = 0;
133   return addEntity(aEntity);
134 }
135
136 bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
137 {
138   bool aResult = true;
139   int aPos = Search(theEntityID, myEntities);
140   if (aPos >= 0 && aPos < (int)myEntities.size()) {
141     // Firstly, check the entity is not used elsewhere
142     std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
143     for (; anEntIter != myEntities.end(); anEntIter++) {
144       for (int i = 0; i < 4; i++)
145         if (anEntIter->point[i] == theEntityID)
146           return false;
147       if (anEntIter->distance == theEntityID)
148         return false;
149     }
150     std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
151     for (; aConstrIter != myConstraints.end(); aConstrIter++) {
152       Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
153           aConstrIter->entityA, aConstrIter->entityB,
154           aConstrIter->entityC, aConstrIter->entityD};
155       for (int i = 0; i < 6; i++)
156         if (anEntIDs[i] == theEntityID)
157           return false;
158     }
159     // The entity is not used, remove it and its parameters
160     Slvs_Entity anEntity = myEntities[aPos];
161     myEntities.erase(myEntities.begin() + aPos);
162     if (anEntity.distance != SLVS_E_UNKNOWN)
163       aResult = aResult && removeParameter(anEntity.distance);
164     for (int i = 0; i < 4; i++)
165       if (anEntity.param[i] != SLVS_E_UNKNOWN)
166         aResult = removeParameter(anEntity.param[i]) && aResult;
167     for (int i = 0; i < 4; i++)
168       if (anEntity.point[i] != SLVS_E_UNKNOWN)
169         aResult = removeEntity(anEntity.point[i]) && aResult;
170     myNeedToResolve = true;
171     myRemovedEntities.insert(theEntityID);
172   }
173   return aResult;
174 }
175
176 const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
177 {
178   int aPos = Search(theEntityID, myEntities);
179   if (aPos >= 0 && aPos < (int)myEntities.size())
180     return myEntities[aPos];
181
182   // Entity is not found, return empty object
183   static Slvs_Entity aDummy;
184   aDummy.h = 0;
185   return aDummy;
186 }
187
188
189 Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
190 {
191   if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
192     // Constraint is already used, rewrite it
193     return updateConstraint(theConstraint);
194   }
195
196   Slvs_Constraint aConstraint = theConstraint;
197   if (aConstraint.h > myConstrMaxID)
198     myConstrMaxID = aConstraint.h;
199   else
200     aConstraint.h = ++myConstrMaxID;
201   myConstraints.push_back(aConstraint);
202   myNeedToResolve = true;
203   return aConstraint.h;
204 }
205
206 Slvs_hConstraint SketchSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
207 {
208   if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
209     // Constraint already used, rewrite it
210     int aPos = Search(theConstraint.h, myConstraints);
211     if (aPos >= 0 && aPos < (int)myConstraints.size()) {
212       myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
213       myConstraints[aPos] = theConstraint;
214       return theConstraint.h;
215     }
216   }
217
218   // Constraint is not found, add new one
219   Slvs_Constraint aConstraint = theConstraint;
220   aConstraint.h = 0;
221   return addConstraint(aConstraint);
222 }
223
224 bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
225 {
226   bool aResult = true;
227   int aPos = Search(theConstraintID, myConstraints);
228   if (aPos >= 0 && aPos < (int)myConstraints.size()) {
229     Slvs_Constraint aConstraint = myConstraints[aPos];
230     myConstraints.erase(myConstraints.begin() + aPos);
231     myNeedToResolve = true;
232     myRemovedConstraints.insert(theConstraintID);
233     // Remove all entities
234     Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
235         aConstraint.entityA, aConstraint.entityB,
236         aConstraint.entityC, aConstraint.entityD};
237     for (int i = 0; i < 6; i++)
238       if (anEntities[i] != SLVS_E_UNKNOWN) {
239         aResult = removeEntity(anEntities[i]) && aResult;
240         // remove temporary fixed points, if exists
241         std::vector<Slvs_hEntity>::iterator aFPIt = myFixedPoints.begin();
242         for (; aFPIt != myFixedPoints.end(); aFPIt++)
243           if (*aFPIt == anEntities[i]) {
244             myFixedPoints.erase(aFPIt);
245             break;
246           }
247       }
248   }
249   return aResult;
250 }
251
252 const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
253 {
254   int aPos = Search(theConstraintID, myConstraints);
255   if (aPos >= 0 && aPos < (int)myConstraints.size())
256     return myConstraints[aPos];
257
258   // Constraint is not found, return empty object
259   static Slvs_Constraint aDummy;
260   aDummy.h = 0;
261   return aDummy;
262 }
263
264 void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
265 {
266   int aPos = Search(theConstraintID, myConstraints);
267   myFixedPoints.push_back(myConstraints[aPos].ptA);
268 }
269
270 void SketchSolver_Storage::getRemoved(
271     std::set<Slvs_hParam>& theParameters,
272     std::set<Slvs_hEntity>& theEntities,
273     std::set<Slvs_hConstraint>& theConstraints)
274 {
275   theParameters = myRemovedParameters;
276   theEntities = myRemovedEntities;
277   theConstraints = myRemovedConstraints;
278
279   myRemovedParameters.clear();
280   myRemovedEntities.clear();
281   myRemovedConstraints.clear();
282 }
283
284 void SketchSolver_Storage::initializeSolver(SketchSolver_Solver& theSolver)
285 {
286   theSolver.setParameters(myParameters.data(), (int)myParameters.size());
287   theSolver.setEntities(myEntities.data(), (int)myEntities.size());
288   theSolver.setConstraints(myConstraints.data(), (int)myConstraints.size());
289
290   // initialize fixed points
291   if (!myFixedPoints.empty()) {
292     int aPos = Search(myFixedPoints.front(), myEntities);
293     theSolver.setDraggedParameters(myEntities[aPos].param);
294   }
295 }
296
297
298 // ========================================================
299 // =========      Auxiliary functions       ===============
300 // ========================================================
301
302 template<typename T>
303 int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
304 {
305   int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
306   int aVecSize = theEntities.size();
307   while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
308     aResIndex--;
309   while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
310     aResIndex++;
311   if (aResIndex == -1)
312     aResIndex = aVecSize;
313   return aResIndex;
314 }
315
316 bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
317 {
318   return fabs(theParam1.val - theParam2.val) > tolerance;
319 }
320
321 bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
322 {
323   int i = 0;
324   for (; theEntity1.param[i] != 0 && i < 4; i++)
325     if (theEntity1.param[i] != theEntity2.param[i])
326       return true;
327   i = 0;
328   for (; theEntity1.point[i] != 0 && i < 4; i++)
329     if (theEntity1.point[i] != theEntity2.point[i])
330       return true;
331   return false;
332 }
333
334 bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
335 {
336   return theConstraint1.ptA != theConstraint2.ptA ||
337          theConstraint1.ptB != theConstraint2.ptB ||
338          theConstraint1.entityA != theConstraint2.entityA ||
339          theConstraint1.entityB != theConstraint2.entityB ||
340          theConstraint1.entityC != theConstraint2.entityC ||
341          theConstraint1.entityD != theConstraint2.entityD ||
342          fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;
343 }