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 std::map<Slvs_hConstraint, ConstraintPtr>::const_iterator anIt = myExtraCoincidence.begin();
36 for (; anIt != myExtraCoincidence.end(); anIt++)
37 if (anIt->second == theConstraint)
42 std::list<ConstraintPtr> SketchSolver_ConstraintCoincidence::constraints() const
44 std::list<ConstraintPtr> aConstraints;
45 aConstraints.push_back(myBaseConstraint);
46 std::map<Slvs_hConstraint, ConstraintPtr>::const_iterator anIt = myExtraCoincidence.begin();
47 for (; anIt != myExtraCoincidence.end(); anIt++)
48 aConstraints.push_back(anIt->second);
52 bool SketchSolver_ConstraintCoincidence::isCoincide(
53 std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
55 // Multi-coincidence allowed for two points only
56 if (getType() != theConstraint->getType() || getType() != SLVS_C_POINTS_COINCIDENT)
59 std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
60 for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
61 if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
66 void SketchSolver_ConstraintCoincidence::attach(
67 std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
70 // Remove constraints from theConstraint
71 std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
72 for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
73 theConstraint->myStorage->removeConstraint(*aCIter);
75 if (myStorage == theConstraint->myStorage) {
76 // Clean removed items
77 std::set<Slvs_hParam> aRemParams;
78 std::set<Slvs_hEntity> aRemEnts;
79 std::set<Slvs_hConstraint> aRemConstr;
80 theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
84 addConstraint(theConstraint->myBaseConstraint);
85 std::map<Slvs_hConstraint, ConstraintPtr>::iterator aConstrIter =
86 theConstraint->myExtraCoincidence.begin();
87 for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
88 addConstraint(aConstrIter->second);
89 // Clear the lists to not remove the entities on destruction
90 theConstraint->mySlvsConstraints.clear();
91 theConstraint->myFeatureMap.clear();
92 theConstraint->myAttributeMap.clear();
95 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
96 Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
98 bool hasDuplicated = myStorage->hasDuplicatedConstraint();
99 Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
100 SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
101 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
102 Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
103 if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
104 // the duplicated constraint appears
105 myStorage->removeConstraint(aNewID);
106 return SLVS_E_UNKNOWN;
108 mySlvsConstraints.push_back(aNewID);
112 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
114 std::list<AttributePtr> anAttrList =
115 theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
116 std::list<AttributePtr>::iterator anIter = anAttrList.begin();
117 std::vector<Slvs_hEntity> anEntities;
118 for (; anIter != anAttrList.end(); anIter++) {
119 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
120 if (!aRefAttr || aRefAttr->isObject() ||
121 myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end())
124 Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr());
125 if (anEntityID == SLVS_E_UNKNOWN)
126 anEntityID = changeEntity(aRefAttr->attr(), aType);
127 anEntities.push_back(anEntityID);
128 myCoincidentPoints.insert(aRefAttr->attr());
131 Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
132 std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
133 if (mySlvsConstraints.empty()) {
134 aNewConstr = addConstraint(*anEntIter, *(anEntIter + 1));
137 Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
138 for (; anEntIter != anEntities.end(); anEntIter++)
139 aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
140 myExtraCoincidence[aNewConstr] = theConstraint;
143 void SketchSolver_ConstraintCoincidence::process()
145 SketchSolver_Constraint::process();
147 // Fill the list of coincident points
148 std::list<AttributePtr> anAttrList =
149 myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
150 std::list<AttributePtr>::iterator anIt = anAttrList.begin();
151 for (; anIt != anAttrList.end(); anIt++) {
152 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
153 if (!aRefAttr || aRefAttr->isObject())
155 myCoincidentPoints.insert(aRefAttr->attr());
159 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
162 if (mySlvsConstraints.empty())
164 ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
165 int aPos = -1; // position of constraint in the list (-1 for base constraint)
166 std::map<Slvs_hConstraint, ConstraintPtr>::iterator anExtraIt;
167 if (aConstraint != myBaseConstraint) {
168 anExtraIt = myExtraCoincidence.begin();
169 for (aPos = 0; anExtraIt != myExtraCoincidence.end(); anExtraIt++, aPos++)
170 if (anExtraIt->second == aConstraint)
172 if (aPos >= (int)myExtraCoincidence.size())
173 return false; // there is no constraint, which is specified to remove
175 bool isEmpty = anExtraIt->first == SLVS_E_UNKNOWN;
177 for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
178 if (mySlvsConstraints[aPos] == anExtraIt->first)
182 myExtraCoincidence.erase(anExtraIt);
188 bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
189 mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
190 if (aPos < 0 && !myExtraCoincidence.empty()) {
191 anExtraIt = myExtraCoincidence.begin();
192 // Remove invalid constraints
193 while (anExtraIt != myExtraCoincidence.end()) {
194 if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
195 std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
196 if (aTempIt->first != SLVS_E_UNKNOWN) {
197 myStorage->removeConstraint(aTempIt->first);
198 std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
199 for (; anIt != mySlvsConstraints.end(); anIt++)
200 if (*anIt == aTempIt->first) {
201 mySlvsConstraints.erase(anIt);
205 myExtraCoincidence.erase(aTempIt);
210 // Find first non-extra conststraint
211 anExtraIt = myExtraCoincidence.begin();
212 while (anExtraIt != myExtraCoincidence.end() && anExtraIt->first == SLVS_E_UNKNOWN)
214 if (anExtraIt != myExtraCoincidence.end()) {
215 // Need to specify another base coincidence constraint
216 myBaseConstraint = anExtraIt->second;
217 myExtraCoincidence.erase(anExtraIt);
218 if (mySlvsConstraints.empty()) {
219 std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
220 Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
221 for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
222 Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
223 aConstr.ptA = aBase.ptA;
224 myStorage->updateConstraint(aConstr);
229 // Clear removed attributes
230 std::set<Slvs_hParam> aParamRemoved;
231 std::set<Slvs_hEntity> anEntRemoved;
232 std::set<Slvs_hConstraint> aConstrRemoved;
233 myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
234 std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
235 while (anAttrIter != myAttributeMap.end()) {
236 if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
237 std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
238 myCoincidentPoints.erase(aTempIt->first);
239 myAttributeMap.erase(aTempIt);
245 // Go through remaining extra coincidence and try to add or remove them
246 anExtraIt = myExtraCoincidence.begin();
247 while (anExtraIt != myExtraCoincidence.end()) {
248 if (anExtraIt->first == SLVS_E_UNKNOWN) {
249 if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
250 std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
251 myExtraCoincidence.erase(aTempIt);
254 if (mySlvsConstraints.empty()) {
255 myBaseConstraint = anExtraIt->second;
256 std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
257 myExtraCoincidence.erase(aTempIt);
261 addConstraint(anExtraIt->second);
265 return mySlvsConstraints.empty();