GCC Code Coverage Report


Directory: ./
File: lib/geogram/points/nn_search.h
Date: 2026-09-07 02:37:58
Exec Total Coverage
Lines: 12 12 100.0%
Functions: 4 4 100.0%
Branches: 4 20 20.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2000-2022 Inria
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * * Neither the name of the ALICE Project-Team nor the names of its
14 * contributors may be used to endorse or promote products derived from this
15 * software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
18 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
28 *
29 * Contact: Bruno Levy
30 *
31 * https://www.inria.fr/fr/bruno-levy
32 *
33 * Inria,
34 * Domaine de Voluceau,
35 * 78150 Le Chesnay - Rocquencourt
36 * FRANCE
37 *
38 */
39
40 #ifndef GEOGRAM_POINTS_NN_SEARCH
41 #define GEOGRAM_POINTS_NN_SEARCH
42
43 #include <geogram/basic/common.h>
44 #include <geogram/basic/numeric.h>
45 #include <geogram/basic/smart_pointer.h>
46 #include <geogram/basic/counted.h>
47 #include <geogram/basic/factory.h>
48
49 /**
50 * \file geogram/points/nn_search.h
51 * \brief Abstract interface for nearest neighbor searching
52 */
53
54 namespace GEO {
55
56 /**
57 * \brief Abstract interface for nearest neighbor search algorithms.
58 * \details
59 * Given a point set in arbitrary dimension, creates a data
60 * structure for efficient nearest neighbor queries.
61 *
62 * NearestNeighborSearch objects are created using method create() which
63 * uses the Factory service. New search algorithms can be implemented and
64 * registered to the factory using
65 * geo_register_NearestNeighborSearch_creator().
66 * \see NearestNeighborSearchFactory
67 * \see geo_register_NearestNeighborSearch_creator
68 */
69 class GEOGRAM_API NearestNeighborSearch : public Counted {
70 public:
71 /**
72 * \brief Creates a new search algorithm
73 * \param[in] dimension dimension of the points (e.g., 3 for 3d)
74 * \param[in] name name of the search algorithm to create:
75 * - "ANN" - uses the standard ANN algorithm
76 * - "BNN" - uses the optimized KdTree
77 * - "default", uses the command line argument "algo:nn_search"
78 * \retval nullptr if \p name is not a valid search algorithm name
79 * \retval otherwise, a pointer to a search algorithm object. The
80 * returned pointer must be stored in a NearestNeighborSearch_var that
81 * does automatic destruction:
82 * \code
83 * NearestNeighborSearch_var nnsearch =
84 * NearestNeighborSearch::create(3, "ANN");
85 * \endcode
86 */
87 static NearestNeighborSearch* create(
88
1/6
✓ Branch 1 taken 67 times.
✗ Branch 2 not taken.
✗ Branch 5 not taken.
✗ Branch 6 not taken.
✗ Branch 8 not taken.
✗ Branch 9 not taken.
201 coord_index_t dimension, const std::string& name = "default"
89 );
90
91 /**
92 * \brief Sets the points and create the search data structure.
93 * \param[in] nb_points number of points
94 * \param[in] points an array of nb_points * dimension()
95 */
96 virtual void set_points(index_t nb_points, const double* points);
97
98 /**
99 * \brief Tests whether the stride variant of set_points() is supported
100 * \return true if stride different from dimension can be used
101 * in set_points(), false otherwise
102 */
103 virtual bool stride_supported() const;
104
105 /**
106 * \brief Sets the points and create the search data structure.
107 * \details This variant has a stride parameter. Call
108 * stride_supported() before to check whether it is supported.
109 *
110 * \param[in] nb_points number of points
111 * \param[in] points an array of nb_points * dimension()
112 * \param[in] stride number of doubles between two consecutive
113 * points (stride=dimension() by default).
114 */
115 virtual void set_points(
116 index_t nb_points, const double* points, index_t stride
117 );
118
119 /**
120 * \brief Finds the nearest neighbors of a point given by
121 * coordinates.
122 * \param[in] nb_neighbors number of neighbors to be searched.
123 * Should be smaller or equal to nb_points() (else it triggers
124 * an assertion)
125 * \param[in] query_point as an array of dimension() doubles
126 * \param[out] neighbors array of nb_neighbors index_t
127 * \param[out] neighbors_sq_dist array of nb_neighbors doubles
128 */
129 virtual void get_nearest_neighbors(
130 index_t nb_neighbors,
131 const double* query_point,
132 index_t* neighbors,
133 double* neighbors_sq_dist
134 ) const = 0;
135
136
137 /**
138 * \brief A structure to discriminate between the two
139 * versions of get_nearest_neighbors()
140 */
141 struct KeepInitialValues {
142 };
143
144 /**
145 * \brief Finds the nearest neighbors of a point given by
146 * coordinates. Uses input neighbors and squared distance as
147 * an initialization.
148 * \details Default implementation ignores the input values.
149 * Derived classes may have more efficient implementations.
150 * \param[in] nb_neighbors number of neighbors to be searched.
151 * Should be smaller or equal to nb_points() (else it triggers
152 * an assertion)
153 * \param[in] query_point as an array of dimension() doubles
154 * \param[in,out] neighbors array of nb_neighbors index_t
155 * \param[in,out] neighbors_sq_dist array of nb_neighbors doubles
156 * \param[in] dummy a dummy parameter to discriminate between the
157 * two forms of get_nearest_neighbors()
158 */
159 virtual void get_nearest_neighbors(
160 index_t nb_neighbors,
161 const double* query_point,
162 index_t* neighbors,
163 double* neighbors_sq_dist,
164 KeepInitialValues dummy
165 ) const;
166
167 /**
168 * \brief Finds the nearest neighbors of a point given by
169 * its index.
170 * \details For some implementation, may be faster than
171 * nearest neighbor search by point coordinates.
172 * \param[in] nb_neighbors number of neighbors to be searched.
173 * Should be smaller or equal to nb_points() (else it triggers
174 * an assertion)
175 * \param[in] query_point as the index of one of the points that
176 * was inserted in this NearestNeighborSearch
177 * \param[out] neighbors array of nb_neighbors index_t
178 * \param[out] neighbors_sq_dist array of nb_neighbors doubles
179 */
180 virtual void get_nearest_neighbors(
181 index_t nb_neighbors,
182 index_t query_point,
183 index_t* neighbors,
184 double* neighbors_sq_dist
185 ) const;
186
187 /**
188 * \brief Nearest neighbor search.
189 * \param[in] query_point array of dimension() doubles
190 * \return the index of the nearest neighbor from \p query_point
191 */
192 1750 index_t get_nearest_neighbor(const double* query_point) const {
193 index_t result;
194 double sq_dist;
195
1/2
✓ Branch 1 taken 1750 times.
✗ Branch 2 not taken.
1750 get_nearest_neighbors(1, query_point, &result, &sq_dist);
196
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 1750 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
1750 geo_assert(result < nb_points());
197 1750 return result;
198 }
199
200 /**
201 * \brief Gets the dimension of the points.
202 * \return the dimension
203 */
204 183112732 coord_index_t dimension() const {
205 183112732 return dimension_;
206 }
207
208 /**
209 * \brief Gets the number of points.
210 * \return the number of points
211 */
212 230352299 index_t nb_points() const {
213 230352299 return nb_points_;
214 }
215
216 /**
217 * \brief Gets a point by its index
218 * \param[in] i index of the point
219 * \return a const pointer to the coordinates of the point
220 */
221 226705394 const double* point_ptr(index_t i) const {
222
1/6
✗ Branch 1 not taken.
✓ Branch 2 taken 226705394 times.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
✗ Branch 7 not taken.
✗ Branch 8 not taken.
226705394 geo_debug_assert(i < nb_points());
223 226705394 return points_ + i * stride_;
224 }
225
226 /**
227 * \brief Search can be exact or approximate. Approximate
228 * search may be faster.
229 * \return true if nearest neighbor search is exact,
230 * false otherwise
231 */
232 bool exact() const {
233 return exact_;
234 }
235
236 /**
237 * \brief Search can be exact or approximate. Approximate
238 * search may be faster.
239 * \param[in] x true if nearest neighbor search is exact,
240 * false otherwise. Default mode is exact.
241 */
242 virtual void set_exact(bool x);
243
244 protected:
245 /**
246 * \brief Constructs a NearestNeighborSearch.
247 * \param[in] dimension dimension of the points
248 */
249 NearestNeighborSearch(coord_index_t dimension);
250
251 /**
252 * \brief NearestNeighborSearch destructor
253 */
254 ~NearestNeighborSearch() override;
255
256 protected:
257 coord_index_t dimension_;
258 index_t nb_points_;
259 index_t stride_;
260 const double* points_;
261 bool exact_;
262 };
263
264 /**
265 * \brief A smart pointer that contains a NearestNeighborSearch object.
266 * \relates NearestNeighborSearch
267 */
268 typedef SmartPointer<NearestNeighborSearch> NearestNeighborSearch_var;
269
270 /**
271 * \brief NearestNeighborSearch Factory
272 * \details
273 * This Factory is used to create NearestNeighborSearch objects.
274 * It can also be used to register new NearestNeighborSearch
275 * implementations.
276 * \see geo_register_NearestNeighborSearch_creator
277 * \see Factory
278 * \relates NearestNeighborSearch
279 */
280 typedef Factory1<NearestNeighborSearch, coord_index_t>
281 NearestNeighborSearchFactory;
282
283 /**
284 * \brief Helper macro to register a NearestNeighborSearch implementation
285 * \see NearestNeighborSearchFactory
286 * \relates NearestNeighborSearch
287 */
288 #define geo_register_NearestNeighborSearch_creator(type, name) \
289 geo_register_creator(GEO::NearestNeighborSearchFactory, type, name)
290 }
291
292 #endif
293