Point Cloud Library (PCL) 1.15.1-dev
Loading...
Searching...
No Matches
brute_force.hpp
1/*
2 * Software License Agreement (BSD License)
3 *
4 * Point Cloud Library (PCL) - www.pointclouds.org
5 * Copyright (c) 2010-2011, Willow Garage, Inc.
6 *
7 * All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * * Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * * Redistributions in binary form must reproduce the above
16 * copyright notice, this list of conditions and the following
17 * disclaimer in the documentation and/or other materials provided
18 * with the distribution.
19 * * Neither the name of the copyright holder(s) nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
31 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
33 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
34 * POSSIBILITY OF SUCH DAMAGE.
35 *
36 */
37
38#pragma once
39
40#include <pcl/search/brute_force.h>
41#include <queue>
42#include <vector>
43
44//////////////////////////////////////////////////////////////////////////////////////////////
45template <typename PointT> float
47 const PointT& point1, const PointT& point2) const
48{
49 if constexpr (pcl::traits::has_xyz_v<PointT>)
50 {
51 if (point_representation_->isTrivial () &&
52 point_representation_->getNumberOfDimensions () == 3)
53 return (point1.getVector3fMap () - point2.getVector3fMap ()).squaredNorm ();
54 }
55
56 const int nr_dimensions = point_representation_->getNumberOfDimensions ();
57 std::vector<float> point1_representation (nr_dimensions);
58 std::vector<float> point2_representation (nr_dimensions);
59 point_representation_->vectorize (point1, point1_representation);
60 point_representation_->vectorize (point2, point2_representation);
61
62 float dist = 0.0f;
63 for (int i = 0; i < nr_dimensions; ++i)
64 {
65 const float diff = point1_representation[i] - point2_representation[i];
66 dist += diff * diff;
67 }
68 return (dist);
69}
70
71//////////////////////////////////////////////////////////////////////////////////////////////
72template <typename PointT> int
74 const PointT& point, int k, Indices& k_indices, std::vector<float>& k_distances) const
75{
76 assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point given to nearestKSearch!");
77
78 k_indices.clear ();
79 k_distances.clear ();
80 if (k < 1)
81 return 0;
82
83 if (input_->is_dense)
84 return denseKSearch (point, k, k_indices, k_distances);
85 return sparseKSearch (point, k, k_indices, k_distances);
86}
87
88//////////////////////////////////////////////////////////////////////////////////////////////
89template <typename PointT> int
91 const PointT &point, int k, Indices &k_indices, std::vector<float> &k_distances) const
92{
93 // container for first k elements -> O(1) for insertion, since order not required here
94 std::vector<Entry> result;
95 result.reserve (k);
96 std::priority_queue<Entry> queue;
97 if (indices_)
98 {
99 auto iIt = indices_->cbegin ();
100 auto iEnd = indices_->cbegin () + std::min (static_cast<unsigned> (k), static_cast<unsigned> (indices_->size ()));
101 for (; iIt != iEnd; ++iIt)
102 result.push_back (Entry (*iIt, getDistSqr ((*input_)[*iIt], point)));
103
104 queue = std::priority_queue<Entry> (result.begin (), result.end ());
105
106 // add the rest
107 Entry entry;
108 for (; iIt != indices_->cend (); ++iIt)
109 {
110 entry.distance = getDistSqr ((*input_)[*iIt], point);
111 if (queue.top ().distance > entry.distance)
112 {
113 entry.index = *iIt;
114 queue.pop ();
115 queue.push (entry);
116 }
117 }
118 }
119 else
120 {
121 Entry entry;
122 for (entry.index = 0; entry.index < std::min<pcl::index_t> (k, input_->size ()); ++entry.index)
123 {
124 entry.distance = getDistSqr ((*input_)[entry.index], point);
125 result.push_back (entry);
126 }
127
128 queue = std::priority_queue<Entry> (result.begin (), result.end ());
129
130 // add the rest
131 for (; entry.index < static_cast<pcl::index_t>(input_->size ()); ++entry.index)
132 {
133 entry.distance = getDistSqr ((*input_)[entry.index], point);
134 if (queue.top ().distance > entry.distance)
135 {
136 queue.pop ();
137 queue.push (entry);
138 }
139 }
140 }
141
142 k_indices.resize (queue.size ());
143 k_distances.resize (queue.size ());
144 std::size_t idx = queue.size () - 1;
145 while (!queue.empty ())
146 {
147 k_indices [idx] = queue.top ().index;
148 k_distances [idx] = queue.top ().distance;
149 queue.pop ();
150 --idx;
151 }
152
153 return (static_cast<int> (k_indices.size ()));
154}
155
156//////////////////////////////////////////////////////////////////////////////////////////////
157template <typename PointT> int
159 const PointT &point, int k, Indices &k_indices, std::vector<float> &k_distances) const
160{
161 // result used to collect the first k neighbors -> unordered
162 std::vector<Entry> result;
163 result.reserve (k);
164
165 std::priority_queue<Entry> queue;
166 if (indices_)
167 {
168 auto iIt =indices_->cbegin ();
169 for (; iIt != indices_->cend () && result.size () < static_cast<unsigned> (k); ++iIt)
170 {
171 if (point_representation_->isValid ((*input_)[*iIt]))
172 result.push_back (Entry (*iIt, getDistSqr ((*input_)[*iIt], point)));
173 }
174
175 queue = std::priority_queue<Entry> (result.begin (), result.end ());
176 if (queue.empty ())
177 return 0;
178
179 // either we have k elements, or there are none left to iterate >in either case we're fine
180 // add the rest
181 Entry entry;
182 for (; iIt != indices_->cend (); ++iIt)
183 {
184 if (!point_representation_->isValid ((*input_)[*iIt]))
185 continue;
186
187 entry.distance = getDistSqr ((*input_)[*iIt], point);
188 if (queue.top ().distance > entry.distance)
189 {
190 entry.index = *iIt;
191 queue.pop ();
192 queue.push (entry);
193 }
194 }
195 }
196 else
197 {
198 Entry entry;
199 for (entry.index = 0; (entry.index < static_cast<pcl::index_t>(input_->size ())) && (result.size () < static_cast<std::size_t> (k)); ++entry.index)
200 {
201 if (point_representation_->isValid ((*input_)[entry.index]))
202 {
203 entry.distance = getDistSqr ((*input_)[entry.index], point);
204 result.push_back (entry);
205 }
206 }
207 queue = std::priority_queue<Entry> (result.begin (), result.end ());
208 if (queue.empty ())
209 return 0;
210
211 // add the rest
212 for (; entry.index < static_cast<pcl::index_t>(input_->size ()); ++entry.index)
213 {
214 if (!point_representation_->isValid ((*input_)[entry.index]))
215 continue;
216
217 entry.distance = getDistSqr ((*input_)[entry.index], point);
218 if (queue.top ().distance > entry.distance)
219 {
220 queue.pop ();
221 queue.push (entry);
222 }
223 }
224 }
225
226 k_indices.resize (queue.size ());
227 k_distances.resize (queue.size ());
228 std::size_t idx = queue.size () - 1;
229 while (!queue.empty ())
230 {
231 k_indices [idx] = queue.top ().index;
232 k_distances [idx] = queue.top ().distance;
233 queue.pop ();
234 --idx;
235 }
236 return (static_cast<int> (k_indices.size ()));
237}
238
239//////////////////////////////////////////////////////////////////////////////////////////////
240template <typename PointT> int
242 const PointT& point, double radius,
243 Indices &k_indices, std::vector<float> &k_sqr_distances,
244 unsigned int max_nn) const
245{
246 radius *= radius;
247
248 std::size_t reserve = max_nn;
249 if (reserve == 0)
250 {
251 if (indices_)
252 reserve = std::min (indices_->size (), input_->size ());
253 else
254 reserve = input_->size ();
255 }
256 k_indices.reserve (reserve);
257 k_sqr_distances.reserve (reserve);
258 float distance;
259 if (indices_)
260 {
261 for (const auto& idx : *indices_)
262 {
263 distance = getDistSqr ((*input_)[idx], point);
264 if (distance <= radius)
265 {
266 k_indices.push_back (idx);
267 k_sqr_distances.push_back (distance);
268 if (k_indices.size () == max_nn) // max_nn = 0 -> never true
269 break;
270 }
271 }
272 }
273 else
274 {
275 for (std::size_t index = 0; index < input_->size (); ++index)
276 {
277 distance = getDistSqr ((*input_)[index], point);
278 if (distance <= radius)
279 {
280 k_indices.push_back (index);
281 k_sqr_distances.push_back (distance);
282 if (k_indices.size () == max_nn) // never true if max_nn = 0
283 break;
284 }
285 }
286 }
287
288 if (sorted_results_)
289 this->sortResults (k_indices, k_sqr_distances);
290
291 return (static_cast<int> (k_indices.size ()));
292}
293
294//////////////////////////////////////////////////////////////////////////////////////////////
295template <typename PointT> int
297 const PointT& point, double radius,
298 Indices &k_indices, std::vector<float> &k_sqr_distances,
299 unsigned int max_nn) const
300{
301 radius *= radius;
302
303 std::size_t reserve = max_nn;
304 if (reserve == 0)
305 {
306 if (indices_)
307 reserve = std::min (indices_->size (), input_->size ());
308 else
309 reserve = input_->size ();
310 }
311 k_indices.reserve (reserve);
312 k_sqr_distances.reserve (reserve);
313
314 float distance;
315 if (indices_)
316 {
317 for (const auto& idx : *indices_)
318 {
319 if (!point_representation_->isValid ((*input_)[idx]))
320 continue;
321
322 distance = getDistSqr ((*input_)[idx], point);
323 if (distance <= radius)
324 {
325 k_indices.push_back (idx);
326 k_sqr_distances.push_back (distance);
327 if (k_indices.size () == max_nn) // never true if max_nn = 0
328 break;
329 }
330 }
331 }
332 else
333 {
334 for (std::size_t index = 0; index < input_->size (); ++index)
335 {
336 if (!point_representation_->isValid ((*input_)[index]))
337 continue;
338 distance = getDistSqr ((*input_)[index], point);
339 if (distance <= radius)
340 {
341 k_indices.push_back (index);
342 k_sqr_distances.push_back (distance);
343 if (k_indices.size () == max_nn) // never true if max_nn = 0
344 break;
345 }
346 }
347 }
348
349 if (sorted_results_)
350 this->sortResults (k_indices, k_sqr_distances);
351
352 return (static_cast<int> (k_indices.size ()));
353}
354
355//////////////////////////////////////////////////////////////////////////////////////////////
356template <typename PointT> int
358 const PointT& point, double radius, Indices &k_indices,
359 std::vector<float> &k_sqr_distances, unsigned int max_nn) const
360{
361 assert (point_representation_->isValid (point) && "Invalid (NaN, Inf) point given to radiusSearch!");
362
363 k_indices.clear ();
364 k_sqr_distances.clear ();
365 if (radius <= 0)
366 return 0;
367
368 if (input_->is_dense)
369 return denseRadiusSearch (point, radius, k_indices, k_sqr_distances, max_nn);
370 return sparseRadiusSearch (point, radius, k_indices, k_sqr_distances, max_nn);
371}
372
373#define PCL_INSTANTIATE_BruteForce(T) template class PCL_EXPORTS pcl::search::BruteForce<T>;
Implementation of a simple brute force search algorithm.
Definition brute_force.h:53
int nearestKSearch(const PointT &point, int k, Indices &k_indices, std::vector< float > &k_distances) const override
Search for the k-nearest neighbors for the given query point.
int radiusSearch(const PointT &point, double radius, Indices &k_indices, std::vector< float > &k_sqr_distances, unsigned int max_nn=0) const override
Search for all the nearest neighbors of the query point in a given radius.
float distance(const PointT &p1, const PointT &p2)
Definition geometry.h:60
detail::int_type_t< detail::index_type_size, detail::index_type_signed > index_t
Type used for an index in PCL.
Definition types.h:112
IndicesAllocator<> Indices
Type used for indices in PCL.
Definition types.h:133
A point structure representing Euclidean xyz coordinates, and the RGB color.