1 #include <SketchSolver_ConstraintCoincidence.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Group.h>
7 void SketchSolver_ConstraintCoincidence::getAttributes(
9 std::vector<Slvs_hEntity>& theAttributes)
11 SketchSolver_Constraint::getAttributes(theValue, theAttributes);
12 if (!myErrorMsg.empty() || theAttributes[0] == SLVS_E_UNKNOWN)
15 if (theAttributes[1] != SLVS_E_UNKNOWN)
16 myType = SLVS_C_POINTS_COINCIDENT;
17 else if (theAttributes[2] != SLVS_E_UNKNOWN) {
18 // check the type of entity (line or circle)
19 Slvs_Entity anEnt = myStorage->getEntity(theAttributes[2]);
20 if (anEnt.type == SLVS_E_LINE_SEGMENT)
21 myType = SLVS_C_PT_ON_LINE;
22 else if (anEnt.type == SLVS_E_CIRCLE || anEnt.type == SLVS_E_ARC_OF_CIRCLE)
23 myType = SLVS_C_PT_ON_CIRCLE;
25 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
27 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
31 bool SketchSolver_ConstraintCoincidence::hasConstraint(ConstraintPtr theConstraint) const
33 if (myBaseConstraint == theConstraint)
35 return myExtraCoincidence.find(theConstraint) != myExtraCoincidence.end();
38 std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
40 std::list<ConstraintPtr> aConstraints;
41 aConstraints.push_back(myBaseConstraint);
42 std::map<ConstraintPtr, Slvs_hConstraint>::const_iterator anIt = myExtraCoincidence.begin();
43 for (; anIt != myExtraCoincidence.end(); anIt++)
44 aConstraints.push_back(anIt->first);
48 bool SketchSolver_ConstraintCoincidence::isCoincide(
49 std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
51 // Multi-coincidence allowed for two points only
52 if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT)
55 std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
56 for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
57 if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
62 void SketchSolver_ConstraintCoincidence::attach(
63 std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
66 // Remove constraints from theConstraint
67 std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
68 for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
69 theConstraint->myStorage->removeConstraint(*aCIter);
71 if (myStorage == theConstraint->myStorage) {
72 // Clean removed items
73 std::set<Slvs_hParam> aRemParams;
74 std::set<Slvs_hEntity> aRemEnts;
75 std::set<Slvs_hConstraint> aRemConstr;
76 theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
78 if (!aRemEnts.empty()) {
79 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
80 while (aFeatIt != theConstraint->myFeatureMap.end()) {
81 if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
83 std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
84 theConstraint->myFeatureMap.erase(aRemoveIt);
88 std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
89 while (anAttrIt != theConstraint->myAttributeMap.end()) {
90 if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
92 std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
93 theConstraint->myAttributeMap.erase(aRemoveIt);
101 addConstraint(theConstraint->myBaseConstraint);
102 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
103 theConstraint->myExtraCoincidence.begin();
104 for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
105 addConstraint(aConstrIter->first);
106 // Clear the lists to not remove the entities on destruction
107 theConstraint->mySlvsConstraints.clear();
108 theConstraint->myFeatureMap.clear();
109 theConstraint->myAttributeMap.clear();
112 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
113 Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
115 bool hasDuplicated = myStorage->hasDuplicatedConstraint();
116 Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
117 SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
118 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
119 Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
120 if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
121 // the duplicated constraint appears
122 myStorage->removeConstraint(aNewID);
123 return SLVS_E_UNKNOWN;
125 mySlvsConstraints.push_back(aNewID);
129 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
131 std::list<AttributePtr> anAttrList =
132 theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
133 std::list<AttributePtr>::iterator anIter = anAttrList.begin();
134 std::vector<Slvs_hEntity> anEntities;
135 for (; anIter != anAttrList.end(); anIter++) {
136 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
137 if (!aRefAttr || aRefAttr->isObject() ||
138 myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end())
141 Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr());
142 if (anEntityID == SLVS_E_UNKNOWN)
143 anEntityID = changeEntity(aRefAttr->attr(), aType);
144 anEntities.push_back(anEntityID);
145 myCoincidentPoints.insert(aRefAttr->attr());
148 Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
149 std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
150 if (mySlvsConstraints.empty()) {
151 aNewConstr = addConstraint(*anEntIter, *(anEntIter + 1));
154 Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
155 for (; anEntIter != anEntities.end(); anEntIter++)
156 aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
157 myExtraCoincidence[theConstraint] = aNewConstr;
160 void SketchSolver_ConstraintCoincidence::process()
162 SketchSolver_Constraint::process();
164 // Fill the list of coincident points
165 std::list<AttributePtr> anAttrList =
166 myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
167 std::list<AttributePtr>::iterator anIt = anAttrList.begin();
168 for (; anIt != anAttrList.end(); anIt++) {
169 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
170 if (!aRefAttr || aRefAttr->isObject())
172 myCoincidentPoints.insert(aRefAttr->attr());
176 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
179 if (mySlvsConstraints.empty())
181 ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
182 int aPos = -1; // position of constraint in the list (-1 for base constraint)
183 std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
184 if (aConstraint != myBaseConstraint) {
185 anExtraIt = myExtraCoincidence.find(aConstraint);
186 if (anExtraIt == myExtraCoincidence.end())
187 return false; // there is no constraint, which is specified to remove
189 bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
192 for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
193 if (mySlvsConstraints[aPos] == anExtraIt->second) {
199 myExtraCoincidence.erase(anExtraIt);
205 bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
206 mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
207 if (aPos < 0 && !myExtraCoincidence.empty()) {
208 anExtraIt = myExtraCoincidence.begin();
209 // Remove invalid constraints
210 while (anExtraIt != myExtraCoincidence.end()) {
211 if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
212 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
213 if (aTempIt->first != SLVS_E_UNKNOWN) {
214 myStorage->removeConstraint(aTempIt->second);
215 std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
216 for (; anIt != mySlvsConstraints.end(); anIt++)
217 if (*anIt == aTempIt->second) {
218 mySlvsConstraints.erase(anIt);
222 myExtraCoincidence.erase(aTempIt);
227 // Find first non-extra conststraint
228 anExtraIt = myExtraCoincidence.begin();
229 while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
231 if (anExtraIt != myExtraCoincidence.end()) {
232 // Need to specify another base coincidence constraint
233 myBaseConstraint = anExtraIt->first;
234 myExtraCoincidence.erase(anExtraIt);
235 if (mySlvsConstraints.empty()) {
236 std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
237 Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
238 for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
239 Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
240 aConstr.ptA = aBase.ptA;
241 myStorage->updateConstraint(aConstr);
246 // Clear removed attributes
247 std::set<Slvs_hParam> aParamRemoved;
248 std::set<Slvs_hEntity> anEntRemoved;
249 std::set<Slvs_hConstraint> aConstrRemoved;
250 myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
251 std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
252 while (anAttrIter != myAttributeMap.end()) {
253 if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
254 std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
255 myCoincidentPoints.erase(aTempIt->first);
256 myAttributeMap.erase(aTempIt);
262 // Go through remaining extra coincidence and try to add or remove them
263 anExtraIt = myExtraCoincidence.begin();
264 while (anExtraIt != myExtraCoincidence.end()) {
265 if (anExtraIt->first == SLVS_E_UNKNOWN) {
266 if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
267 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
268 myExtraCoincidence.erase(aTempIt);
271 if (mySlvsConstraints.empty()) {
272 myBaseConstraint = anExtraIt->first;
273 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
274 myExtraCoincidence.erase(aTempIt);
278 addConstraint(anExtraIt->first);
282 return mySlvsConstraints.empty();