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 static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList,
17 const EntityWrapperPtr& thePoint);
20 void PlaneGCSSolver_UpdateCoincidence::attach(SketchSolver_Constraint* theObserver,
21 const std::string& theType)
23 if (theType == GROUP()) {
24 std::list<SketchSolver_Constraint*>::iterator aPlaceToAdd = myObservers.end();
25 // point-point coincidence is placed first,
26 // other constraints are sorted by their type
27 for (aPlaceToAdd = myObservers.begin(); aPlaceToAdd != myObservers.end(); ++aPlaceToAdd)
28 if ((*aPlaceToAdd)->getType() > theObserver->getType())
30 myObservers.insert(aPlaceToAdd, theObserver);
32 myNext->attach(theObserver, theType);
35 void PlaneGCSSolver_UpdateCoincidence::update(const FeaturePtr& theFeature)
37 if (theFeature->getKind() == SketchPlugin_ConstraintCoincidence::ID() ||
38 theFeature->getKind() == SketchPlugin_ConstraintMiddle::ID() ||
39 theFeature->getKind() == SketchPlugin_ConstraintCollinear::ID()) {
41 // notify listeners and stop procesing
42 std::list<SketchSolver_Constraint*>::iterator anIt = myObservers.begin();
43 for (; anIt != myObservers.end(); ++anIt)
44 (*anIt)->notify(theFeature, this);
46 myNext->update(theFeature);
49 static bool hasAnotherExternalPoint(const std::set<EntityWrapperPtr>& theCoincidences,
50 const EntityWrapperPtr& thePoint)
52 std::set<EntityWrapperPtr>::const_iterator anIt = theCoincidences.begin();
53 for (; anIt != theCoincidences.end(); ++anIt)
54 if ((*anIt)->type() == ENTITY_POINT && (*anIt)->isExternal() && *anIt != thePoint)
59 bool PlaneGCSSolver_UpdateCoincidence::addCoincidence(
60 const EntityWrapperPtr& theEntity1,
61 const EntityWrapperPtr& theEntity2)
63 bool isAccepted = true;
64 std::list<CoincidentEntities>::iterator aFound[2] = {
65 findGroupOfCoincidence(theEntity1),
66 findGroupOfCoincidence(theEntity2)
69 if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
70 // new group of coincidence
71 myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2));
72 } else if (aFound[0] == myCoincident.end()) {
73 isAccepted = addToGroupOfCoincidence(*aFound[1], theEntity1);
74 } else if (aFound[1] == myCoincident.end()) {
75 isAccepted = addToGroupOfCoincidence(*aFound[0], theEntity2);
76 } else if (aFound[0] == aFound[1]) { // same group => already coincident
78 } else { // merge two groups
79 // first check the external points are equal
80 EntityWrapperPtr anExternal0 = aFound[0]->externalPoint();
81 EntityWrapperPtr anExternal1 = aFound[1]->externalPoint();
82 if (anExternal0 && anExternal1) {
83 std::set<EntityWrapperPtr> anExtList;
84 anExtList.insert(anExternal0);
85 if (hasSamePoint(anExtList, anExternal1)) {
86 // no need to add coincidence, because all points are
87 // already coincident to correct external points
93 aFound[0]->merge(*aFound[1]);
94 myCoincident.erase(aFound[1]);
100 bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
101 const EntityWrapperPtr& thePoint,
102 const EntityWrapperPtr& theEntity)
104 std::list<CoincidentEntities>::iterator anIt = findGroupOfCoincidence(thePoint);
105 if (anIt == myCoincident.end())
108 if (anIt->isExist(theEntity))
111 if (theEntity->type() == ENTITY_LINE) {
112 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(
113 std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity)->entity());
114 return anIt->isExist(aLine->p1) || anIt->isExist(aLine->p2);
119 std::list<PlaneGCSSolver_UpdateCoincidence::CoincidentEntities>::iterator
120 PlaneGCSSolver_UpdateCoincidence::findGroupOfCoincidence(const EntityWrapperPtr& theEntity)
122 if (theEntity->type() != ENTITY_POINT)
123 return myCoincident.end();
125 std::list<CoincidentEntities>::iterator aFound = myCoincident.begin();
126 for (; aFound != myCoincident.end(); ++aFound)
127 if (aFound->isExist(theEntity))
132 bool PlaneGCSSolver_UpdateCoincidence::addToGroupOfCoincidence(
133 CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity)
135 if (theGroup.isExist(theEntity))
137 return theGroup.add(theEntity);
144 static const GCS::Point& toPoint(const EntityWrapperPtr& theEntity)
146 PointWrapperPtr aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
147 return *(aPoint->point());
150 static double squareDistance(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
152 double dx = *thePoint1.x - *thePoint2.x;
153 double dy = *thePoint1.y - *thePoint2.y;
154 return dx * dx + dy * dy;
157 static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList, const GCS::Point& thePoint)
159 std::set<EntityWrapperPtr>::const_iterator anIt = theList.begin();
160 for (; anIt != theList.end(); ++anIt)
161 if (squareDistance(thePoint, toPoint(*anIt)) < 1.e-14)
166 bool hasSamePoint(const std::set<EntityWrapperPtr>& theList,
167 const EntityWrapperPtr& thePoint)
169 return hasSamePoint(theList, toPoint(thePoint));
173 PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
174 const EntityWrapperPtr& theEntity1,
175 const EntityWrapperPtr& theEntity2)
181 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::add(
182 const EntityWrapperPtr& theEntity)
185 if (theEntity->type() == ENTITY_POINT) {
186 if (theEntity->isExternal()) {
187 isAdded = !hasSamePoint(myExternalPoints, theEntity);
188 myExternalPoints.insert(theEntity);
190 myPoints.insert(theEntity);
192 myFeatures.insert(theEntity);
196 void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::remove(
197 const EntityWrapperPtr& theEntity)
199 if (theEntity->type() == ENTITY_POINT) {
200 if (theEntity->isExternal())
201 myExternalPoints.erase(theEntity);
203 myPoints.erase(theEntity);
205 myFeatures.erase(theEntity);
208 void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::merge(
209 const CoincidentEntities& theOther)
211 myExternalPoints.insert(theOther.myExternalPoints.begin(), theOther.myExternalPoints.end());
212 myPoints.insert(theOther.myPoints.begin(), theOther.myPoints.end());
213 myFeatures.insert(theOther.myFeatures.begin(), theOther.myFeatures.end());
216 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
217 const EntityWrapperPtr& theEntity) const
219 if (theEntity->type() == ENTITY_POINT) {
220 if (theEntity->isExternal())
221 return myExternalPoints.find(theEntity) != myExternalPoints.end();
223 return myPoints.find(theEntity) != myPoints.end();
226 return myFeatures.find(theEntity) != myFeatures.end();
229 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
230 const GCS::Point& thePoint) const
232 return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint);
235 EntityWrapperPtr PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::externalPoint() const
237 return myExternalPoints.empty() ? EntityWrapperPtr() : *myExternalPoints.begin();