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 std::set<AttributePtr>::const_iterator anAttrIter = theConstraint->myCoincidentPoints.begin();
52 for (; anAttrIter != theConstraint->myCoincidentPoints.end(); anAttrIter++)
53 if (myCoincidentPoints.find(*anAttrIter) != myCoincidentPoints.end())
58 void SketchSolver_ConstraintCoincidence::attach(
59 std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
62 // Remove constraints from theConstraint
63 std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
64 for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
65 theConstraint->myStorage->removeConstraint(*aCIter);
67 if (myStorage == theConstraint->myStorage) {
68 // Clean removed items
69 std::set<Slvs_hParam> aRemParams;
70 std::set<Slvs_hEntity> aRemEnts;
71 std::set<Slvs_hConstraint> aRemConstr;
72 theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
74 if (!aRemEnts.empty()) {
75 std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
76 while (aFeatIt != theConstraint->myFeatureMap.end()) {
77 if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
79 std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
80 theConstraint->myFeatureMap.erase(aRemoveIt);
84 std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
85 while (anAttrIt != theConstraint->myAttributeMap.end()) {
86 if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
88 std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
89 theConstraint->myAttributeMap.erase(aRemoveIt);
97 addConstraint(theConstraint->myBaseConstraint);
98 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
99 theConstraint->myExtraCoincidence.begin();
100 for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
101 addConstraint(aConstrIter->first);
102 // Clear the lists to not remove the entities on destruction
103 theConstraint->mySlvsConstraints.clear();
104 theConstraint->myFeatureMap.clear();
105 theConstraint->myAttributeMap.clear();
108 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
109 Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
111 if (thePoint1 == thePoint2)
112 return SLVS_E_UNKNOWN;
114 bool hasDuplicated = myStorage->hasDuplicatedConstraint();
115 Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
116 SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
117 SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
118 Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
119 if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
120 // the duplicated constraint appears
121 myStorage->removeConstraint(aNewID);
122 return SLVS_E_UNKNOWN;
124 mySlvsConstraints.push_back(aNewID);
128 Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
129 Slvs_hEntity thePoint, Slvs_hEntity theEntity)
131 // Check the point is not coincident with boundaries of the entity
132 Slvs_Entity anEnt = myStorage->getEntity(theEntity);
133 int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
134 for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
135 if (anEnt.point[aPos] == thePoint ||
136 myStorage->isCoincident(anEnt.point[aPos], thePoint))
137 return SLVS_E_UNKNOWN;
139 bool hasDuplicated = myStorage->hasDuplicatedConstraint();
140 Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
141 Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
142 SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
143 Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
144 aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
145 theEntity, SLVS_E_UNKNOWN);
146 Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
147 if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
148 // the duplicated constraint appears
149 myStorage->removeConstraint(aNewID);
150 return SLVS_E_UNKNOWN;
152 mySlvsConstraints.push_back(aNewID);
156 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
158 if (mySlvsConstraints.empty()) {
159 // This constraint is empty, rebuild it from scratch
160 myBaseConstraint = theConstraint;
165 std::list<AttributePtr> anAttrList =
166 theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
167 std::list<AttributePtr>::iterator anIter = anAttrList.begin();
168 std::vector<Slvs_hEntity> aPoints;
169 Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
171 for (; anIter != anAttrList.end(); anIter++) {
172 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
175 if (aRefAttr->isObject()) {
176 FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
177 std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound =
178 myFeatureMap.find(aFeature);
179 if (aFeatFound != myFeatureMap.end())
180 anEntity = aFeatFound->second;
182 anEntity = myGroup->getFeatureId(aFeature);
183 if (anEntity == SLVS_E_UNKNOWN)
184 anEntity = changeEntity(aFeature, anEntType);
186 myFeatureMap[aFeature] = anEntity;
189 Slvs_hEntity anEntID = SLVS_E_UNKNOWN;
190 std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
191 myAttributeMap.find(aRefAttr->attr());
192 if (anAttrFound != myAttributeMap.end())
193 anEntID = anAttrFound->second;
195 anEntID = myGroup->getAttributeId(aRefAttr->attr());
196 if (anEntID == SLVS_E_UNKNOWN)
197 anEntID = changeEntity(aRefAttr->attr(), anEntType);
199 myAttributeMap[aRefAttr->attr()] = anEntID;
201 aPoints.push_back(anEntID);
202 myCoincidentPoints.insert(aRefAttr->attr());
206 Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
207 if (anEntity != SLVS_E_UNKNOWN)
208 aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
209 else { // coincidence between two points
210 Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
211 std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
212 for (; aPtIter != aPoints.end(); aPtIter++) {
213 Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
214 if (aC != SLVS_E_UNKNOWN)
218 myExtraCoincidence[theConstraint] = aNewConstr;
221 void SketchSolver_ConstraintCoincidence::process()
223 SketchSolver_Constraint::process();
225 // Fill the list of coincident points
226 std::list<AttributePtr> anAttrList =
227 myBaseConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
228 std::list<AttributePtr>::iterator anIt = anAttrList.begin();
229 for (; anIt != anAttrList.end(); anIt++) {
230 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIt);
231 if (!aRefAttr || aRefAttr->isObject())
233 myCoincidentPoints.insert(aRefAttr->attr());
237 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
240 if (mySlvsConstraints.empty())
242 ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
243 int aPos = -1; // position of constraint in the list (-1 for base constraint)
244 std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
245 if (aConstraint != myBaseConstraint) {
246 anExtraIt = myExtraCoincidence.find(aConstraint);
247 if (anExtraIt == myExtraCoincidence.end())
248 return false; // there is no constraint, which is specified to remove
250 bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
253 for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
254 if (mySlvsConstraints[aPos] == anExtraIt->second) {
260 myExtraCoincidence.erase(anExtraIt);
266 bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
267 mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
268 if (aPos < 0 && !myExtraCoincidence.empty()) {
269 anExtraIt = myExtraCoincidence.begin();
270 // Remove invalid constraints
271 while (anExtraIt != myExtraCoincidence.end()) {
272 if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
273 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
274 if (aTempIt->first != SLVS_E_UNKNOWN) {
275 myStorage->removeConstraint(aTempIt->second);
276 std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
277 for (; anIt != mySlvsConstraints.end(); anIt++)
278 if (*anIt == aTempIt->second) {
279 mySlvsConstraints.erase(anIt);
283 myExtraCoincidence.erase(aTempIt);
288 // Find first non-extra conststraint
289 anExtraIt = myExtraCoincidence.begin();
290 while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
292 if (anExtraIt != myExtraCoincidence.end()) {
293 // Need to specify another base coincidence constraint
294 myBaseConstraint = anExtraIt->first;
295 myExtraCoincidence.erase(anExtraIt);
296 if (mySlvsConstraints.empty()) {
297 std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
298 Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
299 for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
300 Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
301 aConstr.ptA = aBase.ptA;
302 myStorage->updateConstraint(aConstr);
307 // Clear removed attributes
308 std::set<Slvs_hParam> aParamRemoved;
309 std::set<Slvs_hEntity> anEntRemoved;
310 std::set<Slvs_hConstraint> aConstrRemoved;
311 myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
312 std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
313 while (anAttrIter != myAttributeMap.end()) {
314 if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
315 std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
316 myCoincidentPoints.erase(aTempIt->first);
317 myAttributeMap.erase(aTempIt);
323 // Go through remaining extra coincidence and try to add or remove them
324 anExtraIt = myExtraCoincidence.begin();
325 while (anExtraIt != myExtraCoincidence.end()) {
326 if (anExtraIt->first == SLVS_E_UNKNOWN) {
327 if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
328 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
329 myExtraCoincidence.erase(aTempIt);
332 if (mySlvsConstraints.empty()) {
333 myBaseConstraint = anExtraIt->first;
334 std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
335 myExtraCoincidence.erase(aTempIt);
339 addConstraint(anExtraIt->first);
343 return mySlvsConstraints.empty();