1 // Copyright (C) 2014-20xx CEA/DEN, EDF R&D
3 // File: PlaneGCSSolver_UpdateCoincidence.cpp
4 // Created: 17 Feb 2017
5 // Author: Artem ZHIDKOV
7 #include <PlaneGCSSolver_UpdateCoincidence.h>
8 #include <PlaneGCSSolver_EdgeWrapper.h>
9 #include <PlaneGCSSolver_PointWrapper.h>
10 #include <SketchSolver_Constraint.h>
12 #include <SketchPlugin_ConstraintCoincidence.h>
13 #include <SketchPlugin_ConstraintCollinear.h>
14 #include <SketchPlugin_ConstraintMiddle.h>
16 void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver,
17 const std::string& theType)
19 if (theType == GROUP()) {
20 std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
21 // point-point coincidence is placed first,
22 // other constraints are sorted by their type
23 for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
24 if ((*aPlaceToAdd)->getType() > theObserver->getType())
26 myObservers.insert(aPlaceToAdd, theObserver);
28 myNext->attach(theObserver, theType);
31 void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
33 if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
34 theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() ||
35 theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
37 // notify listeners and stop procesing
38 std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
39 for (; anIt != myObservers.end(); ++anIt)
40 (*anIt)->notify(theFeature, this);
42 myNext->update(theFeature);
45 static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences,
46 const EntityWrapperPtr& thePoint)
48 std::set<EntityWrapperPtr>::const_iterator anIt = theCoincidences.begin();
49 for (; anIt != theCoincidences.end(); ++anIt)
50 if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint)
55 bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
56 const EntityWrapperPtr& theEntity1,
57 const EntityWrapperPtr& theEntity2)
59 bool isAccepted = true;
61 std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
62 std::list<CoincidentEntities>::iterator
63 aFound[2] = {myCoincident.end(), myCoincident.end()};
65 for (; anIt != myCoincident.end(); ++anIt) {
66 if (anIt->isExist(theEntity1))
68 if (anIt->isExist(theEntity2))
70 if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end())
74 if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
75 // new group of coincidence
76 myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2));
77 } else if (aFound[0] == aFound[1]) // same group => already coincident
80 if (aFound[0] == myCoincident.end())
81 isAccepted = aFound[1]->isNewCoincidence(theEntity2, theEntity1);
82 else if (aFound[1] == myCoincident.end())
83 isAccepted = aFound[0]->isNewCoincidence(theEntity1, theEntity2);
84 else { // merge two groups
85 isAccepted = aFound[0]->isNewCoincidence(theEntity1, *(aFound[1]), theEntity2);
86 myCoincident.erase(aFound[1]);
93 bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
94 const EntityWrapperPtr& thePoint,
95 const EntityWrapperPtr& theEntity)
97 std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
98 for (; anIt != myCoincident.end(); ++anIt)
99 if (anIt->isExist(thePoint))
102 if (anIt == myCoincident.end())
105 if (anIt->isExist(theEntity))
108 if (theEntity->type() == ENTITY_LINE) {
109 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(
110 std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity)->entity());
111 return anIt->isExist(aLine->p1) || anIt->isExist(aLine->p2);
120 PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
121 const EntityWrapperPtr& theEntity1,
122 const EntityWrapperPtr& theEntity2)
124 if (theEntity1->isExternal() && theEntity2->isExternal()) {
125 myExternalAndConnected[theEntity1] = std::set<EntityWrapperPtr>();
126 myExternalAndConnected[theEntity2] = std::set<EntityWrapperPtr>();
127 } else if (theEntity1->isExternal())
128 myExternalAndConnected[theEntity1].insert(theEntity2);
129 else if (theEntity2->isExternal())
130 myExternalAndConnected[theEntity2].insert(theEntity1);
132 std::set<EntityWrapperPtr> aGroup;
133 aGroup.insert(theEntity1);
134 aGroup.insert(theEntity2);
135 myExternalAndConnected[EntityWrapperPtr()] = aGroup;
139 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::hasExternal() const
141 return myExternalAndConnected.size() != 1 ||
142 myExternalAndConnected.find(EntityWrapperPtr()) == myExternalAndConnected.end();
145 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
146 const EntityWrapperPtr& theEntity) const
148 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
149 anIt = myExternalAndConnected.begin();
150 for (; anIt != myExternalAndConnected.end(); ++anIt)
151 if (anIt->first == theEntity ||
152 anIt->second.find(theEntity) != anIt->second.end())
157 static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
159 return thePoint1.x == thePoint2.x && thePoint1.y == thePoint2.y;
162 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
163 const GCS::Point& thePoint) const
165 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
166 anIt = myExternalAndConnected.begin();
167 for (; anIt != myExternalAndConnected.end(); ++anIt) {
168 if (anIt->first && anIt->first->type() == ENTITY_POINT) {
169 const GCSPointPtr& aPoint =
170 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(anIt->first)->point();
171 if (isEqual(*aPoint, thePoint))
175 std::set<EntityWrapperPtr>::const_iterator anEntIt = anIt->second.begin();
176 for (; anEntIt != anIt->second.end(); ++anEntIt)
177 if ((*anEntIt)->type() == ENTITY_POINT) {
178 const GCSPointPtr& aPoint =
179 std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(*anEntIt)->point();
180 if (isEqual(*aPoint, thePoint))
187 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
188 const EntityWrapperPtr& theEntityExist,
189 const EntityWrapperPtr& theOtherEntity)
191 if (theOtherEntity->isExternal()) {
193 if (myExternalAndConnected.find(theOtherEntity) == myExternalAndConnected.end())
194 myExternalAndConnected[theOtherEntity] = std::set<EntityWrapperPtr>();
195 // check whether all external entities are edges
196 bool isNewCoinc = true;
197 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator
198 anIt = myExternalAndConnected.begin();
199 for (; anIt != myExternalAndConnected.end() && isNewCoinc; ++anIt)
200 isNewCoinc = (anIt->first->type() != ENTITY_POINT);
203 myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()];
204 myExternalAndConnected.erase(EntityWrapperPtr());
209 if (theEntityExist->isExternal()) {
210 myExternalAndConnected[theEntityExist].insert(theOtherEntity);
214 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator
215 anIt = myExternalAndConnected.begin();
216 for (; anIt != myExternalAndConnected.end(); ++anIt)
217 if (anIt->second.find(theEntityExist) != anIt->second.end()) {
218 anIt->second.insert(theOtherEntity);
224 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
225 const EntityWrapperPtr& theEntityExist,
226 const CoincidentEntities& theOtherGroup,
227 const EntityWrapperPtr& theEntityInOtherGroup)
229 bool hasExt[2] = {hasExternal(), theOtherGroup.hasExternal()};
230 if (hasExt[0] && hasExt[1]) {
231 myExternalAndConnected.insert(theOtherGroup.myExternalAndConnected.begin(),
232 theOtherGroup.myExternalAndConnected.end());
234 } else if (!hasExt[0] && !hasExt[1]) {
235 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
236 aFound = theOtherGroup.myExternalAndConnected.find(EntityWrapperPtr());
238 myExternalAndConnected[EntityWrapperPtr()].insert(
239 aFound->second.begin(), aFound->second.end());
242 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > aSource, aDest;
243 EntityWrapperPtr aTarget;
245 aDest = myExternalAndConnected;
246 aSource = theOtherGroup.myExternalAndConnected;
247 aTarget = theEntityExist;
249 aSource = myExternalAndConnected;
250 aDest = theOtherGroup.myExternalAndConnected;
251 aTarget = theEntityInOtherGroup;
254 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
255 aFound = aSource.find(EntityWrapperPtr());
257 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::iterator anIt = aDest.begin();
258 for (; anIt != aDest.end(); ++anIt)
259 if (anIt->first == aTarget ||
260 anIt->second.find(aTarget) != anIt->second.end()) {
261 anIt->second.insert(aFound->second.begin(), aFound->second.end());