Salome HOME
Sketcher: Remove obsolete interfaces. Code cleanup.
[modules/shaper.git] / src / SketchSolver / PlaneGCSSolver / PlaneGCSSolver_UpdateCoincidence.cpp
1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
2
3 // File:    PlaneGCSSolver_UpdateCoincidence.cpp
4 // Created: 17 Feb 2017
5 // Author:  Artem ZHIDKOV
6
7 #include <PlaneGCSSolver_UpdateCoincidence.h>
8 #include <PlaneGCSSolver_EdgeWrapper.h>
9 #include <PlaneGCSSolver_PointWrapper.h>
10 #include <SketchSolver_Constraint.h>
11
12 #include <SketchPlugin_ConstraintCoincidence.h>
13 #include <SketchPlugin_ConstraintCollinear.h>
14 #include <SketchPlugin_ConstraintMiddle.h>
15
16 void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver,
17                                               const std::string& theType)
18 {
19   if (theType == GROUP()) {
20     std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
21     // point-point coincidence is placed first
22     if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
23       for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
24         if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT)
25           break;
26     }
27     myObservers.insert(aPlaceToAdd, theObserver);
28   } else
29     myNext->attach(theObserver, theType);
30 }
31
32 void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
33 {
34   if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
35       theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() ||
36       theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
37     myCoincident.clear();
38     // notify listeners and stop procesing
39     std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
40     for (; anIt != myObservers.end(); ++anIt)
41       (*anIt)->notify(theFeature, this);
42   } else
43     myNext->update(theFeature);
44 }
45
46 static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences,
47                                     const EntityWrapperPtr& thePoint)
48 {
49   std::set<EntityWrapperPtr>::const_iterator anIt = theCoincidences.begin();
50   for (; anIt != theCoincidences.end(); ++anIt)
51     if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint)
52       return true;
53   return false;
54 }
55
56 bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
57     const EntityWrapperPtr& theEntity1,
58     const EntityWrapperPtr& theEntity2)
59 {
60   bool isAccepted = true;
61
62   std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
63   std::list<CoincidentEntities>::iterator
64       aFound[2] = {myCoincident.end(), myCoincident.end()};
65
66   for (; anIt != myCoincident.end(); ++anIt) {
67     if (anIt->isExist(theEntity1))
68       aFound[0] = anIt;
69     if (anIt->isExist(theEntity2))
70       aFound[1] = anIt;
71     if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end())
72       break;
73   }
74
75   if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
76     // new group of coincidence
77     myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2));
78   } else if (aFound[0] == aFound[1]) // same group => already coincident
79     isAccepted = false;
80   else {
81     if (aFound[0] == myCoincident.end())
82       isAccepted = aFound[1]->isNewCoincidence(theEntity2, theEntity1);
83     else if (aFound[1] == myCoincident.end())
84       isAccepted = aFound[0]->isNewCoincidence(theEntity1, theEntity2);
85     else { // merge two groups
86       isAccepted = aFound[0]->isNewCoincidence(theEntity1, *(aFound[1]), theEntity2);
87       myCoincident.erase(aFound[1]);
88     }
89   }
90
91   return isAccepted;
92 }
93
94 bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
95     const EntityWrapperPtr& thePoint,
96     const EntityWrapperPtr& theEntity)
97 {
98   std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
99   for (; anIt != myCoincident.end(); ++anIt)
100     if (anIt->isExist(thePoint))
101       break;
102
103   if (anIt == myCoincident.end())
104     return false;
105
106   if (anIt->isExist(theEntity))
107     return true;
108
109   if (theEntity->type() == ENTITY_LINE) {
110     std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(
111         std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity)->entity());
112     return anIt->isExist(aLine->p1) || anIt->isExist(aLine->p2);
113   }
114   return false;
115 }
116
117
118
119
120
121 PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
122     const EntityWrapperPtr& theEntity1,
123     const EntityWrapperPtr& theEntity2)
124 {
125   if (theEntity1->isExternal() && theEntity2->isExternal()) {
126     myExternalAndConnected[theEntity1] = std::set<EntityWrapperPtr>();
127     myExternalAndConnected[theEntity2] = std::set<EntityWrapperPtr>();
128   } else if (theEntity1->isExternal())
129     myExternalAndConnected[theEntity1].insert(theEntity2);
130   else if (theEntity2->isExternal())
131     myExternalAndConnected[theEntity2].insert(theEntity1);
132   else {
133     std::set<EntityWrapperPtr> aGroup;
134     aGroup.insert(theEntity1);
135     aGroup.insert(theEntity2);
136     myExternalAndConnected[EntityWrapperPtr()] = aGroup;
137   }
138 }
139
140 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::hasExternal() const
141 {
142   return myExternalAndConnected.size() != 1 ||
143          myExternalAndConnected.find(EntityWrapperPtr()) == myExternalAndConnected.end();
144 }
145
146 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
147     const EntityWrapperPtr& theEntity) const
148 {
149   std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
150       anIt = myExternalAndConnected.begin();
151   for (; anIt != myExternalAndConnected.end(); ++anIt)
152     if (anIt->first == theEntity ||
153         anIt->second.find(theEntity) != anIt->second.end())
154       return true;
155   return false;
156 }
157
158 static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
159 {
160   return thePoint1.x == thePoint2.x && thePoint1.y == thePoint2.y;
161 }
162
163 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
164     const GCS::Point& thePoint) const
165 {
166   std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
167       anIt = myExternalAndConnected.begin();
168   for (; anIt != myExternalAndConnected.end(); ++anIt) {
169     if (anIt->first && anIt->first->type() == ENTITY_POINT) {
170       const GCSPointPtr& aPoint =
171           std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->first)->point();
172       if (isEqual(*aPoint, thePoint))
173         return true;
174     }
175
176     std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
177     for (; anEntIt != anIt->second.end(); ++anEntIt)
178       if ((*anEntIt)->type() == ENTITY_POINT) {
179         const GCSPointPtr& aPoint =
180             std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anEntIt)->point();
181         if (isEqual(*aPoint, thePoint))
182           return true;
183       }
184   }
185   return false;
186 }
187
188 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
189     const EntityWrapperPtr& theEntityExist,
190     const EntityWrapperPtr& theOtherEntity)
191 {
192   if (theOtherEntity->isExternal()) {
193     if (hasExternal()) {
194       if (myExternalAndConnected.find(theOtherEntity) == myExternalAndConnected.end())
195         myExternalAndConnected[theOtherEntity] = std::set<EntityWrapperPtr>();
196       return false;
197     } else {
198       myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()];
199       myExternalAndConnected.erase(EntityWrapperPtr());
200       return true;
201     }
202   }
203
204   if (theEntityExist->isExternal()) {
205     myExternalAndConnected[theEntityExist].insert(theOtherEntity);
206     return true;
207   }
208
209   std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator
210       anIt = myExternalAndConnected.begin();
211   for (; anIt != myExternalAndConnected.end(); ++anIt)
212     if (anIt->second.find(theEntityExist) != anIt->second.end()) {
213       anIt->second.insert(theOtherEntity);
214       break;
215     }
216   return true;
217 }
218
219 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
220     const EntityWrapperPtr&   theEntityExist,
221     const CoincidentEntities& theOtherGroup,
222     const EntityWrapperPtr&   theEntityInOtherGroup)
223 {
224   bool hasExt[2] = {hasExternal(), theOtherGroup.hasExternal()};
225   if (hasExt[0] && hasExt[1]) {
226     myExternalAndConnected.insert(theOtherGroup.myExternalAndConnected.begin(),
227                                   theOtherGroup.myExternalAndConnected.end());
228     return false;
229   } else if (!hasExt[0] && !hasExt[1]) {
230     std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
231         aFound = theOtherGroup.myExternalAndConnected.find(EntityWrapperPtr());
232
233     myExternalAndConnected[EntityWrapperPtr()].insert(
234         aFound->second.begin(), aFound->second.end());
235     return true;
236   } else {
237     std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > aSource, aDest;
238     EntityWrapperPtr aTarget;
239     if (hasExt[0]) {
240       aDest = myExternalAndConnected;
241       aSource = theOtherGroup.myExternalAndConnected;
242       aTarget = theEntityExist;
243     } else {
244       aSource = myExternalAndConnected;
245       aDest = theOtherGroup.myExternalAndConnected;
246       aTarget = theEntityInOtherGroup;
247     }
248
249     std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
250         aFound = aSource.find(EntityWrapperPtr());
251
252     std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator anIt = aDest.begin();
253     for (; anIt != aDest.end(); ++anIt)
254       if (anIt->first == aTarget ||
255           anIt->second.find(aTarget) != anIt->second.end()) {
256         anIt->second.insert(aFound->second.begin(), aFound->second.end());
257         break;
258       }
259     return true;
260   }
261   // impossible case
262   return false;
263 }