1 #include <SketchSolver_ConstraintCoincidence.h>
2 #include <SketchSolver_Error.h>
3 #include <SketchSolver_Manager.h>
5 ////#include <SketchPlugin_Point.h>
6 ////#include <GeomDataAPI_Point2D.h>
10 void SketchSolver_ConstraintCoincidence::getAttributes(
12 std::vector<EntityWrapperPtr>& theAttributes)
14 SketchSolver_Constraint::getAttributes(theValue, theAttributes);
15 if (!myErrorMsg.empty() || !theAttributes[0]) {
16 theAttributes.clear();
20 if (theAttributes[1]) {
21 myType = CONSTRAINT_PT_PT_COINCIDENT;
22 // Set the slave (second) point the same as master (first) point.
23 // This will allow to skip adding point-point coincidence to the set of constraints
24 // and give us speed-up in solving the set of equations
25 myStorage->addCoincidentPoints(theAttributes[0], theAttributes[1]);
27 else if (theAttributes[2]) {
28 // check the type of entity (line or circle)
29 SketchSolver_EntityType anEntType = theAttributes[2]->type();
30 if (anEntType == ENTITY_LINE)
31 myType = CONSTRAINT_PT_ON_LINE;
32 else if (anEntType == ENTITY_CIRCLE || anEntType == ENTITY_ARC)
33 myType = CONSTRAINT_PT_ON_CIRCLE;
35 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
37 myErrorMsg = SketchSolver_Error::INCORRECT_ATTRIBUTE();
41 static bool isBase(const std::list<ConstraintWrapperPtr>& theConstraints, AttributePtr theAttribute)
43 AttributePtr anAttribute = theAttribute;
45 AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(theAttribute);
47 if (aRefAttr->isObject())
48 aFeature = ModelAPI_Feature::feature(aRefAttr->object());
50 anAttribute = aRefAttr->attr();
53 std::list<ConstraintWrapperPtr>::const_iterator aCIt = theConstraints.begin();
54 for (; aCIt != theConstraints.end(); ++aCIt) {
55 std::list<EntityWrapperPtr> aSubs = (*aCIt)->entities();
56 std::list<EntityWrapperPtr>::const_iterator aSIt = aSubs.begin();
57 for (; aSIt != aSubs.end(); ++aSIt)
58 if ((aFeature && (*aSIt)->isBase(aFeature)) ||
59 (!aFeature && (*aSIt)->isBase(anAttribute)))
65 ////bool SketchSolver_ConstraintCoincidence::isCoincide(
66 //// std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint) const
68 //// std::list<ConstraintPtr>::const_iterator anOtherCIt = theConstraint->myConstraints.begin();
69 //// for (; anOtherCIt != theConstraint->myConstraints.end(); ++anOtherCIt) {
70 //// std::list<ConstraintPtr>::const_iterator aCIt = myConstraints.begin();
71 //// for (; aCIt != myConstraints.end(); ++aCIt) {
72 //// std::list<ConstraintWrapperPtr> aWrappers = myStorage->constraint(*aCIt);
73 //// if (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_A())) ||
74 //// (isBase(aWrappers, (*anOtherCIt)->attribute(SketchPlugin_Constraint::ENTITY_B()))))
81 ////void SketchSolver_ConstraintCoincidence::attach(
82 //// std::shared_ptr<SketchSolver_ConstraintCoincidence> theConstraint)
85 //// ConstraintWrapperPtr aFirstConstraint = myStorage->constraint(myConstraints.front()).front();
86 //// EntityWrapperPtr aMasterPoint = aFirstConstraint->entities().front();
88 //// // Set points from theConstraint equal to master point
89 //// const std::list<ConstraintPtr>& anOtherConstraints = theConstraint->myConstraints;
90 //// std::list<ConstraintPtr>::const_iterator anOtherCIt = anOtherConstraints.begin();
91 //// bool isFirstUpd = false;
92 //// for (; anOtherCIt != anOtherConstraints.end(); ++anOtherCIt) {
93 //// std::list<ConstraintWrapperPtr> aSolverConstraints = myStorage->constraint(*anOtherCIt);
94 //// std::list<ConstraintWrapperPtr>::iterator aSCIt = aSolverConstraints.begin();
95 //// // First point in each constraint is the same (master point of theConstraint),
96 //// // it should be updated only once.
97 //// if (!isFirstUpd) {
98 //// EntityWrapperPtr anOtherMasterPoint = (*aSCIt)->entities().front();
99 //// myStorage->addCoincidentPoints(aMasterPoint, anOtherMasterPoint);
100 //// isFirstUpd = true;
102 //// // Update all slave points
103 //// for (; aSCIt != aSolverConstraints.end(); ++aSCIt) {
104 //// std::list<EntityWrapperPtr> aSubs = (*aSCIt)->entities();
105 //// std::list<EntityWrapperPtr>::iterator aSubIt = aSubs.begin();
106 //// for (++aSubIt; aSubIt != aSubs.end(); ++aSubIt)
107 //// myStorage->addCoincidentPoints(aMasterPoint, *aSubIt);
109 //// // add constraint to myConstraints
110 //// myConstraints.push_back(*anOtherCIt);
113 //// // Remove constraints from theConstraint
114 //// std::vector<Slvs_hConstraint>::iterator aCIter = theConstraint->mySlvsConstraints.begin();
115 //// for (; aCIter != theConstraint->mySlvsConstraints.end(); aCIter++)
116 //// theConstraint->myStorage->removeConstraint(*aCIter);
118 //// if (myStorage == theConstraint->myStorage) {
119 //// // Clean removed items
120 //// std::set<Slvs_hParam> aRemParams;
121 //// std::set<Slvs_hEntity> aRemEnts;
122 //// std::set<Slvs_hConstraint> aRemConstr;
123 //// theConstraint->myStorage->getRemoved(aRemParams, aRemEnts, aRemConstr);
125 //// if (!aRemEnts.empty()) {
126 //// std::map<FeaturePtr, Slvs_hEntity>::iterator aFeatIt = theConstraint->myFeatureMap.begin();
127 //// while (aFeatIt != theConstraint->myFeatureMap.end()) {
128 //// if (aRemEnts.find(aFeatIt->second) != aRemEnts.end()) {
129 //// // remove feature
130 //// std::map<FeaturePtr, Slvs_hEntity>::iterator aRemoveIt = aFeatIt++;
131 //// theConstraint->myFeatureMap.erase(aRemoveIt);
135 //// std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIt = theConstraint->myAttributeMap.begin();
136 //// while (anAttrIt != theConstraint->myAttributeMap.end()) {
137 //// if (aRemEnts.find(anAttrIt->second) != aRemEnts.end()) {
138 //// // remove attribute
139 //// std::map<AttributePtr, Slvs_hEntity>::iterator aRemoveIt = anAttrIt++;
140 //// theConstraint->myAttributeMap.erase(aRemoveIt);
148 //// addConstraint(theConstraint->myBaseConstraint);
149 //// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aConstrIter =
150 //// theConstraint->myExtraCoincidence.begin();
151 //// for (; aConstrIter != theConstraint->myExtraCoincidence.end(); aConstrIter++)
152 //// addConstraint(aConstrIter->first);
153 //// // Clear the lists to not remove the entities on destruction
154 //// theConstraint->mySlvsConstraints.clear();
155 //// theConstraint->myFeatureMap.clear();
156 //// theConstraint->myAttributeMap.clear();
159 ////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addConstraint(
160 //// Slvs_hEntity thePoint1, Slvs_hEntity thePoint2)
162 //// if (thePoint1 == thePoint2)
163 //// return SLVS_E_UNKNOWN;
165 //// bool hasDuplicated = myStorage->hasDuplicatedConstraint();
166 //// Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
167 //// SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2,
168 //// SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
169 //// Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
170 //// if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
171 //// // the duplicated constraint appears
172 //// myStorage->removeConstraint(aNewID);
173 //// return SLVS_E_UNKNOWN;
175 //// mySlvsConstraints.push_back(aNewID);
179 ////Slvs_hConstraint SketchSolver_ConstraintCoincidence::addPointOnEntity(
180 //// Slvs_hEntity thePoint, Slvs_hEntity theEntity)
182 //// // Check the point is not coincident with boundaries of the entity
183 //// Slvs_Entity anEnt = myStorage->getEntity(theEntity);
184 //// int aPos = anEnt.type == SLVS_E_LINE_SEGMENT ? 0 : 1;
185 //// for (; anEnt.point[aPos] != SLVS_E_UNKNOWN; aPos++)
186 //// if (anEnt.point[aPos] == thePoint ||
187 //// myStorage->isCoincident(anEnt.point[aPos], thePoint))
188 //// return SLVS_E_UNKNOWN;
190 //// bool hasDuplicated = myStorage->hasDuplicatedConstraint();
191 //// Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
192 //// Slvs_hConstraint aType = anEnt.type == SLVS_E_LINE_SEGMENT ?
193 //// SLVS_C_PT_ON_LINE : SLVS_C_PT_ON_CIRCLE;
194 //// Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
195 //// aType, myGroup->getWorkplaneId(), 0.0, aBaseCoincidence.ptA, SLVS_E_UNKNOWN,
196 //// theEntity, SLVS_E_UNKNOWN);
197 //// Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
198 //// if (!hasDuplicated && myStorage->hasDuplicatedConstraint()) {
199 //// // the duplicated constraint appears
200 //// myStorage->removeConstraint(aNewID);
201 //// return SLVS_E_UNKNOWN;
203 //// mySlvsConstraints.push_back(aNewID);
207 ////void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
209 //// if (mySlvsConstraints.empty()) {
210 //// // This constraint is empty, rebuild it from scratch
211 //// myBaseConstraint = theConstraint;
216 //// std::list<AttributePtr> anAttrList =
217 //// theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
218 //// std::list<AttributePtr>::iterator anIter = anAttrList.begin();
219 //// std::vector<Slvs_hEntity> aPoints;
220 //// Slvs_hEntity anEntity = SLVS_E_UNKNOWN;
222 //// for (; anIter != anAttrList.end(); anIter++) {
223 //// Slvs_hEntity aPointID = SLVS_E_UNKNOWN;
224 //// AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
228 //// AttributePtr aPointAttr;
229 //// if (aRefAttr->isObject()) {
230 //// FeaturePtr aFeature = ModelAPI_Feature::feature(aRefAttr->object());
231 //// std::map<FeaturePtr, Slvs_hEntity>::const_iterator aFeatFound =
232 //// myFeatureMap.find(aFeature);
233 //// if (aFeatFound != myFeatureMap.end())
234 //// anEntity = aFeatFound->second;
236 //// anEntity = myGroup->getFeatureId(aFeature);
237 //// if (anEntity == SLVS_E_UNKNOWN)
238 //// anEntity = changeEntity(aFeature, anEntType);
240 //// myFeatureMap[aFeature] = anEntity;
241 //// // Obtain relations between attributes of the feature and SolveSpace entities
242 //// std::list<AttributePtr> anAttrList =
243 //// aFeature->data()->attributes(GeomDataAPI_Point2D::typeId());
244 //// std::list<AttributePtr>::iterator anIt = anAttrList.begin();
245 //// for (; anIt != anAttrList.end(); ++anIt) {
246 //// Slvs_hEntity anAttrID = myGroup->getAttributeId(*anIt);
247 //// if (anAttrID != SLVS_E_UNKNOWN)
248 //// myAttributeMap[*anIt] = anAttrID;
252 //// // If the feature is a point, add it to the list of coincident points
253 //// if (aFeature->getKind() == SketchPlugin_Point::ID()) {
254 //// aPointID = anEntity;
255 //// anEntity = SLVS_E_UNKNOWN;
256 //// aPointAttr = aFeature->attribute(SketchPlugin_Point::COORD_ID());
259 //// aPointAttr = aRefAttr->attr();
260 //// std::map<AttributePtr, Slvs_hEntity>::const_iterator anAttrFound =
261 //// myAttributeMap.find(aPointAttr);
262 //// if (anAttrFound != myAttributeMap.end())
263 //// aPointID = anAttrFound->second;
265 //// aPointID = myGroup->getAttributeId(aPointAttr);
266 //// if (aPointID == SLVS_E_UNKNOWN)
267 //// aPointID = changeEntity(aPointAttr, anEntType);
271 //// if (aPointAttr) { // the point is found
272 //// aPoints.push_back(aPointID);
273 //// myCoincidentPoints.insert(aPointAttr);
274 //// myAttributeMap[aPointAttr] = aPointID;
278 //// Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
279 //// if (anEntity != SLVS_E_UNKNOWN)
280 //// aNewConstr = addPointOnEntity(aPoints.front(), anEntity);
281 //// else { // coincidence between two points
282 //// Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
283 //// std::vector<Slvs_hEntity>::const_iterator aPtIter = aPoints.begin();
284 //// for (; aPtIter != aPoints.end(); aPtIter++) {
285 //// Slvs_hConstraint aC = addConstraint(aBaseCoincidence.ptA, *aPtIter);
286 //// if (aC != SLVS_E_UNKNOWN)
287 //// aNewConstr = aC;
290 //// myExtraCoincidence[theConstraint] = aNewConstr;
293 ////bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
295 //// cleanErrorMsg();
296 //// if (mySlvsConstraints.empty())
298 //// ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
299 //// int aPos = -1; // position of constraint in the list (-1 for base constraint)
300 //// std::map<ConstraintPtr, Slvs_hConstraint>::iterator anExtraIt;
301 //// if (aConstraint != myBaseConstraint) {
302 //// anExtraIt = myExtraCoincidence.find(aConstraint);
303 //// if (anExtraIt == myExtraCoincidence.end())
304 //// return false; // there is no constraint, which is specified to remove
306 //// bool isEmpty = anExtraIt->second == SLVS_E_UNKNOWN;
309 //// for (aPos = 0; aPos < (int)mySlvsConstraints.size(); aPos++)
310 //// if (mySlvsConstraints[aPos] == anExtraIt->second) {
311 //// isEmpty = false;
316 //// myExtraCoincidence.erase(anExtraIt);
322 //// bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
323 //// mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
324 //// if (aPos < 0 && !myExtraCoincidence.empty()) {
325 //// anExtraIt = myExtraCoincidence.begin();
326 //// // Remove invalid constraints
327 //// while (anExtraIt != myExtraCoincidence.end()) {
328 //// if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
329 //// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
330 //// if (aTempIt->first != SLVS_E_UNKNOWN) {
331 //// myStorage->removeConstraint(aTempIt->second);
332 //// std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
333 //// for (; anIt != mySlvsConstraints.end(); anIt++)
334 //// if (*anIt == aTempIt->second) {
335 //// mySlvsConstraints.erase(anIt);
339 //// myExtraCoincidence.erase(aTempIt);
344 //// // Find first non-extra conststraint
345 //// anExtraIt = myExtraCoincidence.begin();
346 //// while (anExtraIt != myExtraCoincidence.end() && anExtraIt->second == SLVS_E_UNKNOWN)
348 //// if (anExtraIt != myExtraCoincidence.end()) {
349 //// // Need to specify another base coincidence constraint
350 //// myBaseConstraint = anExtraIt->first;
351 //// myExtraCoincidence.erase(anExtraIt);
352 //// if (mySlvsConstraints.empty()) {
353 //// std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
354 //// Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
355 //// for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
356 //// Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
357 //// aConstr.ptA = aBase.ptA;
358 //// myStorage->updateConstraint(aConstr);
363 //// // Clear removed attributes
364 //// std::set<Slvs_hParam> aParamRemoved;
365 //// std::set<Slvs_hEntity> anEntRemoved;
366 //// std::set<Slvs_hConstraint> aConstrRemoved;
367 //// myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
368 //// std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
369 //// while (anAttrIter != myAttributeMap.end()) {
370 //// if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
371 //// std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
372 //// myCoincidentPoints.erase(aTempIt->first);
373 //// myAttributeMap.erase(aTempIt);
379 //// // Go through remaining extra coincidence and try to add or remove them
380 //// anExtraIt = myExtraCoincidence.begin();
381 //// while (anExtraIt != myExtraCoincidence.end()) {
382 //// if (anExtraIt->first == SLVS_E_UNKNOWN) {
383 //// if (!anExtraIt->first->data() || !anExtraIt->first->data()->isValid()) {
384 //// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
385 //// myExtraCoincidence.erase(aTempIt);
388 //// if (mySlvsConstraints.empty()) {
389 //// myBaseConstraint = anExtraIt->first;
390 //// std::map<ConstraintPtr, Slvs_hConstraint>::iterator aTempIt = anExtraIt++;
391 //// myExtraCoincidence.erase(aTempIt);
395 //// addConstraint(anExtraIt->first);
399 //// return mySlvsConstraints.empty();