Salome HOME
Merge branch 'Dev_1.1.0' of newgeom:newgeom.git into Dev_1.1.0
[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   Slvs_Constraint aNewConstraint = Slvs_MakeConstraint(SLVS_E_UNKNOWN, myGroup->getId(),
72       SLVS_C_POINTS_COINCIDENT, myGroup->getWorkplaneId(), 0.0, thePoint1, thePoint2, 
73       SLVS_E_UNKNOWN, SLVS_E_UNKNOWN);
74   Slvs_hConstraint aNewID = myStorage->addConstraint(aNewConstraint);
75   mySlvsConstraints.push_back(aNewID);
76   return aNewID;
77 }
78
79 void SketchSolver_ConstraintCoincidence::addConstraint(ConstraintPtr theConstraint)
80 {
81   std::list<AttributePtr> anAttrList =
82       theConstraint->data()->attributes(ModelAPI_AttributeRefAttr::typeId());
83   std::list<AttributePtr>::iterator anIter = anAttrList.begin();
84   std::vector<Slvs_hEntity> anEntities;
85   for (; anIter != anAttrList.end(); anIter++) {
86     AttributeRefAttrPtr aRefAttr = std::dynamic_pointer_cast<ModelAPI_AttributeRefAttr>(*anIter);
87     if (!aRefAttr || aRefAttr->isObject() ||
88         myAttributeMap.find(aRefAttr->attr()) != myAttributeMap.end())
89       continue;
90     int aType;
91     Slvs_hEntity anEntityID = myGroup->getAttributeId(aRefAttr->attr());
92     if (anEntityID == SLVS_E_UNKNOWN)
93       anEntityID = changeEntity(aRefAttr->attr(), aType);
94     anEntities.push_back(anEntityID);
95     myCoincidentPoints.insert(aRefAttr->attr());
96   }
97
98   Slvs_Constraint aBaseCoincidence = myStorage->getConstraint(mySlvsConstraints.front());
99   Slvs_hConstraint aNewConstr = SLVS_E_UNKNOWN;
100   std::vector<Slvs_hEntity>::iterator anEntIter = anEntities.begin();
101   for (; anEntIter != anEntities.end(); anEntIter++)
102     aNewConstr = addConstraint(aBaseCoincidence.ptA, *anEntIter);
103   myExtraCoincidence[aNewConstr] = theConstraint;
104 }
105
106 bool SketchSolver_ConstraintCoincidence::remove(ConstraintPtr theConstraint)
107 {
108   cleanErrorMsg();
109   if (mySlvsConstraints.empty())
110     return true;
111   ConstraintPtr aConstraint = theConstraint ? theConstraint : myBaseConstraint;
112   int aPos = -1; // position of constraint in the list (-1 for base constraint)
113   std::map<Slvs_hConstraint, ConstraintPtr>::iterator anExtraIt;
114   if (aConstraint != myBaseConstraint) {
115     anExtraIt = myExtraCoincidence.begin();
116     for (aPos = 0; anExtraIt != myExtraCoincidence.end(); anExtraIt++, aPos++)
117       if (anExtraIt->second == aConstraint)
118         break;
119     if (aPos >= (int)myExtraCoincidence.size())
120       return false; // there is no constraint, which is specified to remove
121     else {
122       bool isEmpty = anExtraIt->first == SLVS_E_UNKNOWN;
123       myExtraCoincidence.erase(anExtraIt);
124       if (isEmpty)
125         return false;
126     }
127   }
128
129   bool isFullyRemoved = myStorage->removeConstraint(mySlvsConstraints[aPos+1]);
130   mySlvsConstraints.erase(mySlvsConstraints.begin() + (1+aPos));
131   if (aPos < 0 && !myExtraCoincidence.empty()) {
132     anExtraIt = myExtraCoincidence.begin();
133     // Remove invalid constraints
134     while (anExtraIt != myExtraCoincidence.end()) {
135       if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
136         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
137         if (aTempIt->first != SLVS_E_UNKNOWN) {
138           myStorage->removeConstraint(aTempIt->first);
139           std::vector<Slvs_hConstraint>::iterator anIt = mySlvsConstraints.begin();
140           for (; anIt != mySlvsConstraints.end(); anIt++)
141             if (*anIt == aTempIt->first) {
142               mySlvsConstraints.erase(anIt);
143               break;
144             }
145         }
146         myExtraCoincidence.erase(aTempIt);
147         continue;
148       }
149       anExtraIt++;
150     }
151     // Find first non-extra conststraint
152     while (anExtraIt != myExtraCoincidence.end() && anExtraIt->first == SLVS_E_UNKNOWN)
153       anExtraIt++;
154     if (anExtraIt != myExtraCoincidence.end()) {
155       // Need to specify another base coincidence constraint
156       myBaseConstraint = anExtraIt->second;
157       myExtraCoincidence.erase(anExtraIt);
158       std::vector<Slvs_hConstraint>::iterator aCIter = mySlvsConstraints.begin();
159       Slvs_Constraint aBase = myStorage->getConstraint(*aCIter);
160       for (++aCIter; aCIter != mySlvsConstraints.end(); aCIter++) {
161         Slvs_Constraint aConstr = myStorage->getConstraint(*aCIter);
162         aConstr.ptA = aBase.ptA;
163         myStorage->updateConstraint(aConstr);
164       }
165     }
166   }
167   // Clear removed attributes
168   std::set<Slvs_hParam> aParamRemoved;
169   std::set<Slvs_hEntity> anEntRemoved;
170   std::set<Slvs_hConstraint> aConstrRemoved;
171   myStorage->getRemoved(aParamRemoved, anEntRemoved, aConstrRemoved);
172   std::map<AttributePtr, Slvs_hEntity>::iterator anAttrIter = myAttributeMap.begin();
173   while (anAttrIter != myAttributeMap.end()) {
174     if (anEntRemoved.find(anAttrIter->second) != anEntRemoved.end()) {
175       std::map<AttributePtr, Slvs_hEntity>::iterator aTempIt = anAttrIter++;
176       myCoincidentPoints.erase(aTempIt->first);
177       myAttributeMap.erase(aTempIt);
178       continue;
179     }
180     anAttrIter++;
181   }
182
183   // Go through remaining extra coincidence and try to add or remove them
184   anExtraIt = myExtraCoincidence.begin();
185   while (anExtraIt != myExtraCoincidence.end()) {
186     if (anExtraIt->first == SLVS_E_UNKNOWN) {
187       if (!anExtraIt->second->data() || !anExtraIt->second->data()->isValid()) {
188         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
189         myExtraCoincidence.erase(aTempIt);
190         continue;
191       }
192       if (mySlvsConstraints.empty()) {
193         myBaseConstraint = anExtraIt->second;
194         std::map<Slvs_hConstraint, ConstraintPtr>::iterator aTempIt = anExtraIt++;
195         myExtraCoincidence.erase(aTempIt);
196         process();
197         continue;
198       } else
199         addConstraint(anExtraIt->second);
200     }
201     anExtraIt++;
202   }
203   return mySlvsConstraints.empty();
204 }
205