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