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 if (theObserver->getType() == CONSTRAINT_PT_PT_COINCIDENT) {
23 for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
24 if ((*aPlaceToAdd)->getType() != CONSTRAINT_PT_PT_COINCIDENT)
27 myObservers.insert(aPlaceToAdd, theObserver);
29 myNext->attach(theObserver, theType);
32 void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
34 if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
35 theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() ||
36 theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
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);
43 myNext->update(theFeature);
46 static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences,
47 const EntityWrapperPtr& thePoint)
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)
56 bool PlaneGCSSolver_UpdateCoincidence::checkCoincidence(
57 const EntityWrapperPtr& theEntity1,
58 const EntityWrapperPtr& theEntity2)
60 bool isAccepted = true;
62 std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
63 std::list<CoincidentEntities>::iterator
64 aFound[2] = {myCoincident.end(), myCoincident.end()};
66 for (; anIt != myCoincident.end(); ++anIt) {
67 if (anIt->isExist(theEntity1))
69 if (anIt->isExist(theEntity2))
71 if (aFound[0] != myCoincident.end() && aFound[1] != myCoincident.end())
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
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]);
94 bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
95 const EntityWrapperPtr& thePoint,
96 const EntityWrapperPtr& theEntity)
98 std::list<CoincidentEntities>::iterator anIt = myCoincident.begin();
99 for (; anIt != myCoincident.end(); ++anIt)
100 if (anIt->isExist(thePoint))
103 if (anIt == myCoincident.end())
106 if (anIt->isExist(theEntity))
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);
121 PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
122 const EntityWrapperPtr& theEntity1,
123 const EntityWrapperPtr& theEntity2)
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);
133 std::set<EntityWrapperPtr> aGroup;
134 aGroup.insert(theEntity1);
135 aGroup.insert(theEntity2);
136 myExternalAndConnected[EntityWrapperPtr()] = aGroup;
140 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::hasExternal() const
142 return myExternalAndConnected.size() != 1 ||
143 myExternalAndConnected.find(EntityWrapperPtr()) == myExternalAndConnected.end();
146 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
147 const EntityWrapperPtr& theEntity) const
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())
158 static bool isEqual(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
160 return thePoint1.x == thePoint2.x && thePoint1.y == thePoint2.y;
163 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
164 const GCS::Point& thePoint) const
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))
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))
188 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
189 const EntityWrapperPtr& theEntityExist,
190 const EntityWrapperPtr& theOtherEntity)
192 if (theOtherEntity->isExternal()) {
194 if (myExternalAndConnected.find(theOtherEntity) == myExternalAndConnected.end())
195 myExternalAndConnected[theOtherEntity] = std::set<EntityWrapperPtr>();
198 myExternalAndConnected[theOtherEntity] = myExternalAndConnected[EntityWrapperPtr()];
199 myExternalAndConnected.erase(EntityWrapperPtr());
204 if (theEntityExist->isExternal()) {
205 myExternalAndConnected[theEntityExist].insert(theOtherEntity);
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);
219 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isNewCoincidence(
220 const EntityWrapperPtr& theEntityExist,
221 const CoincidentEntities& theOtherGroup,
222 const EntityWrapperPtr& theEntityInOtherGroup)
224 bool hasExt[2] = {hasExternal(), theOtherGroup.hasExternal()};
225 if (hasExt[0] && hasExt[1]) {
226 myExternalAndConnected.insert(theOtherGroup.myExternalAndConnected.begin(),
227 theOtherGroup.myExternalAndConnected.end());
229 } else if (!hasExt[0] && !hasExt[1]) {
230 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
231 aFound = theOtherGroup.myExternalAndConnected.find(EntityWrapperPtr());
233 myExternalAndConnected[EntityWrapperPtr()].insert(
234 aFound->second.begin(), aFound->second.end());
237 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> > aSource, aDest;
238 EntityWrapperPtr aTarget;
240 aDest = myExternalAndConnected;
241 aSource = theOtherGroup.myExternalAndConnected;
242 aTarget = theEntityExist;
244 aSource = myExternalAndConnected;
245 aDest = theOtherGroup.myExternalAndConnected;
246 aTarget = theEntityInOtherGroup;
249 std::map<EntityWrapperPtr, std::set<EntityWrapperPtr> >::const_iterator
250 aFound = aSource.find(EntityWrapperPtr());
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());