gtsam_points
Loading...
Searching...
No Matches
knn_result.hpp
1// SPDX-FileCopyrightText: Copyright 2024 Kenji Koide
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include <limits>
6#include <iostream>
7
8namespace gtsam_points {
9
11struct KnnSetting {
12public:
14 template <typename Result>
15 bool fulfilled(const Result& result) const {
16 return result.worst_distance() < epsilon || result.num_found() >= max_nn;
17 }
18
19public:
20 int max_nn = std::numeric_limits<int>::max();
21 double max_sq_dist = std::numeric_limits<double>::max();
22 double epsilon = 0.0;
23};
24
27 template <typename T>
28 T operator()(const T& x) const {
29 return x;
30 }
31};
32
35template <int N, typename IndexTransform = identity_transform>
36struct KnnResult {
37public:
38 static constexpr size_t INVALID = std::numeric_limits<size_t>::max();
39
45 explicit KnnResult(
46 size_t* indices,
47 double* distances,
48 int num_neighbors = -1,
49 const IndexTransform& index_transform = IndexTransform(),
50 double max_sq_dist = std::numeric_limits<double>::max())
51 : index_transform(index_transform),
52 capacity(num_neighbors),
56 if constexpr (N > 0) {
57 if (num_neighbors >= 0) {
58 std::cerr << "warning: Specifying dynamic num_neighbors=" << num_neighbors << " for a static KNN result container (N=" << N << ")"
59 << std::endl;
60 abort();
61 }
62 } else {
63 if (num_neighbors <= 0) {
64 std::cerr << "error: Specifying invalid num_neighbors=" << num_neighbors << " for a dynamic KNN result container" << std::endl;
65 abort();
66 }
67 }
68
69 std::fill(this->indices, this->indices + buffer_size(), INVALID);
70 std::fill(this->distances, this->distances + buffer_size(), max_sq_dist);
71 }
72
74 size_t buffer_size() const {
75 if constexpr (N > 0) {
76 return N;
77 } else {
78 return capacity;
79 }
80 }
81
83 size_t num_found() const { return num_found_neighbors; }
84
86 double worst_distance() const { return distances[buffer_size() - 1]; }
87
89 void push(size_t index, double distance) {
90 if (distance >= worst_distance()) {
91 return;
92 }
93
94 if constexpr (N == 1) {
95 indices[0] = index_transform(index);
96 distances[0] = distance;
97 } else {
98 int insert_loc = std::min<int>(num_found_neighbors, buffer_size() - 1);
99 for (; insert_loc > 0 && distance < distances[insert_loc - 1]; insert_loc--) {
100 indices[insert_loc] = indices[insert_loc - 1];
101 distances[insert_loc] = distances[insert_loc - 1];
102 }
103
104 indices[insert_loc] = index_transform(index);
105 distances[insert_loc] = distance;
106 }
107
109 }
110
111public:
112 const IndexTransform& index_transform;
113 const int capacity;
115 size_t* indices;
116 double* distances;
117};
118
120template <typename IndexTransform = identity_transform>
122public:
125 explicit RadiusSearchResult(const IndexTransform& index_transform = IndexTransform()) : index_transform(index_transform) { neighbors.reserve(32); }
126
128 size_t num_found() const { return neighbors.size(); }
129
131 constexpr double worst_distance() const { return std::numeric_limits<double>::max(); }
132
134 void sort() {
135 std::sort(neighbors.begin(), neighbors.end(), [](const auto& a, const auto& b) { return a.second < b.second; });
136 }
137
139 void push(size_t index, double distance) { neighbors.emplace_back(index_transform(index), distance); }
140
141public:
142 const IndexTransform& index_transform;
143 std::vector<std::pair<size_t, double>> neighbors;
144};
145
146} // namespace gtsam_points
K-nearest neighbor search result container.
Definition knn_result.hpp:36
void push(size_t index, double distance)
Push a pair of point index and distance to the result.
Definition knn_result.hpp:89
double worst_distance() const
Worst distance in the result.
Definition knn_result.hpp:86
size_t buffer_size() const
Buffer size (i.e., Maximum number of neighbors)
Definition knn_result.hpp:74
const int capacity
Maximum number of neighbors to search.
Definition knn_result.hpp:113
size_t num_found() const
Number of found neighbors.
Definition knn_result.hpp:83
KnnResult(size_t *indices, double *distances, int num_neighbors=-1, const IndexTransform &index_transform=IndexTransform(), double max_sq_dist=std::numeric_limits< double >::max())
Constructor.
Definition knn_result.hpp:45
size_t * indices
Indices of neighbors.
Definition knn_result.hpp:115
double * distances
Distances to neighbors.
Definition knn_result.hpp:116
int num_found_neighbors
Number of found neighbors.
Definition knn_result.hpp:114
K-nearest neighbor search setting.
Definition knn_result.hpp:11
double epsilon
Early termination threshold.
Definition knn_result.hpp:22
int max_nn
Maximum number of neighbors to search.
Definition knn_result.hpp:20
bool fulfilled(const Result &result) const
Check if the result satisfies the early termination condition.
Definition knn_result.hpp:15
double max_sq_dist
Maximum squared distance to search.
Definition knn_result.hpp:21
Radius neighbor search result container.
Definition knn_result.hpp:121
void sort()
Sort neighbors by distance.
Definition knn_result.hpp:134
std::vector< std::pair< size_t, double > > neighbors
Pairs of point index and distance.
Definition knn_result.hpp:143
void push(size_t index, double distance)
Push a pair of point index and distance to the result.
Definition knn_result.hpp:139
constexpr double worst_distance() const
Worst distance in the result.
Definition knn_result.hpp:131
size_t num_found() const
Number of found neighbors.
Definition knn_result.hpp:128
RadiusSearchResult(const IndexTransform &index_transform=IndexTransform())
Constructor.
Definition knn_result.hpp:125
Identity transformation function. (use std::identity instead in C++20)
Definition knn_result.hpp:26