1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: SketchSolver_Storage.cpp
4 // Created: 18 Mar 2015
5 // Author: Artem ZHIDKOV
7 #include <SketchSolver_Storage.h>
11 /** \brief Search the entity/parameter with specified ID in the list of elements
12 * \param[in] theEntityID unique ID of the element
13 * \param[in] theEntities list of elements
14 * \return position of the found element or -1 if the element is not found
17 static int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities);
19 /// \brief Compare two parameters to be different
20 static bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2);
21 /// \brief Compare two entities to be different
22 static bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2);
23 /// \brief Compare two constriants to be different
24 static bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2);
27 SketchSolver_Storage::SketchSolver_Storage()
28 : myParamMaxID(SLVS_E_UNKNOWN),
29 myEntityMaxID(SLVS_E_UNKNOWN),
30 myConstrMaxID(SLVS_C_UNKNOWN),
31 myFixed(SLVS_E_UNKNOWN),
32 myNeedToResolve(false),
33 myDuplicatedConstraint(false)
37 Slvs_hParam SketchSolver_Storage::addParameter(const Slvs_Param& theParam)
39 if (theParam.h > 0 && theParam.h <= myParamMaxID) {
40 // parameter is already used, rewrite it
41 return updateParameter(theParam);
44 Slvs_Param aParam = theParam;
45 if (aParam.h > myParamMaxID)
46 myParamMaxID = aParam.h;
48 aParam.h = ++myParamMaxID;
49 myParameters.push_back(aParam);
50 myNeedToResolve = true;
54 Slvs_hParam SketchSolver_Storage::updateParameter(const Slvs_Param& theParam)
56 if (theParam.h > 0 && theParam.h <= myParamMaxID) {
57 // parameter already used, rewrite it
58 int aPos = Search(theParam.h, myParameters);
59 if (aPos >= 0 && aPos < (int)myParameters.size()) {
60 myNeedToResolve = myNeedToResolve || IsNotEqual(myParameters[aPos], theParam);
61 myParameters[aPos] = theParam;
66 // Parameter is not found, add new one
67 Slvs_Param aParam = theParam;
69 return addParameter(aParam);
72 bool SketchSolver_Storage::removeParameter(const Slvs_hParam& theParamID)
74 int aPos = Search(theParamID, myParameters);
75 if (aPos >= 0 && aPos < (int)myParameters.size()) {
76 // Firstly, search the parametes is not used elsewhere
77 std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
78 for (; anEntIter != myEntities.end(); anEntIter++) {
79 for (int i = 0; i < 4; i++)
80 if (anEntIter->param[i] == theParamID)
84 myParameters.erase(myParameters.begin() + aPos);
85 myParamMaxID = myParameters.empty() ? SLVS_E_UNKNOWN : myParameters.back().h;
86 myNeedToResolve = true;
87 myRemovedParameters.insert(theParamID);
93 const Slvs_Param& SketchSolver_Storage::getParameter(const Slvs_hParam& theParamID) const
95 int aPos = Search(theParamID, myParameters);
96 if (aPos >= 0 && aPos < (int)myParameters.size())
97 return myParameters[aPos];
99 // Parameter is not found, return empty object
100 static Slvs_Param aDummy;
106 Slvs_hEntity SketchSolver_Storage::addEntity(const Slvs_Entity& theEntity)
108 if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
109 // Entity is already used, rewrite it
110 return updateEntity(theEntity);
113 Slvs_Entity aEntity = theEntity;
114 if (aEntity.h > myEntityMaxID)
115 myEntityMaxID = aEntity.h;
117 aEntity.h = ++myEntityMaxID;
118 myEntities.push_back(aEntity);
119 myNeedToResolve = true;
123 Slvs_hEntity SketchSolver_Storage::updateEntity(const Slvs_Entity& theEntity)
125 if (theEntity.h > 0 && theEntity.h <= myEntityMaxID) {
126 // Entity already used, rewrite it
127 int aPos = Search(theEntity.h, myEntities);
128 if (aPos >= 0 && aPos < (int)myEntities.size()) {
129 myNeedToResolve = myNeedToResolve || IsNotEqual(myEntities[aPos], theEntity);
130 myEntities[aPos] = theEntity;
135 // Entity is not found, add new one
136 Slvs_Entity aEntity = theEntity;
138 return addEntity(aEntity);
141 bool SketchSolver_Storage::removeEntity(const Slvs_hEntity& theEntityID)
144 int aPos = Search(theEntityID, myEntities);
145 if (aPos >= 0 && aPos < (int)myEntities.size()) {
146 // Firstly, check the entity and its attributes is not used elsewhere
147 std::set<Slvs_hEntity> anEntAndSubs;
148 anEntAndSubs.insert(theEntityID);
149 for (int i = 0; i < 4; i++)
150 if (myEntities[aPos].point[i] != SLVS_E_UNKNOWN)
151 anEntAndSubs.insert(myEntities[aPos].point[i]);
153 std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
154 for (; anEntIter != myEntities.end(); anEntIter++) {
155 for (int i = 0; i < 4; i++)
156 if (anEntAndSubs.find(anEntIter->point[i]) != anEntAndSubs.end())
158 if (anEntAndSubs.find(anEntIter->distance) != anEntAndSubs.end())
161 std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
162 for (; aConstrIter != myConstraints.end(); aConstrIter++) {
163 Slvs_hEntity anEntIDs[6] = {aConstrIter->ptA, aConstrIter->ptB,
164 aConstrIter->entityA, aConstrIter->entityB,
165 aConstrIter->entityC, aConstrIter->entityD};
166 for (int i = 0; i < 6; i++)
167 if (anEntAndSubs.find(anEntIDs[i]) != anEntAndSubs.end())
170 // The entity is not used, remove it and its parameters
171 Slvs_Entity anEntity = myEntities[aPos];
172 myEntities.erase(myEntities.begin() + aPos);
173 myEntityMaxID = myEntities.empty() ? SLVS_E_UNKNOWN : myEntities.back().h;
174 if (anEntity.distance != SLVS_E_UNKNOWN)
175 aResult = aResult && removeParameter(anEntity.distance);
176 for (int i = 0; i < 4; i++)
177 if (anEntity.param[i] != SLVS_E_UNKNOWN)
178 aResult = removeParameter(anEntity.param[i]) && aResult;
179 for (int i = 0; i < 4; i++)
180 if (anEntity.point[i] != SLVS_E_UNKNOWN)
181 aResult = removeEntity(anEntity.point[i]) && aResult;
182 myNeedToResolve = true;
183 myRemovedEntities.insert(theEntityID);
184 if (anEntity.type == SLVS_E_POINT_IN_2D || anEntity.type == SLVS_E_POINT_IN_3D)
185 removeCoincidentPoint(theEntityID);
190 const Slvs_Entity& SketchSolver_Storage::getEntity(const Slvs_hEntity& theEntityID) const
192 int aPos = Search(theEntityID, myEntities);
193 if (aPos >= 0 && aPos < (int)myEntities.size())
194 return myEntities[aPos];
196 // Entity is not found, return empty object
197 static Slvs_Entity aDummy;
198 aDummy.h = SLVS_E_UNKNOWN;
202 Slvs_hEntity SketchSolver_Storage::copyEntity(const Slvs_hEntity& theCopied)
204 int aPos = Search(theCopied, myEntities);
205 if (aPos < 0 || aPos >= (int)myEntities.size())
206 return SLVS_E_UNKNOWN;
208 Slvs_Entity aCopy = myEntities[aPos];
209 aCopy.h = SLVS_E_UNKNOWN;
211 while (aCopy.point[i] != SLVS_E_UNKNOWN) {
212 aCopy.point[i] = copyEntity(aCopy.point[i]);
215 if (aCopy.param[0] != SLVS_E_UNKNOWN) {
216 aPos = Search(aCopy.param[0], myParameters);
218 while (aCopy.param[i] != SLVS_E_UNKNOWN) {
219 Slvs_Param aNewParam = myParameters[aPos];
220 aNewParam.h = SLVS_E_UNKNOWN;
221 aCopy.param[i] = addParameter(aNewParam);
226 return addEntity(aCopy);
229 void SketchSolver_Storage::copyEntity(const Slvs_hEntity& theFrom, const Slvs_hEntity& theTo)
231 int aPosFrom = Search(theFrom, myEntities);
232 int aPosTo = Search(theTo, myEntities);
233 if (aPosFrom < 0 || aPosFrom >= (int)myEntities.size() ||
234 aPosTo < 0 || aPosTo >= (int)myEntities.size())
237 Slvs_Entity aEntFrom = myEntities[aPosFrom];
238 Slvs_Entity aEntTo = myEntities[aPosTo];
240 while (aEntFrom.point[i] != SLVS_E_UNKNOWN) {
241 copyEntity(aEntFrom.point[i], aEntTo.point[i]);
244 if (aEntFrom.param[0] != SLVS_E_UNKNOWN) {
245 aPosFrom = Search(aEntFrom.param[0], myParameters);
246 aPosTo = Search(aEntTo.param[0], myParameters);
248 while (aEntFrom.param[i] != SLVS_E_UNKNOWN) {
249 myParameters[aPosTo++].val = myParameters[aPosFrom++].val;
256 bool SketchSolver_Storage::isPointFixed(
257 const Slvs_hEntity& thePointID, Slvs_hConstraint& theFixed, bool theAccurate) const
259 // Search the set of coincident points
260 std::set<Slvs_hEntity> aCoincident;
261 aCoincident.insert(thePointID);
262 std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
263 for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
264 if (aCPIter->find(thePointID) != aCPIter->end()) {
265 aCoincident = *aCPIter;
269 // Search the Rigid constraint
270 std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
271 for (; aConstrIter != myConstraints.end(); aConstrIter++)
272 if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
273 aCoincident.find(aConstrIter->ptA) != aCoincident.end()) {
274 theFixed = aConstrIter->h;
279 // Try to find the fixed entity which uses such point or its coincidence
280 std::vector<Slvs_Entity>::const_iterator anEntIter = myEntities.begin();
281 for (; anEntIter != myEntities.end(); anEntIter++) {
282 for (int i = 0; i < 4; i++) {
283 Slvs_hEntity aPt = anEntIter->point[i];
284 if (aPt != SLVS_E_UNKNOWN &&
285 (aPt == thePointID || aCoincident.find(aPt) != aCoincident.end())) {
286 if (isEntityFixed(anEntIter->h, true))
292 return SLVS_E_UNKNOWN;
295 bool SketchSolver_Storage::isEntityFixed(const Slvs_hEntity& theEntityID, bool theAccurate) const
297 int aPos = Search(theEntityID, myEntities);
298 if (aPos < 0 || aPos >= (int)myEntities.size())
301 // Firstly, find how many points are under Rigid constraint
303 for (int i = 0; i < 4; i++) {
304 Slvs_hEntity aPoint = myEntities[aPos].point[i];
305 if (aPoint == SLVS_E_UNKNOWN)
308 std::set<Slvs_hEntity> aCoincident;
309 aCoincident.insert(aPoint);
310 std::vector< std::set<Slvs_hEntity> >::const_iterator aCPIter = myCoincidentPoints.begin();
311 for (; aCPIter != myCoincidentPoints.end(); aCPIter++)
312 if (aCPIter->find(aPoint) != aCPIter->end()) {
313 aCoincident = *aCPIter;
317 // Search the Rigid constraint
318 std::vector<Slvs_Constraint>::const_iterator aConstrIter = myConstraints.begin();
319 for (; aConstrIter != myConstraints.end(); aConstrIter++)
320 if (aConstrIter->type == SLVS_C_WHERE_DRAGGED &&
321 aCoincident.find(aConstrIter->ptA) != aCoincident.end())
325 std::list<Slvs_Constraint> aList;
326 std::list<Slvs_Constraint>::iterator anIt;
327 Slvs_hConstraint aTempID; // used in isPointFixed() method
329 if (myEntities[aPos].type == SLVS_E_LINE_SEGMENT) {
332 else if (aNbFixed == 0 || !theAccurate)
334 // Additional check (the line may be fixed if it is used by different constraints):
335 // 1. The line is used in Equal constraint, another entity is fixed and there is a fixed point on line
336 aList = getConstraintsByType(SLVS_C_PT_ON_LINE);
337 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
338 if (anIt->entityA == theEntityID && isPointFixed(anIt->ptA, aTempID))
340 if (anIt != aList.end()) {
341 aList = getConstraintsByType(SLVS_C_EQUAL_LENGTH_LINES);
342 aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
343 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
344 if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
345 Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
346 if (isEntityFixed(anOther, false))
350 // 2. The line is used in Parallel/Perpendicular/Vertical/Horizontal and Length constraints
351 aList = getConstraintsByType(SLVS_C_PARALLEL);
352 aList.splice(aList.end(), getConstraintsByType(SLVS_C_PERPENDICULAR));
353 aList.splice(aList.end(), getConstraintsByType(SLVS_C_VERTICAL));
354 aList.splice(aList.end(), getConstraintsByType(SLVS_C_HORIZONTAL));
355 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
356 if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
357 Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
358 if (isEntityFixed(anOther, false))
361 if (anIt != aList.end()) {
362 aList = getConstraintsByType(SLVS_C_PT_PT_DISTANCE);
363 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
364 if ((anIt->ptA == myEntities[aPos].point[0] && anIt->ptB == myEntities[aPos].point[1]) ||
365 (anIt->ptA == myEntities[aPos].point[1] && anIt->ptB == myEntities[aPos].point[0]))
368 // 3. Another verifiers ...
369 } else if (myEntities[aPos].type == SLVS_E_CIRCLE) {
372 // Search for Diameter constraint
373 aList = getConstraintsByType(SLVS_C_DIAMETER);
374 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
375 if (anIt->entityA == theEntityID)
379 // Additional check (the circle may be fixed if it is used by different constraints):
380 // 1. The circle is used in Equal constraint and another entity is fixed
381 aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
382 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
383 if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
384 Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
385 if (isEntityFixed(anOther, false))
388 // 2. Another verifiers ...
389 } else if (myEntities[aPos].type == SLVS_E_ARC_OF_CIRCLE) {
392 else if (aNbFixed <= 1)
394 // Search for Diameter constraint
395 aList = getConstraintsByType(SLVS_C_DIAMETER);
396 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
397 if (anIt->entityA == theEntityID)
401 // Additional check (the arc may be fixed if it is used by different constraints):
402 // 1. The arc is used in Equal constraint and another entity is fixed
403 aList = getConstraintsByType(SLVS_C_EQUAL_RADIUS);
404 aList.splice(aList.end(), getConstraintsByType(SLVS_C_EQUAL_LINE_ARC_LEN));
405 for (anIt = aList.begin(); anIt != aList.end(); anIt++)
406 if (anIt->entityA == theEntityID || anIt->entityB == theEntityID) {
407 Slvs_hEntity anOther = anIt->entityA == theEntityID ? anIt->entityB : anIt->entityA;
408 if (isEntityFixed(anOther, false))
411 // 2. Another verifiers ...
417 Slvs_hConstraint SketchSolver_Storage::addConstraint(const Slvs_Constraint& theConstraint)
419 if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
420 // Constraint is already used, rewrite it
421 return updateConstraint(theConstraint);
424 Slvs_Constraint aConstraint = theConstraint;
426 // Find a constraint with same type uses same arguments to show user overconstraint situation
427 std::vector<Slvs_Constraint>::iterator aCIt = myConstraints.begin();
428 for (; aCIt != myConstraints.end(); aCIt++) {
429 if (aConstraint.type != aCIt->type)
431 if (aConstraint.ptA == aCIt->ptA && aConstraint.ptB == aCIt->ptB &&
432 aConstraint.entityA == aCIt->entityA && aConstraint.entityB == aCIt->entityB &&
433 aConstraint.entityC == aCIt->entityC && aConstraint.entityD == aCIt->entityD)
434 myDuplicatedConstraint = true;
437 if (aConstraint.h > myConstrMaxID)
438 myConstrMaxID = aConstraint.h;
440 aConstraint.h = ++myConstrMaxID;
441 myConstraints.push_back(aConstraint);
442 myNeedToResolve = true;
443 if (aConstraint.type == SLVS_C_POINTS_COINCIDENT)
444 addCoincidentPoints(aConstraint.ptA, aConstraint.ptB);
445 return aConstraint.h;
448 Slvs_hConstraint SketchSolver_Storage::updateConstraint(const Slvs_Constraint& theConstraint)
450 if (theConstraint.h > 0 && theConstraint.h <= myConstrMaxID) {
451 // Constraint already used, rewrite it
452 int aPos = Search(theConstraint.h, myConstraints);
453 if (aPos >= 0 && aPos < (int)myConstraints.size()) {
454 myNeedToResolve = myNeedToResolve || IsNotEqual(myConstraints[aPos], theConstraint);
455 myConstraints[aPos] = theConstraint;
456 if (theConstraint.type == SLVS_C_POINTS_COINCIDENT)
457 addCoincidentPoints(theConstraint.ptA, theConstraint.ptB);
458 return theConstraint.h;
462 // Constraint is not found, add new one
463 Slvs_Constraint aConstraint = theConstraint;
465 return addConstraint(aConstraint);
468 bool SketchSolver_Storage::removeConstraint(const Slvs_hConstraint& theConstraintID)
471 int aPos = Search(theConstraintID, myConstraints);
472 if (aPos >= 0 && aPos < (int)myConstraints.size()) {
473 Slvs_Constraint aConstraint = myConstraints[aPos];
474 myConstraints.erase(myConstraints.begin() + aPos);
475 myConstrMaxID = myConstraints.empty() ? SLVS_E_UNKNOWN : myConstraints.back().h;
476 myNeedToResolve = true;
477 myRemovedConstraints.insert(theConstraintID);
478 // Remove all entities
479 Slvs_hEntity anEntities[6] = {aConstraint.ptA, aConstraint.ptB,
480 aConstraint.entityA, aConstraint.entityB,
481 aConstraint.entityC, aConstraint.entityD};
482 for (int i = 0; i < 6; i++)
483 if (anEntities[i] != SLVS_E_UNKNOWN)
484 aResult = removeEntity(anEntities[i]) && aResult;
485 // remove temporary fixed point, if available
486 if (myFixed == theConstraintID)
487 myFixed = SLVS_E_UNKNOWN;
488 if (myDuplicatedConstraint) {
489 // Check the duplicated constraints are still available
490 myDuplicatedConstraint = false;
491 std::vector<Slvs_Constraint>::const_iterator anIt1 = myConstraints.begin();
492 std::vector<Slvs_Constraint>::const_iterator anIt2 = myConstraints.begin();
493 for (; anIt1 != myConstraints.end() && !myDuplicatedConstraint; anIt1++)
494 for (anIt2 = anIt1+1; anIt2 != myConstraints.end() && !myDuplicatedConstraint; anIt2++) {
495 if (anIt1->type != anIt2->type)
497 if (anIt1->ptA == anIt2->ptA && anIt1->ptB == anIt2->ptB &&
498 anIt1->entityA == anIt2->entityA && anIt1->entityB == anIt2->entityB &&
499 anIt1->entityC == anIt2->entityC && anIt1->entityD == anIt2->entityD)
500 myDuplicatedConstraint = true;
507 const Slvs_Constraint& SketchSolver_Storage::getConstraint(const Slvs_hConstraint& theConstraintID) const
509 int aPos = Search(theConstraintID, myConstraints);
510 if (aPos >= 0 && aPos < (int)myConstraints.size())
511 return myConstraints[aPos];
513 // Constraint is not found, return empty object
514 static Slvs_Constraint aDummy;
519 std::list<Slvs_Constraint> SketchSolver_Storage::getConstraintsByType(int theConstraintType) const
521 std::list<Slvs_Constraint> aResult;
522 std::vector<Slvs_Constraint>::const_iterator aCIter = myConstraints.begin();
523 for (; aCIter != myConstraints.end(); aCIter++)
524 if (aCIter->type == theConstraintType)
525 aResult.push_back(*aCIter);
530 void SketchSolver_Storage::addConstraintWhereDragged(const Slvs_hConstraint& theConstraintID)
532 if (myFixed != SLVS_E_UNKNOWN)
533 return; // the point is already fixed
534 int aPos = Search(theConstraintID, myConstraints);
535 if (aPos >= 0 && aPos < (int)myConstraints.size())
536 myFixed = theConstraintID;
539 void SketchSolver_Storage::addTemporaryConstraint(const Slvs_hConstraint& theConstraintID)
541 myTemporaryConstraints.insert(theConstraintID);
544 void SketchSolver_Storage::removeTemporaryConstraints()
546 myTemporaryConstraints.clear();
549 int SketchSolver_Storage::deleteTemporaryConstraint()
551 if (myTemporaryConstraints.empty())
553 // Search the point-on-line or a non-rigid constraint
554 std::set<Slvs_hConstraint>::iterator aCIt = myTemporaryConstraints.begin();
555 for (; aCIt != myTemporaryConstraints.end(); aCIt++) {
556 int aPos = Search(*aCIt, myConstraints);
557 if (aPos >= (int)myConstraints.size() || myConstraints[aPos].type != SLVS_C_WHERE_DRAGGED)
559 std::vector<Slvs_Constraint>::iterator anIt = myConstraints.begin();
560 for (; anIt != myConstraints.end(); anIt++)
561 if (anIt->type == SLVS_C_PT_ON_LINE && anIt->ptA == myConstraints[aPos].ptA)
563 if (anIt != myConstraints.end())
566 if (aCIt == myTemporaryConstraints.end())
567 aCIt = myTemporaryConstraints.begin();
568 bool aNewFixed = (*aCIt == myFixed);
569 removeConstraint(*aCIt);
570 myTemporaryConstraints.erase(aCIt);
572 for (aCIt = myTemporaryConstraints.begin(); aCIt != myTemporaryConstraints.end(); aCIt++) {
573 int aPos = Search(*aCIt, myConstraints);
574 if (myConstraints[aPos].type == SLVS_C_WHERE_DRAGGED) {
580 return (int)myTemporaryConstraints.size();
583 bool SketchSolver_Storage::isTemporary(const Slvs_hConstraint& theConstraintID) const
585 return myTemporaryConstraints.find(theConstraintID) != myTemporaryConstraints.end();
589 void SketchSolver_Storage::getRemoved(
590 std::set<Slvs_hParam>& theParameters,
591 std::set<Slvs_hEntity>& theEntities,
592 std::set<Slvs_hConstraint>& theConstraints)
594 theParameters = myRemovedParameters;
595 theEntities = myRemovedEntities;
596 theConstraints = myRemovedConstraints;
598 myRemovedParameters.clear();
599 myRemovedEntities.clear();
600 myRemovedConstraints.clear();
603 void SketchSolver_Storage::initializeSolver(SketchSolver_Solver& theSolver)
605 theSolver.setParameters(myParameters.data(), (int)myParameters.size());
606 theSolver.setEntities(myEntities.data(), (int)myEntities.size());
608 // Copy constraints excluding the fixed one
609 std::vector<Slvs_Constraint> aConstraints = myConstraints;
610 if (myFixed != SLVS_E_UNKNOWN) {
611 Slvs_hEntity aFixedPoint = SLVS_E_UNKNOWN;
612 std::vector<Slvs_Constraint>::iterator anIt = aConstraints.begin();
613 for (; anIt != aConstraints.end(); anIt++)
614 if (anIt->h == myFixed) {
615 aFixedPoint = anIt->ptA;
616 aConstraints.erase(anIt);
619 // set dragged parameters
620 int aPos = Search(aFixedPoint, myEntities);
621 theSolver.setDraggedParameters(myEntities[aPos].param);
623 theSolver.setConstraints(aConstraints.data(), (int)aConstraints.size());
626 void SketchSolver_Storage::addCoincidentPoints(
627 const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2)
629 std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
630 std::vector< std::set<Slvs_hEntity> >::iterator aFoundIter = myCoincidentPoints.end(); // already found coincidence
631 bool isFound = false;
632 for (; aCIter != myCoincidentPoints.end(); aCIter++) {
633 bool isFirstFound = aCIter->find(thePoint1) != aCIter->end();
634 bool isSecondFound = aCIter->find(thePoint2) != aCIter->end();
635 isFound = isFound || isFirstFound || isSecondFound;
636 if (isFirstFound && isSecondFound)
637 break; // already coincident
638 else if (isFirstFound || isSecondFound) {
639 if (aFoundIter != myCoincidentPoints.end()) {
641 aFoundIter->insert(aCIter->begin(), aCIter->end());
642 myCoincidentPoints.erase(aCIter);
645 aCIter->insert(thePoint1);
646 aCIter->insert(thePoint2);
649 // coincident points not found
651 std::set<Slvs_hEntity> aNewSet;
652 aNewSet.insert(thePoint1);
653 aNewSet.insert(thePoint2);
654 myCoincidentPoints.push_back(aNewSet);
658 void SketchSolver_Storage::removeCoincidentPoint(const Slvs_hEntity& thePoint)
660 std::vector< std::set<Slvs_hEntity> >::iterator aCIter = myCoincidentPoints.begin();
661 for (; aCIter != myCoincidentPoints.end(); aCIter++)
662 if (aCIter->find(thePoint) != aCIter->end()) {
663 aCIter->erase(thePoint);
664 if (aCIter->size() <= 1)
665 myCoincidentPoints.erase(aCIter);
670 bool SketchSolver_Storage::isCoincident(
671 const Slvs_hEntity& thePoint1, const Slvs_hEntity& thePoint2) const
673 std::vector< std::set<Slvs_hEntity> >::const_iterator aCIter = myCoincidentPoints.begin();
674 for (; aCIter != myCoincidentPoints.end(); aCIter++)
675 if (aCIter->find(thePoint1) != aCIter->end() && aCIter->find(thePoint2) != aCIter->end())
677 // precise checking of coincidence
678 int aEnt1Pos = Search(thePoint1, myEntities);
679 int aEnt2Pos = Search(thePoint2, myEntities);
680 if (aEnt1Pos >= 0 && aEnt1Pos < (int)myEntities.size() &&
681 aEnt2Pos >= 0 && aEnt2Pos < (int)myEntities.size()) {
684 for (int i = 0; i < 2; i++) {
685 aParamPos = Search(myEntities[aEnt1Pos].param[i], myParameters);
686 aDist[i] = myParameters[aParamPos].val;
687 aParamPos = Search(myEntities[aEnt2Pos].param[i], myParameters);
688 aDist[i] -= myParameters[aParamPos].val;
690 if (aDist[0] * aDist[0] + aDist[1] * aDist[1] < tolerance * tolerance)
699 // ========================================================
700 // ========= Auxiliary functions ===============
701 // ========================================================
704 int Search(const uint32_t& theEntityID, const std::vector<T>& theEntities)
706 int aResIndex = theEntityID <= theEntities.size() ? theEntityID - 1 : 0;
707 int aVecSize = theEntities.size();
708 if (theEntities.empty())
710 while (aResIndex >= 0 && theEntities[aResIndex].h > theEntityID)
712 while (aResIndex < aVecSize && aResIndex >= 0 && theEntities[aResIndex].h < theEntityID)
714 if (aResIndex == -1 || (aResIndex < aVecSize && theEntities[aResIndex].h != theEntityID))
715 aResIndex = aVecSize;
719 bool IsNotEqual(const Slvs_Param& theParam1, const Slvs_Param& theParam2)
721 return fabs(theParam1.val - theParam2.val) > tolerance;
724 bool IsNotEqual(const Slvs_Entity& theEntity1, const Slvs_Entity& theEntity2)
727 for (; theEntity1.param[i] != 0 && i < 4; i++)
728 if (theEntity1.param[i] != theEntity2.param[i])
731 for (; theEntity1.point[i] != 0 && i < 4; i++)
732 if (theEntity1.point[i] != theEntity2.point[i])
737 bool IsNotEqual(const Slvs_Constraint& theConstraint1, const Slvs_Constraint& theConstraint2)
739 return theConstraint1.ptA != theConstraint2.ptA ||
740 theConstraint1.ptB != theConstraint2.ptB ||
741 theConstraint1.entityA != theConstraint2.entityA ||
742 theConstraint1.entityB != theConstraint2.entityB ||
743 theConstraint1.entityC != theConstraint2.entityC ||
744 theConstraint1.entityD != theConstraint2.entityD ||
745 fabs(theConstraint1.valA - theConstraint2.valA) > tolerance;