Salome HOME
Update constraint Mirror.
[modules/shaper.git] / src / SketchSolver / SketchSolver_ConstraintCoincidence.cpp
1 #include <SketchSolver_ConstraintCoincidence.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Group.h>
4
5 #include <map>
6
7 bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
8 {
9   if (myBaseConstraint == theConstraint)
10     return true;
11   std::map<Slvs_hConstraint, ConstraintPtr>::const_iterator anIt = myExtraCoincidence.begin();
12   for (; anIt != myExtraCoincidence.end(); anIt++)
13     if (anIt->second == theConstraint)
14       return true;
15   return false;
16 }
17
18 std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
19 {
20   std::list<ConstraintPtr> aConstraints;
21   aConstraints.push_back(myBaseConstraint);
22   std::map<Slvs_hConstraint, ConstraintPtr>::const_iterator anIt = myExtraCoincidence.begin();
23   for (; anIt != myExtraCoincidence.end(); anIt++)
24     aConstraints.push_back(anIt->second);
25   return aConstraints;
26 }
27
28 bool SketchSolver_ConstraintCoincidence::isCoincide(
29     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
30 {
31   std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatIter = myFeatureMap.begin();
32   for (; aFeatIter != myFeatureMap.end(); aFeatIter++)
33     if (theConstraint->myFeatureMap.find(aFeatIter->first) != theConstraint->myFeatureMap.end())
34       return true;
35   std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrIter = myAttributeMap.begin();
36   for (; anAttrIter != myAttributeMap.end(); anAttrIter++)
37     if (theConstraint->myAttributeMap.find(anAttrIter->first) != theConstraint->myAttributeMap.end())
38       return true;
39   return false;
40 }
41
42 void SketchSolver_ConstraintCoincidence::attach(
43     std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
44 {
45   cleanErrorMsg();
46   Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
47   // Remove constraints from theConstraint
48   std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
49   for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
50     theConstraint->myStorage->removeConstraint(*aCIter);
51
52   if (myStorage == theConstraint->myStorage) {
53     // Clean removed items
54     std::set<Slvs_hParam> aRemParams;
55     std::set<Slvs_hEntity> aRemEnts;
56     std::set<Slvs_hConstraint> aRemConstr;
57     theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
58   }
59
60   // Copy data.
61   addConstraint(theConstraint->myBaseConstraint);
62   std::map<Slvs_hConstraint, ConstraintPtr>::iterator aConstrIter =
63       theConstraint->myExtraCoincidence.begin();
64   for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
65     addConstraint(aConstrIter->second);
66   // Clear the lists to not remove the entities on destruction
67   theConstraint->mySlvsConstraints.clear();
68   theConstraint->myFeatureMap.clear();
69   theConstraint->myAttributeMap.clear();
70 }
71
72 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
73     Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
74 {
75   Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
76       SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
77       SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
78   Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
79   mySlvsConstraints.push_back(aNewID);
80   return aNewID;
81 }
82
83 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
84 {
85   std::list<AttributePtr> anAttrList =
86       theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
87   std::list<AttributePtr>::iterator anIter = anAttrList.begin();
88   std::vector<Slvs_hEntity> anEntities;
89   for (; anIter != anAttrList.end(); anIter++) {
90     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
91     if (!aRefAttr || aRefAttr->isObject() ||
92         myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end())
93       continue;
94     int aType;
95     Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr());
96     if (anEntityID == SLVS_E_UNKNOWN)
97       anEntityID = changeEntity(aRefAttr->attr(), aType);
98     anEntities.push_back(anEntityID);
99   }
100
101   Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
102   Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
103   std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
104   for (; anEntIter != anEntities.end(); anEntIter++)
105     aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
106   myExtraCoincidence[aNewConstr] = theConstraint;
107 }
108
109 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
110 {
111   cleanErrorMsg();
112   if (mySlvsConstraints.empty())
113     return true;
114   ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
115   int aPos = -1; // position of constraint in the list (-1 for base constraint)
116   std::map<Slvs_hConstraint, ConstraintPtr>::iterator anExtraIt;
117   if (aConstraint != myBaseConstraint) {
118     anExtraIt = myExtraCoincidence.begin();
119     for (aPos = 0; anExtraIt != myExtraCoincidence.end(); anExtraIt++, aPos++)
120       if (anExtraIt->second == aConstraint)
121         break;
122     if (aPos >= (int)myExtraCoincidence.size())
123       return false; // there is no constraint, which is specified to remove
124     else {
125       bool isEmpty = anExtraIt->first == SLVS_E_UNKNOWN;
126       myExtraCoincidence.erase(anExtraIt);
127       if (isEmpty)
128         return false;
129     }
130   }
131
132   bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
133   mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
134   if (aPos < 0 && !myExtraCoincidence.empty()) {
135     anExtraIt = myExtraCoincidence.begin();
136     // Remove invalid constraints
137     while (anExtraIt != myExtraCoincidence.end()) {
138       if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
139         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
140         if (aTempIt->first != SLVS_E_UNKNOWN) {
141           myStorage->removeConstraint(aTempIt->first);
142           std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
143           for (; anIt != mySlvsConstraints.end(); anIt++)
144             if (*anIt == aTempIt->first) {
145               mySlvsConstraints.erase(anIt);
146               break;
147             }
148         }
149         myExtraCoincidence.erase(aTempIt);
150         continue;
151       }
152       anExtraIt++;
153     }
154     // Find first non-extra conststraint
155     while (anExtraIt != myExtraCoincidence.end() && anExtraIt->first == SLVS_E_UNKNOWN)
156       anExtraIt++;
157     if (anExtraIt != myExtraCoincidence.end()) {
158       // Need to specify another base coincidence constraint
159       myBaseConstraint = anExtraIt->second;
160       myExtraCoincidence.erase(anExtraIt);
161       std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
162       Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
163       for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
164         Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
165         aConstr.ptA = aBase.ptA;
166         myStorage->updateConstraint(aConstr);
167       }
168     }
169   }
170   // Clear removed attributes
171   std::set<Slvs_hParam> aParamRemoved;
172   std::set<Slvs_hEntity> anEntRemoved;
173   std::set<Slvs_hConstraint> aConstrRemoved;
174   myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
175   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
176   while (anAttrIter != myAttributeMap.end()) {
177     if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
178       std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
179       myAttributeMap.erase(aTempIt);
180       continue;
181     }
182     anAttrIter++;
183   }
184
185   // Go through remaining extra coincidence and try to add or remove them
186   anExtraIt = myExtraCoincidence.begin();
187   while (anExtraIt != myExtraCoincidence.end()) {
188     if (anExtraIt->first == SLVS_E_UNKNOWN) {
189       if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
190         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
191         myExtraCoincidence.erase(aTempIt);
192         continue;
193       }
194       if (mySlvsConstraints.empty()) {
195         myBaseConstraint = anExtraIt->second;
196         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
197         myExtraCoincidence.erase(aTempIt);
198         process();
199         continue;
200       } else
201         addConstraint(anExtraIt->second);
202     }
203     anExtraIt++;
204   }
205   return mySlvsConstraints.empty();
206 }
207