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::addCoincidence(
56 const EntityWrapperPtr& theEntity1,
57 const EntityWrapperPtr& theEntity2)
59 bool isAccepted = true;
60 std::list<CoincidentEntities>::iterator aFound[2] = {
61 findGroupOfCoincidence(theEntity1),
62 findGroupOfCoincidence(theEntity2)
65 if (aFound[0] == myCoincident.end() && aFound[1] == myCoincident.end()) {
66 // new group of coincidence
67 myCoincident.push_back(CoincidentEntities(theEntity1, theEntity2));
68 } else if (aFound[0] == myCoincident.end()) {
69 isAccepted = addToGroupOfCoincidence(*aFound[1], theEntity1);
70 } else if (aFound[1] == myCoincident.end()) {
71 isAccepted = addToGroupOfCoincidence(*aFound[0], theEntity2);
72 } else if (aFound[0] == aFound[1]) { // same group => already coincident
74 } else { // merge two groups
75 EntityWrapperPtr anEntityToAdd = theEntity1;
76 if (theEntity1->isExternal()) { // swap found groups;
77 anEntityToAdd = theEntity2;
78 std::list<CoincidentEntities>::iterator aTempIt = aFound[0];
79 aFound[0] = aFound[1];
83 aFound[1]->remove(anEntityToAdd);
84 aFound[0]->merge(*aFound[1]);
85 isAccepted = aFound[0]->add(anEntityToAdd);
86 myCoincident.erase(aFound[1]);
92 bool PlaneGCSSolver_UpdateCoincidence::isPointOnEntity(
93 const EntityWrapperPtr& thePoint,
94 const EntityWrapperPtr& theEntity)
96 std::list<CoincidentEntities>::iterator anIt = findGroupOfCoincidence(thePoint);
97 if (anIt == myCoincident.end())
100 if (anIt->isExist(theEntity))
103 if (theEntity->type() == ENTITY_LINE) {
104 std::shared_ptr<GCS::Line> aLine = std::dynamic_pointer_cast<GCS::Line>(
105 std::dynamic_pointer_cast<PlaneGCSSolver_EdgeWrapper>(theEntity)->entity());
106 return anIt->isExist(aLine->p1) || anIt->isExist(aLine->p2);
111 std::list<PlaneGCSSolver_UpdateCoincidence::CoincidentEntities>::iterator
112 PlaneGCSSolver_UpdateCoincidence::findGroupOfCoincidence(const EntityWrapperPtr& theEntity)
114 if (theEntity->type() != ENTITY_POINT)
115 return myCoincident.end();
117 std::list<CoincidentEntities>::iterator aFound = myCoincident.begin();
118 for (; aFound != myCoincident.end(); ++aFound)
119 if (aFound->isExist(theEntity))
124 bool PlaneGCSSolver_UpdateCoincidence::addToGroupOfCoincidence(
125 CoincidentEntities& theGroup, const EntityWrapperPtr& theEntity)
127 if (theGroup.isExist(theEntity))
130 theGroup.add(theEntity);
138 static const GCS::Point& toPoint(const EntityWrapperPtr& theEntity)
140 PointWrapperPtr aPoint = std::dynamic_pointer_cast<PlaneGCSSolver_PointWrapper>(theEntity);
141 return *(aPoint->point());
144 static double squareDistance(const GCS::Point& thePoint1, const GCS::Point& thePoint2)
146 double dx = *thePoint1.x - *thePoint2.x;
147 double dy = *thePoint1.y - *thePoint2.y;
148 return dx * dx + dy * dy;
151 static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList, const GCS::Point& thePoint)
153 std::set<EntityWrapperPtr>::const_iterator anIt = theList.begin();
154 for (; anIt != theList.end(); ++anIt)
155 if (squareDistance(thePoint, toPoint(*anIt)) < 1.e-14)
160 static bool hasSamePoint(const std::set<EntityWrapperPtr>& theList,
161 const EntityWrapperPtr& thePoint)
163 return hasSamePoint(theList, toPoint(thePoint));
167 PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::CoincidentEntities(
168 const EntityWrapperPtr& theEntity1,
169 const EntityWrapperPtr& theEntity2)
175 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::add(
176 const EntityWrapperPtr& theEntity)
179 if (theEntity->type() == ENTITY_POINT) {
180 if (theEntity->isExternal()) {
181 isAdded = !hasSamePoint(myExternalPoints, theEntity);
182 myExternalPoints.insert(theEntity);
184 myPoints.insert(theEntity);
186 myFeatures.insert(theEntity);
190 void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::remove(
191 const EntityWrapperPtr& theEntity)
193 if (theEntity->type() == ENTITY_POINT) {
194 if (theEntity->isExternal())
195 myExternalPoints.erase(theEntity);
197 myPoints.erase(theEntity);
199 myFeatures.erase(theEntity);
202 void PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::merge(
203 const CoincidentEntities& theOther)
205 myExternalPoints.insert(theOther.myExternalPoints.begin(), theOther.myExternalPoints.end());
206 myPoints.insert(theOther.myPoints.begin(), theOther.myPoints.end());
207 myFeatures.insert(theOther.myFeatures.begin(), theOther.myFeatures.end());
210 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
211 const EntityWrapperPtr& theEntity) const
213 if (theEntity->type() == ENTITY_POINT) {
214 if (theEntity->isExternal())
215 return myExternalPoints.find(theEntity) != myExternalPoints.end();
217 return myPoints.find(theEntity) != myPoints.end();
220 return myFeatures.find(theEntity) != myFeatures.end();
223 bool PlaneGCSSolver_UpdateCoincidence::CoincidentEntities::isExist(
224 const GCS::Point& thePoint) const
226 return hasSamePoint(myExternalPoints, thePoint) || hasSamePoint(myPoints, thePoint);