28 Node(
const TPoint& pt) : m_point(pt), m_left(
nullptr), m_right(
nullptr)
37 class BoundedPriorityQueue
41 BoundedPriorityQueue() =
delete;
42 BoundedPriorityQueue(
size_t bound) : bound(bound) { elements.reserve(bound + 1); };
44 void push(
const std::pair<double, const Node*>& val)
46 auto it = std::find_if(std::begin(elements), std::end(elements),
47 [&val](std::pair<double, const Node*> element) {
return val.first < element.first; });
48 elements.insert(it, val);
50 if (elements.size() > bound)
54 const std::pair<double, const Node*>& back()
const {
return elements.back(); };
55 const std::pair<double, const Node*>& operator[](
size_t index)
const {
return elements[index]; }
56 size_t size()
const {
return elements.size(); }
60 std::vector<std::pair<double, const Node*>> elements;
64 std::vector<Node> m_nodes;
68 NodeCmp(uint8_t index,
const GetComponentFunc& getComponentFunc) : m_index(index), m_getComponentFunc(getComponentFunc)
71 bool operator()(
const Node& a,
const Node& b)
const
73 return m_getComponentFunc(a.m_point, m_index) < m_getComponentFunc(b.m_point, m_index);
79 Node* MakeTree(
size_t begin,
size_t end, uint8_t index)
84 size_t n = begin + (end - begin) / 2;
86 auto i = m_nodes.begin();
87 std::nth_element(i + begin, i + n, i + end, NodeCmp(index, m_getComponentFunc));
89 index = (index + 1) % Dimensions;
91 m_nodes[n].m_left = MakeTree(begin, n, index);
92 m_nodes[n].m_right = MakeTree(n + 1, end, index);
96 void Nearest(
const Node* root,
const Coordinate& point, uint8_t index,
double& bestDistance,
const Node*& best,
double maxDistance)
const
98 if (root ==
nullptr) {
102 const double d = m_getDistanceFunc(point, root->m_point);
104 if (d < bestDistance) {
107 if (bestDistance <= maxDistance) {
112 if (bestDistance == 0) {
116 const double dx = m_getComponentFunc(root->m_point, index) - point[index];
117 index = (index + 1) % Dimensions;
119 Nearest(dx > 0 ? root->m_left : root->m_right, point, index, bestDistance, best, maxDistance);
121 if (abs(dx) >= bestDistance || abs(dx) >= maxDistance) {
125 Nearest(dx > 0 ? root->m_right : root->m_left, point, index, bestDistance, best, maxDistance);
128 void KNearest(
const Node* root,
const Coordinate& point, uint8_t index, BoundedPriorityQueue& queue,
size_t k)
const
130 if (root ==
nullptr) {
134 const double d = m_getDistanceFunc(point, root->m_point);
135 queue.push(std::make_pair(d, root));
137 const double dx = m_getComponentFunc(root->m_point, index) - point[index];
138 index = (index + 1) % Dimensions;
140 KNearest(dx > 0 ? root->m_left : root->m_right, point, index, queue, k);
142 if(queue.size() < k || abs(dx) < queue.back().first)
143 KNearest(dx > 0 ? root->m_right : root->m_left, point, index, queue, k);
146 void InRadius(
const Node* root,
const Coordinate& point,
const double radius, uint8_t index, std::vector<std::pair<const Node*, double>>& inRadius)
const
148 if (root ==
nullptr) {
152 const double d = m_getDistanceFunc(point, root->m_point);
155 inRadius.push_back(std::make_pair(root, d));
158 const double dx = m_getComponentFunc(root->m_point, index) - point[index];
159 index = (index + 1) % Dimensions;
161 InRadius(dx > 0 ? root->m_left : root->m_right, point, radius, index, inRadius);
163 if (abs(dx) > radius) {
167 InRadius(dx > 0 ? root->m_right : root->m_left, point, radius, index, inRadius);
178 template<
typename iterator>
181 m_getComponentFunc = getComponentFunc;
182 m_getDistanceFunc = getDistanceFunc;
184 m_nodes.reserve(std::distance(begin, end));
186 for (
auto i = begin; i != end; ++i) {
187 m_nodes.emplace_back(*i);
190 if (m_nodes.size() > 0) {
191 m_root = MakeTree(0, m_nodes.size() - 1, 0);
197 m_getComponentFunc = getComponentFunc;
198 m_getDistanceFunc = getDistanceFunc;
202 for (
size_t i = 0; i < n; ++i) {
203 m_nodes.emplace_back(construct(i));
206 if (m_nodes.size() > 0) {
207 m_root = MakeTree(0, m_nodes.size(), 0);
213 return m_nodes.empty();
216 bool Nearest(
const Coordinate& pt, TPoint& p,
double& resultDistance,
double maxDistance = std::numeric_limits<double>::max())
const
218 if (m_root ==
nullptr) {
222 const Node* best =
nullptr;
223 double dist = std::numeric_limits<double>::max();
224 Nearest(m_root, pt, 0, dist, best, maxDistance);
226 if (best !=
nullptr) {
228 resultDistance = dist;
235 bool KNearest(
const Coordinate& pt, std::vector<std::pair<TPoint, double>>& neighborsWithDistance,
size_t k)
const
237 if (m_root ==
nullptr) {
245 BoundedPriorityQueue queue(k);
246 KNearest(m_root, pt, 0, queue, k);
247 neighborsWithDistance.resize(queue.size());
249 for (
size_t i = 0; i < queue.size(); ++i) {
250 neighborsWithDistance[i] = std::make_pair(queue[i].second->m_point, queue[i].first);
256 bool InRadius(
const Coordinate& pt,
double radius, std::vector<std::pair<TPoint, double>>& pointsWithDistance)
const
258 if (m_root ==
nullptr) {
262 std::vector<std::pair<const Node*, double>> inRadiusNode;
263 InRadius(m_root, pt, radius, 0, inRadiusNode);
264 pointsWithDistance.resize(inRadiusNode.size());
266 for (
size_t i = 0; i < inRadiusNode.size(); ++i) {
267 pointsWithDistance[i] = std::make_pair(inRadiusNode[i].first->m_point, inRadiusNode[i].second);