Ocean
Loading...
Searching...
No Matches
SpatialDistribution.h
Go to the documentation of this file.
1/*
2 * Copyright (c) Meta Platforms, Inc. and affiliates.
3 *
4 * This source code is licensed under the MIT license found in the
5 * LICENSE file in the root directory of this source tree.
6 */
7
8#ifndef META_OCEAN_GEOMETRY_SPATIAL_DISTRIBUTION_H
9#define META_OCEAN_GEOMETRY_SPATIAL_DISTRIBUTION_H
10
12
14
15#include "ocean/math/Box2.h"
16
17#include <algorithm>
18
19namespace Ocean
20{
21
22namespace Geometry
23{
24
25/**
26 * This class implements spatial distribution function for 2D geometric data.
27 * @ingroup geometry
28 */
29class OCEAN_GEOMETRY_EXPORT SpatialDistribution
30{
31 public:
32
33 /**
34 * This class implements a base class for data arrays.
35 */
36 class OCEAN_GEOMETRY_EXPORT Array
37 {
38 public:
39
40 /**
41 * Returns the left position of the distribution area.
42 * @return Left position
43 */
44 inline Scalar left() const;
45
46 /**
47 * Returns the top position of the distribution area.
48 * @return Top position
49 */
50 inline Scalar top() const;
51
52 /**
53 * Returns the width of the distribution area.
54 * @return Area width
55 */
56 inline Scalar width() const;
57
58 /**
59 * Returns the height of the distribution area.
60 * @return Area height
61 */
62 inline Scalar height() const;
63
64 /**
65 * Returns the number of horizontal distribution bins.
66 * @return Number of bins
67 */
68 inline unsigned int horizontalBins() const;
69
70 /**
71 * Returns the number of vertical distribution bins.
72 * @return Number of bins
73 */
74 inline unsigned int verticalBins() const;
75
76 /**
77 * Returns the number of bins this distribution holds.
78 * @return Bin number
79 */
80 inline unsigned int bins() const;
81
82 /**
83 * Returns the bin index for a given position.
84 * Beware: Make sure that the given position is inside the specified range!
85 * @param x Horizontal position, with range [0, width())
86 * @param y Vertical position, with range [0, height())
87 * @return Resulting bin index
88 */
89 inline unsigned int index(const Scalar x, const Scalar y) const;
90
91 /**
92 * Returns the horizontal bin of a given horizontal position.
93 * Beware: The resulting bin can exceed the bin-ranges of the array.<br>
94 * @param x Horizontal position, with range (-infinity, infinity)
95 * @return Horizontal bin, with range (-infinity, infinity)
96 * @see clampedHorizontalBin().
97 */
98 inline int horizontalBin(const Scalar x) const;
99
100 /**
101 * Returns the vertical bin of a given vertical position.
102 * Beware: The resulting bin can exceed the bin-ranges of the array.<br>
103 * @param y Vertical position, with range (-infinity, infinity)
104 * @return Vertical bin, with range (-infinity, infinity)
105 * @see clampedVerticalBin().
106 */
107 inline int verticalBin(const Scalar y) const;
108
109 /**
110 * Returns the horizontal bin of a given horizontal position.
111 * Beware: The resulting bin is clamped into the range [0, number of bins - 1).<br>
112 * @param x Horizontal position, with range (-infinity, infinity)
113 * @return Horizontal bin, with range [0, horizontalBins() - 1]
114 * @see horizontalBin().
115 */
116 inline int clampedHorizontalBin(const Scalar x) const;
117
118 /**
119 * Returns the vertical bin of a given vertical position.
120 * Beware: The resulting bin is clamped into the range [0, number of bins - 1).<br>
121 * @param y Vertical position, with range (-infinity, infinity)
122 * @return Vertical bin, with range [0, verticalBins() - 1]
123 * @see clampedVerticalBin().
124 */
125 inline int clampedVerticalBin(const Scalar y) const;
126
127 /**
128 * Returns whether this object holds a valid distribution.
129 * @return True, if so
130 */
131 inline bool isValid() const;
132
133 /**
134 * Returns whether two Array objects are identical.
135 * @param right The second array object to compare
136 * @return True, if so
137 */
138 inline bool operator==(const Array& right) const;
139
140 /**
141 * Returns whether two Array objects are not identical.
142 * @param right The second array object to compare
143 * @return True, if so
144 */
145 inline bool operator!=(const Array& right) const;
146
147 /**
148 * Returns whether this object holds a valid distribution.
149 * @return True, if so
150 */
151 explicit inline operator bool() const;
152
153 protected:
154
155 /**
156 * Creates an empty array object.
157 */
158 Array() = default;
159
160 /**
161 * Copy constructor.
162 * @param object The array object to be copied
163 */
164 Array(const Array& object) = default;
165
166 /**
167 * Move constructor.
168 * @param object The array object to be moved
169 */
170 inline Array(Array&& object) noexcept;
171
172 /**
173 * Creates a new array object.
174 * @param left The left area position, with range (-infinity, infinity)
175 * @param top The top area position, with range (-infinity, infinity)
176 * @param width The width of the distribution area, with range (0, infinity)
177 * @param height The height of the distribution area, with range (0, infinity)
178 * @param horizontalBins Number of horizontal distribution bins, with range [1, infinity)
179 * @param verticalBins Number of vertical distribution bins, with range [1, infinity)
180 */
181 inline Array(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
182
183 /**
184 * Assign operator.
185 * @param object The object to be assigned
186 * @return Reference to this object
187 */
188 inline Array& operator=(const Array& object);
189
190 /**
191 * Move operator.
192 * @param object The object to be moved
193 * @return Reference to this object
194 */
195 inline Array& operator=(Array&& object) noexcept;
196
197 protected:
198
199 /// Left position of the distribution area.
200 Scalar areaLeft_ = Scalar(0);
201
202 /// Top position of the distribution area.
203 Scalar areaTop_ = Scalar(0);
204
205 /// Width of the distribution area.
206 Scalar areaWidth_ = Scalar(0);
207
208 /// Height of the distribution area.
209 Scalar areaHeight_ = Scalar(0);
210
211 /// Number of horizontal distribution bins.
212 unsigned int horizontalBins_ = 0u;
213
214 /// Number of vertical distribution bins.
215 unsigned int verticalBins_ = 0u;
216
217 /// Horizontal position to bin factor.
218 Scalar horizontalPoint2Bin_ = Scalar(0);
219
220 /// Vertical position to bin factor.
221 Scalar verticalPoint2Bin_ = Scalar(0);
222 };
223
224 /**
225 * This class implements a distribution array.
226 */
227 class OCEAN_GEOMETRY_EXPORT DistributionArray : public Array
228 {
229 public:
230
231 /**
232 * Creates an empty distribution array object.
233 */
234 DistributionArray() = default;
235
236 /**
237 * Copy constructor.
238 * @param object The object to be copied
239 */
240 DistributionArray(const DistributionArray& object) = default;
241
242 /**
243 * Move constructor.
244 * @param object The object to be copied
245 */
246 inline DistributionArray(DistributionArray&& object) noexcept;
247
248 /**
249 * Creates a new distribution array object.
250 * @param left The left area position, with range (-infinity, infinity)
251 * @param top The top area position, with range (-infinity, infinity)
252 * @param width The width of the distribution area, with range (0, infinity)
253 * @param height The height of the distribution area, with range (0, infinity)
254 * @param horizontalBins Number of horizontal distribution bins, with range [1, infinity)
255 * @param verticalBins Number of vertical distribution bins, with range [1, infinity)
256 */
257 inline DistributionArray(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
258
259 /**
260 * Copies a given distribution array and optional copies the indices from the 8-neighborhood of each individual bin to the bin in the center of the neighborhood.
261 * The resulting distribution array can be used to speed-up the search for nearest neighbors if the distribution array is reused several times.<br>
262 * Instead of gathering neighboring indices via indicesNeighborhood9(), each bin contains all indices of the 9 neighborhood already.
263 * @param distributionArray The distribution array to be copied
264 * @param copyNeighborhood8 True, to copy the 8-neighborhood of each individual bin to the bin in the center of the neighborhood; False to create a simple copy of the distribution array
265 * @see hasCopiedNeighborhood8().
266 */
267 DistributionArray(const DistributionArray& distributionArray, const bool copyNeighborhood8);
268
269 /**
270 * Returns the indices of the 8-neighborhood and the specified bin itself.
271 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
272 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
273 * @return Indices of the 9 neighboring bins
274 * @see hasCopiedNeighborhood8().
275 */
276 Indices32 indicesNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const;
277
278 /**
279 * Returns the indices of the 8-neighborhood and the specified bin itself.
280 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
281 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
282 * @param indices Resulting indices of the 9 neighboring bins
283 * @see hasCopiedNeighborhood8().
284 */
285 void indicesNeighborhood9(const unsigned int horizontal, const unsigned int vertical, Indices32& indices) const;
286
287 /**
288 * Returns whether this distribution array contains copies of indices within the 8-neighborhood of each individual bin.
289 * @return True, if so
290 */
291 inline bool hasCopiedNeighborhood8() const;
292
293 /**
294 * Removes all elements form this array.
295 */
296 void clear();
297
298 /**
299 * Returns the distribution indices of a specified bin.
300 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
301 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
302 * @return Specified distribution indices
303 */
304 inline const Indices32& operator()(const unsigned int horizontal, const unsigned int vertical) const;
305
306 /**
307 * Returns the distribution indices of a specified bin.
308 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
309 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
310 * @return Specified distribution indices
311 */
312 inline Indices32& operator()(const unsigned int horizontal, const unsigned int vertical);
313
314 /**
315 * Returns the distribution indices of a specified bin.
316 * The bins are stored in a row aligned order.
317 * @param index The index of the specified bin, with range [0, horizontalBins() * verticalBins() - 1]
318 * @return Specified distribution indices
319 */
320 inline const Indices32& operator[](const unsigned int index) const;
321
322 /**
323 * Returns the distribution indices of a specified bin.
324 * The bins are stored in a row aligned order.
325 * @param index The index of the specified bin, with range [0, horizontalBins() * verticalBins() - 1]
326 * @return Specified distribution indices
327 */
328 inline Indices32& operator[](const unsigned int index);
329
330 /**
331 * Assign operator.
332 * @param object The object to be assigned
333 * @return Reference to this object
334 */
335 inline DistributionArray& operator=(const DistributionArray& object);
336
337 /**
338 * Move operator.
339 * @param object The object to be moved
340 */
341 inline DistributionArray& operator=(DistributionArray&& object) noexcept;
342
343 /**
344 * Returns whether two DistributionArray objects are identical.
345 * @param distributionArray The second array object to compare
346 * @return True, if so
347 */
348 inline bool operator==(const DistributionArray& distributionArray) const;
349
350 /**
351 * Returns whether two DistributionArray objects are not identical.
352 * @param distributionArray The second array object to compare
353 * @return True, if so
354 */
355 inline bool operator!=(const DistributionArray& distributionArray) const;
356
357 private:
358
359 /// Distribution array with point indices.
361
362 /// True, if the array contains copies of indices within the 8-neighborhood of each individual bin; False, if each bin contains the indices of the actual bin only
363 bool hasCopiedNeighborhood8_ = false;
364 };
365
366 /**
367 * This class implements an occupancy array.
368 */
369 class OCEAN_GEOMETRY_EXPORT OccupancyArray : public Array
370 {
371 public:
372
373 /**
374 * Creates an empty distribution array object.
375 */
376 OccupancyArray() = default;
377
378 /**
379 * Copy constructor.
380 * @param object Occupancy array object to be copied
381 */
382 OccupancyArray(const OccupancyArray& object) = default;
383
384 /**
385 * Move constructor.
386 * @param object Occupancy array object to be move
387 */
388 inline OccupancyArray(OccupancyArray&& object) noexcept;
389
390 /**
391 * Creates a new distribution array object.
392 * @param boundingBox The bounding box defining the position and dimension of the area, must be valid
393 * @param horizontalBins Number of horizontal distribution bins, with range [1, infinity)
394 * @param verticalBins Number of vertical distribution bins, with range [1, infinity)
395 * @param allFree True, to set all bins as free; False, to set all bins as occupied
396 */
397 inline OccupancyArray(const Box2& boundingBox, const unsigned int horizontalBins, const unsigned int verticalBins, const bool allFree = true);
398
399 /**
400 * Creates a new distribution array object.
401 * @param left The left area position, with range (-infinity, infinity)
402 * @param top The top area position, with range (-infinity, infinity)
403 * @param width The width of the distribution area, with range (0, infinity)
404 * @param height The height of the distribution area, with range (0, infinity)
405 * @param horizontalBins Number of horizontal distribution bins, with range [1, infinity)
406 * @param verticalBins Number of vertical distribution bins, with range [1, infinity)
407 * @param allFree True, to set all bins as free; False, to set all bins as occupied
408 */
409 inline OccupancyArray(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const bool allFree = true);
410
411 /**
412 * Returns whether at least one bin in the 8-neighborhood or the specified bin itself is occupied.
413 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
414 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
415 * @return True, if so
416 */
417 inline bool isOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const;
418
419 /**
420 * Returns whether at least one bin in the 8-neighborhood or the specified bin itself is occupied.
421 * @param point The point for that the 9-neighborhood bins have to be checked, with range (-infinity, infinity)x(-infinity, infinity)
422 * @return True, if so
423 */
424 inline bool isOccupiedNeighborhood9(const Vector2& point) const;
425
426 /**
427 * Returns whether at least one bin in the 8-neighborhood or the specified bin itself is not occupied.
428 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
429 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
430 * @return True, if so
431 */
432 inline bool isNotOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const;
433
434 /**
435 * Returns whether at least one bin in the 8-neighborhood or the specified bin itself is not occupied.
436 * @param point The point for that the 9-neighborhood bins have to be checked, with range (-infinity, infinity)x(-infinity, infinity)
437 * @return True, if so
438 */
439 inline bool isNotOccupiedNeighborhood9(const Vector2& point) const;
440
441 /**
442 * Returns the number of occupied bins in the 9-neighborhood (so the specified bin is included).
443 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
444 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
445 * @return The number of occupied bins
446 */
447 inline unsigned int countOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const;
448
449 /**
450 * Returns the number of occupied bins.
451 * @return Bin number
452 */
453 inline unsigned int occupiedBins() const;
454
455 /**
456 * Returns the number of free bins.
457 * @return Bin number
458 */
459 inline unsigned int freeBins() const;
460
461 /**
462 * Adds an image point and returns whether the corresponding bin was not occupied before (was free before).
463 * If the point lies outside the array False is returned.<br>
464 * The bin (if valid) which belongs to the given point is occupied after the function returns.
465 * @param point The point to be added, with range (-infinity, infinity)x(-infinity, infinity)
466 * @return True, if so
467 */
468 inline bool addPoint(const Vector2& point);
469
470 /**
471 * Adds an image point and returns whether the occupancy counter of the corresponding bin was equal or below a specified value.
472 * If the point lies outside the array False is returned.<br>
473 * The occupancy counter of the bin (if valid) to which the given point belongs will be incremented.<br>
474 * Beware: This function should not be used in conjunction with any other addPoint(), removePoint() function not leveraging a occupancy counter.
475 * @param point The point to be added, with range (-infinity, infinity)x(-infinity, infinity)
476 * @param maximalOccupancyCounter The maximal occupancy counter the corresponding bin may have to add the point.
477 * @return True, if so
478 */
479 inline bool addPointWithCounter(const Vector2& point, const unsigned int maximalOccupancyCounter);
480
481 /**
482 * Removes an image point and returns whether the corresponding bin was occupied before.
483 * If the point lies outside the array False is returned.<br>
484 * The bin (if valid) which belongs to the given point is free (not occupied) after the function returns.
485 * @param point The point to be removed, with range (-infinity, infinity)x(-infinity, infinity)
486 * @return True, if so
487 */
488 inline bool removePoint(const Vector2& point);
489
490 /**
491 * Resets all occupied bins so that all bins a free afterwards.
492 */
493 inline void reset();
494
495 /**
496 * Adds an image point to this occupancy array.
497 * The bin (if valid) which belongs to the given point is occupied after the function returns.
498 * @param point The point to be added, with range (-infinity, infinity)x(-infinity, infinity)
499 * @return Reference to this object
500 */
501 inline OccupancyArray& operator+=(const Vector2& point);
502
503 /**
504 * Removes an image point from this occupancy array.
505 * The bin (if valid) which belongs to the given point is free (not occupied) after the function returns.
506 * @return Reference to this object
507 */
508 inline OccupancyArray& operator-=(const Vector2& point);
509
510 /**
511 * Returns whether a specified bin is occupied.
512 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
513 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
514 * @return True, if so
515 */
516 inline bool operator()(const unsigned int horizontal, const unsigned int vertical) const;
517
518 /**
519 * Returns whether the bin corresponding to a given point is occupied.
520 * @param point The point for which the bin has to be checked, with range (-infinity, infinity)x(-infinity, infinity)
521 * @return True, if so
522 */
523 inline bool operator()(const Vector2& point) const;
524
525 /**
526 * Returns whether a specified bin is occupied.
527 * @param horizontal The horizontal distribution bin, with range [0, horizontalBins() - 1]
528 * @param vertical The vertical distribution bin, with range [0, verticalBins() - 1]
529 * @return Non-zero, if so
530 */
531 inline unsigned int& operator()(const unsigned int horizontal, const unsigned int vertical);
532
533 /**
534 * Returns whether a specified bin is occupied.
535 * @param index The index of the specified bin, with range [0, horizontalBins() * verticalBins() - 1]
536 * @return True, if so
537 */
538 inline bool operator[](const unsigned int index) const;
539
540 /**
541 * Returns whether a specified bin is occupied.
542 * @param index The index of the specified bin, with range [0, horizontalBins() * verticalBins() - 1]
543 * @return Non-zero, if so
544 */
545 inline unsigned int& operator[](const unsigned int index);
546
547 /**
548 * Assign operator.
549 * @param object Occupancy array object to be assigned
550 * @return Reference to this object
551 */
552 inline OccupancyArray& operator=(const OccupancyArray& object);
553
554 /**
555 * Move operator.
556 * @param object Occupancy array object to be moved
557 * @return Reference to this object
558 */
559 inline OccupancyArray& operator=(OccupancyArray&& object) noexcept;
560
561 /**
562 * Returns whether two OccupancyArray objects are identical.
563 * @param occupancyArray The second array object to compare
564 * @return True, if so
565 */
566 inline bool operator==(const OccupancyArray& occupancyArray) const;
567
568 /**
569 * Returns whether two OccupancyArray objects are not identical.
570 * @param occupancyArray The second array object to compare
571 * @return True, if so
572 */
573 inline bool operator!=(const OccupancyArray& occupancyArray) const;
574
575 private:
576
577 /// Occupancy array.
579 };
580
581 /**
582 * Definition of a class holding an index and a distance.
583 */
584 class OCEAN_GEOMETRY_EXPORT DistanceElement
585 {
586 public:
587
588 /**
589 * Creates a new distance element.
590 * @param index Interest index to be stored
591 * @param candidateIndex Index of the candidate to be stored
592 * @param distance The distance to be stored
593 */
594 inline DistanceElement(const unsigned int index, const unsigned int candidateIndex, const Scalar distance);
595
596 /**
597 * Returns the interest index of this element.
598 * @return Stored index
599 */
600 inline unsigned int index() const;
601
602 /**
603 * Returns the candidate index of this element.
604 * @return Stored candidate index
605 */
606 inline unsigned int candidateIndex() const;
607
608 /**
609 * Returns the distance of this element.
610 * @return Stored distance
611 */
612 inline Scalar distance() const;
613
614 /**
615 * Compares two distance elements.
616 * @param left The left element to compare
617 * @param right The right element to compare
618 * @return True, if the left element has a smaller distance value than the right one
619 */
620 static inline bool compareLeftSmaller(const DistanceElement& left, const DistanceElement& right);
621
622 /**
623 * Compares two distance elements.
624 * @param left The left element to compare
625 * @param right The right element to compare
626 * @return True, if the left element has a higher distance value than the right one
627 */
628 static inline bool compareLeftHigher(const DistanceElement& left, const DistanceElement& right);
629
630 /**
631 * Returns whether the left element holds a higher distance than the right one.
632 * @return True, if so
633 */
634 inline bool operator<(const DistanceElement& element) const;
635
636 private:
637
638 /// Interest index.
639 unsigned int index_ = 0u;
640
641 /// Candidate index.
642 unsigned int candidateIndex_ = 0u;
643
644 /// Distance value.
645 Scalar distance_ = Scalar(-1);
646 };
647
648 /**
649 * Definition of a vector holding distance elements.
650 */
651 typedef std::vector<DistanceElement> DistanceElements;
652
653 public:
654
655 /**
656 * Calculates the ideal number of horizontal and vertical bins for an array if the overall number of bins is known.
657 * This function tries to get bins with almost identical horizontal and vertical size.
658 * @param width The width of the area the array covers, with range [1, infinity)
659 * @param height The height of the area the array covers, with range [1, infinity)
660 * @param numberBins The number of bins that would be perfect, with range [1, infinity)
661 * @param horizontalBins The resulting number of horizontal bins that fit best with the given parameters, with range [minimalHorizontalBins, width]
662 * @param verticalBins The resulting number of vertical bins that fit best with the given parameters, with range [minimalVerticalBins, height]
663 * @param minimalHorizontalBins The minimal number of horizontal bins, with range [1, width]
664 * @param minimalVerticalBins The minimal number of vertical bins, with range [1, height]
665 */
666 static void idealBins(const unsigned int width, const unsigned int height, const size_t numberBins, unsigned int& horizontalBins, unsigned int& verticalBins, const unsigned int minimalHorizontalBins = 2u, const unsigned int minimalVerticalBins = 2u);
667
668 /**
669 * Calculates the ideal number of horizontal and vertical bins for an array if bin elements within a certain distance should be guaranteed to be located in the 9 neighborhood of that bin
670 * This function tries to get bins with almost identical horizontal and vertical size.
671 * @param width The width of the area the array covers, with range [1, infinity)
672 * @param height The height of the area the array covers, with range [1, infinity)
673 * @param distance The distance to other bin elements that should be guaranteed to be located in the 9 neighborhood, with range [1, infinity)
674 * @param horizontalBins The resulting number of horizontal bins that fit best with the given parameters, with range [minimalHorizontalBins, width]
675 * @param verticalBins The resulting number of vertical bins that fit best with the given parameters, with range [minimalVerticalBins, height]
676 * @param minimalHorizontalBins The minimal number of horizontal bins, with range [1, maximalHorizontalBins]
677 * @param minimalVerticalBins The minimal number of vertical bins, with range [1, maximalVerticalBins]
678 * @param maximalHorizontalBins The maximal number of horizontal bins, with range [minimalHorizontalBins, width]
679 * @param maximalVerticalBins The maximal number of vertical bins, with range [minimalVerticalBins, height]
680 */
681 static void idealBinsNeighborhood9(const unsigned int width, const unsigned int height, const Scalar distance, unsigned int& horizontalBins, unsigned int& verticalBins, const unsigned int minimalHorizontalBins = 2u, const unsigned int minimalVerticalBins = 2u, const unsigned int maximalHorizontalBins = 20u, const unsigned int maximalVerticalBins = 20u);
682
683 /**
684 * Distributes the given 2D image points into a spatial array.
685 * The number of used horizontal and vertical bins are calculated automatically.
686 * Instead of creating a 2D array a 1D array is returned with the first n elements for the top bins and the second n elements for the second top bins and so on.<br>
687 * Image points not fitting into the array bins are discarded.<br>
688 * @param imagePoints Image points to be distributed, may be nullptr if number==0
689 * @param number The number of given image points, with range [0, infinity)
690 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
691 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
692 * @param width The width of the area holding the elements, with range (0, infinity)
693 * @param height The height of the area holding the elements, with range (0, infinity)
694 * @param averagePointsPerBin Average number of points per bin, with range [1, infinity)
695 * @param maxHorizontalBins Maximal number of horizontal bins, with range [1, infinity)
696 * @param maxVerticalBins Maximal number of vertical bins, with range [1, infinity)
697 * @param horizontalBins Resulting horizontal bins, with range [1, infinity)
698 * @param verticalBins Resulting vertical bins, with range [1, infinity)
699 * @return Resulting array holding the indices of the distributed image points, will be cleared before usage
700 */
701 static inline DistributionArray distributeToArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int averagePointsPerBin, const unsigned int maxHorizontalBins, const unsigned int maxVerticalBins, unsigned int& horizontalBins, unsigned int& verticalBins);
702
703 /**
704 * Distributes a set of given 2D image points into a spatial array.
705 * Image points not fitting into the array bins are discarded.
706 * @param imagePoints Image points to be distributed, with range (-infinity, infinity)x(-infinity, infinity), may be nullptr if number==0
707 * @param number The number of given image points, with range [0, infinity)
708 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
709 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
710 * @param width The width of the area holding the points, with range (0, infinity)
711 * @param height The height of the area holding the points, with range (0, infinity)
712 * @param horizontalBins Number of horizontal bins to distribute the image points into, with range [1, infinity)
713 * @param verticalBins Number of vertical bins to distribute the image points into, with range [1, infinity)
714 * @return Resulting array holding the indices of the distributed image points
715 */
716 static DistributionArray distributeToArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
717
718 /**
719 * Distributes the given elements into a spatial array.
720 * Elements not fitting into the array bins are discarded.
721 * @param elements The elements (e.g. holding image points) to be distributed
722 * @param number The number of given image points
723 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
724 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
725 * @param width The width of the area holding the elements, with range (0, infinity)
726 * @param height The height of the area holding the elements, with range (0, infinity)
727 * @param horizontalBins Number of horizontal bins to distribute the image points into, with range [1, width]
728 * @param verticalBins Number of vertical bins to distribute the image points into, with range [1, height]
729 * @return Resulting array holding the indices of the distributed elements
730 * @tparam T Data type of the given elements
731 * @tparam tFunction Function pointer type of a function returning the 2D position of any element
732 */
733 template <typename T, const Vector2& (*tFunction)(const T&)>
734 static DistributionArray distributeToArray(const T* elements, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
735
736 /**
737 * Distributes the given 2D image points into a spatial array.
738 * Instead of creating a 2D array a 1D array is returned with the first n elements for the top bins and the second n elements for the second top bins and so on.
739 * Image points not fitting into the array bins are discarded.<br>
740 * @param imagePoints Image points to be distributed
741 * @param number The number of given image points
742 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
743 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
744 * @param width The width of the area holding the points, with range (0, infinity)
745 * @param height The height of the area holding the points, with range (0, infinity)
746 * @param searchDistance Search distance that will be applied (minimal size of each bin)
747 * @return Resulting array holding the indices of the distributed image points
748 * @tparam tMaximalBins Number of maximal bins in each direction (horizontal and vertical), width range [1, infinity)
749 */
750 template <unsigned int tMaximalBins>
751 static inline DistributionArray distributeToArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const Scalar searchDistance);
752
753 /**
754 * Distributes the given 2D image points into a spatial array.
755 * Instead of creating a 2D array a 1D array is returned with the first n elements for the top bins and the second n elements for the second top bins and so on.
756 * Image points not fitting into the array bins are discarded.<br>
757 * @param imagePoints Image points to be distributed, must be valid if the specified number is not zero
758 * @param number The number of given image points, with range [0, infinity)
759 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
760 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
761 * @param width The width of the area holding the points, with range (0, infinity)
762 * @param height The height of the area holding the points, with range (0, infinity)
763 * @param horizontalBins Number of horizontal bins to distribute the image points into, with range [1, width]
764 * @param verticalBins Number of vertical bins to distribute the image points into, with range [1, height]
765 * @return Resulting array holding the indices of the distributed image points
766 */
767 static OccupancyArray createOccupancyArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
768
769 /**
770 * Filters the given 2D image points according to their distance to neighboring image points.
771 * @param imagePoints Image points (e.g. holding image points) to be filtered
772 * @param number The number of given image points
773 * @param width The width of the area holding the points in pixel, with range [1, infinity)
774 * @param height The height of the area holding the points in pixel, with range [1, infinity)
775 * @param distance The distance threshold to be used for filtering
776 * @return Resulting vector holding the indices of the found image points
777 */
778 static Indices32 filterAccordingDistance(const ImagePoint* imagePoints, const size_t number, const unsigned int width, const unsigned int height, const Scalar distance);
779
780 /**
781 * Filters the given 2D candidate points according to the distance to the given image points.
782 * @param imagePoints Image points for that the filtered candidate points have to be found
783 * @param numberImagePoints Number of image points
784 * @param candidatePoints Candidate points that will be filtered
785 * @param numberCandidatePoints Number of candidate points
786 * @param width The width of the area holding the image points, with range [1, infinity)
787 * @param height The height of the area holding the image points, with range [1, infinity)
788 * @param filterDistance Distance threshold that define whether a candidate point belongs to one image point
789 * @param filterSize Number of candidate points that can belong to one image point
790 * @param filteredIndices Resulting indices of the filtered candidate points, if defined
791 * @param filteredCandidates Resulting filtered candidate points, if defined
792 */
793 static void filterCandidatePoint(const ImagePoint* imagePoints, const size_t numberImagePoints, const ImagePoint* candidatePoints, const size_t numberCandidatePoints, const unsigned int width, const unsigned int height, const Scalar filterDistance, const unsigned int filterSize, Indices32* filteredIndices = nullptr, ImagePoints* filteredCandidates = nullptr);
794
795 /**
796 * Sorts the given 2D image points according to their minimal distance to neighboring image points.
797 * Points with higher distances will be returned before points with lower distances.
798 * @param imagePoints Image points (e.g. holding image points) to be sorted
799 * @param number The number of given image points
800 * @param minimalDistanceFirst True, to sort minimal distance to the front
801 * @return Resulting vector holding the indices and distances of the sorted image points
802 */
803 static DistanceElements sortAccordingDistance(const ImagePoint* imagePoints, const size_t number, const bool minimalDistanceFirst);
804
805 /**
806 * Sorts the given 2D image points according to their minimal distance to neighboring image points.
807 * Points with higher distances will be returned before points with lower distances.
808 * This function first distributes all points to array bins to speed up the computation.<br>
809 * @param imagePoints Image points (e.g. holding image points) to be sorted
810 * @param number The number of given image points
811 * @param width The width of the area holding the image points in pixel, with range [1, infinity)
812 * @param height The height of the area holding the image points in pixel, with range [1, infinity)
813 * @param bins Number of bins in each direction used for image point distribution
814 * @param minimalDistanceFirst True, to sort minimal distance to the front
815 * @return Resulting vector holding the indices and distances of the sorted image points
816 */
817 static DistanceElements sortAccordingDistance(const ImagePoint* imagePoints, const size_t number, const unsigned int width, const unsigned int height, const unsigned int bins, const bool minimalDistanceFirst);
818
819 /**
820 * Determines the minimal square distance for one given 2D image point to all other points in the same set.
821 * This function uses an already create point distribution to speed up the computation.<br>
822 * Candidates for nearest neighbors are all points lying in the 9-bin-neighborhood of a point, thus the result technically is an approximation and not correct in any case.
823 * @param imagePoints Image points to calculate the distances for
824 * @param numberImagePoints Number of given image points
825 * @param index The index of the image point to find the minimal square distance for, with range [0, numberImagePoints)
826 * @param distributionImagePoints Already created distribution array of the image points
827 * @return Resulting square distances calculated for the given image point
828 */
829 static Scalar determineMinimalSqrDistance(const ImagePoint* imagePoints, const size_t numberImagePoints, const unsigned int index, const DistributionArray& distributionImagePoints);
830
831 /**
832 * Determines the minimal square distances for each given 2D image point to all other points in the same set.
833 * This function first distributes all points to array bins to speed up the computation.<br>
834 * Candidates for nearest neighbors are all points lying in the 9-bin-neighborhood of a point, thus the result technically is an approximation and not correct in any case.
835 * @param imagePoints Image points to calculate the distances for, may be nullptr if numberImagePoints==0
836 * @param numberImagePoints Number of given image points, with range [0, infinity)
837 * @param width The width of the area holding the image points in pixel, with range [1, infinity)
838 * @param height The height of the area holding the image points in pixel, with range [1, infinity)
839 * @param bins Number of bins in each direction used for image point distribution, with range [1, infinity)
840 * @param sqrDistances Resulting square distances calculated for each given image point, make sure that this buffer holds enough space
841 */
842 static void determineMinimalSqrDistances(const ImagePoint* imagePoints, const size_t numberImagePoints, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar* sqrDistances);
843
844 /**
845 * Determines the minimal square distances for each given 2D image point to another given set of 2D image points.
846 * This function first distributes all points to array bins to speed up the computation.<br>
847 * Candidates for nearest neighbors are all points lying in the 9-bin-neighborhood of a point, thus the result technically is an approximation and not correct in any case.
848 * @param imagePoints Image points to calculate the distances for, may be nullptr if numberImagePoints==0
849 * @param numberImagePoints Number of given image points, with range [0, infinity)
850 * @param candidates Image points being candidates as nearest neighbors for the given image points
851 * @param numberCandidates Number of given candidates
852 * @param width The width of the area holding the image points in pixel, with range [1, infinity)
853 * @param height The height of the area holding the image points in pixel, with range [1, infinity)
854 * @param bins Number of bins in each direction used for image point distribution
855 * @param sqrDistances Resulting square distances calculated for each given image point, make sure that this buffer holds enough space
856 */
857 static void determineMinimalSqrDistances(const ImagePoint* imagePoints, const size_t numberImagePoints, const ImagePoint* candidates, const size_t numberCandidates, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar* sqrDistances);
858
859 /**
860 * Determines the minimal square distances for each given image point to another given set of image points.
861 * Candidates for nearest neighbors are all points lying in the 9-bin-neighborhood of a point, thus the result technically is an approximation and not correct in any case.
862 * @param imagePoints Image points to calculate the distances for, may be nullptr if numberImagePoints==0
863 * @param numberImagePoints Number of given image points, with range [0, infinity)
864 * @param candidates Image points being candidates as nearest neighbors for the given image points
865 * @param numberCandidates Number of given candidates
866 * @param distributionCandidates Already created distribution array of the candidates
867 * @param sqrDistances Resulting square distances calculated for each given element, make sure that this buffer holds enough space
868 * @param candidateIndices Optional resulting indices of the candidate with minimal distance, make sure that this buffer holds enough space (if defined)
869 */
870 static void determineMinimalSqrDistances(const ImagePoint* imagePoints, const size_t numberImagePoints, const ImagePoint* candidates, const size_t numberCandidates, const DistributionArray& distributionCandidates, Scalar* sqrDistances, unsigned int* candidateIndices = nullptr);
871
872 /**
873 * Determines the minimal square distances for each specified image point inside their neighborhood.
874 * This function first distributes all image points to array bins to speed up the computation.<br>
875 * Candidates for nearest neighbors are all points lying in the 9-bin-neighborhood of a point, thus the result technically is an approximation and not correct in any case.
876 * @param imagePoints Image points holding the entire set, may be nullptr if numberImagePoints==0
877 * @param numberImagePoints Number of given image points, with range [0, infinity)
878 * @param interestIndices Indices of all interest image points to calculate the minimal distance for
879 * @param numberInterestIndices Number of given interest indices
880 * @param width The width of the area holding the elements in pixel, with range [1, infinity)
881 * @param height The height of the area holding the elements in pixel, with range [1, infinity)
882 * @param bins Number of bins in each direction used for element distribution
883 * @param sqrDistances Resulting square distances calculated for each given interest index, make sure that this buffer holds enough space
884 */
885 static void determineMinimalSqrDistances(const ImagePoint* imagePoints, const size_t numberImagePoints, const unsigned int* interestIndices, const size_t numberInterestIndices, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar* sqrDistances);
886
887 /**
888 * Determines all candidate points for a given image point (interest point) lying inside a specified circle around the interest point.
889 * @param imagePoint The interest image point to find the neighboring candidate points for, with range (-infinity, infinity)x(-infinity, infinity)
890 * @param candidatePoints Candidate points to find the neighbors in
891 * @param numberCandidatePoints Number of given candidate points
892 * @param radius The radius specifying the circle around the interest point, with range [0, infinity)
893 * @param distributionCandidatePoints Already created distribution array of the candidate points
894 * @return Resulting indices of all neighbors out the candidate set lying within the specified circle.
895 */
896 static Indices32 determineNeighbors(const ImagePoint& imagePoint, const ImagePoint* candidatePoints, const size_t numberCandidatePoints, const Scalar radius, const DistributionArray& distributionCandidatePoints);
897
898 /**
899 * Determines the nearest image point between an interest point and a set of given image point lying inside a specified circle around the interest point.
900 * @param interestPoint The interest image point for which the nearest neighbor will be determined, with range (-infinity, infinity)x(-infinity, infinity)
901 * @param imagePoints The set of image points from which the nearest neighbor will be determined
902 * @param numberImagePoints Number of given image points, with range [0, infinity)
903 * @param radius The radius specifying the circle around the interest point, with range [0, infinity)
904 * @param distributionImagePoints Already created distribution array of the image points
905 * @param sqrDistance Optional resulting square distance of the nearest image point, if any
906 * @return Resulting index of the nearest neighbor image point, -1 if no image point lies within the specified radius
907 */
908 static Index32 determineNearestNeighbor(const ImagePoint& interestPoint, const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar radius, const DistributionArray& distributionImagePoints, Scalar* sqrDistance = nullptr);
909
910 /**
911 * Distributes the given image points into an array of specified size and returns (at most) one point from each bin.
912 * @param imagePoints Image points to be distributed and filtered, may be nullptr if numberImagePoints==0
913 * @param numberImagePoints Number of given image points, with range [0, infinity)
914 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
915 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
916 * @param width The width of the area holding the elements, with range (0, infinity)
917 * @param height The height of the area holding the elements, with range (0, infinity)
918 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
919 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
920 * @return Resulting filtered elements
921 */
922 static inline ImagePoints distributeAndFilter(const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
923
924 /**
925 * Distributes the given image points into an array of specified size and returns as much points as requested by first selecting the first point from each bin, then the second point from each bin, and so on.
926 * @param imagePoints Image points to be distributed and filtered, may be nullptr if numberImagePoints==0
927 * @param numberImagePoints Number of given image points, with range [0, infinity)
928 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
929 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
930 * @param width The width of the area holding the elements, with range (0, infinity)
931 * @param height The height of the area holding the elements, with range (0, infinity)
932 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
933 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
934 * @param size The number of requested feature points, with range [0, numberImagePoints]
935 * @return Resulting filtered elements
936 */
937 static ImagePoints distributeAndFilter(const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const size_t size);
938
939 /**
940 * Distributes the given image points into an array of specified size and returns (at most) one point index from each bin.
941 * The resulting indices can be used to filter the actual set of image points.<br>
942 * @param imagePoints Image points to be distributed and filtered, may be nullptr if numberImagePoints==0
943 * @param numberImagePoints Number of given image points, with range [0, infinity)
944 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
945 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
946 * @param width The width of the area holding the elements, with range (0, infinity)
947 * @param height The height of the area holding the elements, with range (0, infinity)
948 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
949 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
950 * @return Resulting indices of the filtered elements
951 * @tparam TIndex The data type of the indices (e.g., may be Index32 or Index64)
952 */
953 template <typename TIndex>
954 static inline std::vector<TIndex> distributeAndFilterIndices(const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
955
956 /**
957 * Distributes the given elements into an array of specified size and returns (at most) one element from each bin.
958 * @param elements The elements to be distributed and filtered, may be nullptr if numberImagePoints==0
959 * @param numberElements Number of given elements, with range [0, infinity)
960 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
961 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
962 * @param width The width of the area holding the elements, with range (0, infinity)
963 * @param height The height of the area holding the elements, with range (0, infinity)
964 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
965 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
966 * @return Resulting filtered elements
967 * @tparam T The data type of the elements to be distributed
968 * @tparam tFunction The function pointer that returns the 2D position of each element
969 */
970 template <typename T, Vector2 (*tFunction)(const T&)>
971 static std::vector<T> distributeAndFilter(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
972
973 /**
974 * Distributes the given elements into an array of specified size but returns as much elements per bin necessary to reach the specified amount of desired elements.
975 * This function should be used whenever the given elements are not distributed equally while a specified amount of feature points is desired.
976 * The function applies several filter iterations until the desired number of elements is reached.<br>
977 * After the first iteration each bin will contain at most one element, after the second iteration at most two elements, and so on.
978 * @param elements The elements to be distributed and filtered, may be nullptr if numberImagePoints==0
979 * @param numberElements Number of given elements, with range [0, infinity)
980 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
981 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
982 * @param width The width of the area holding the elements, with range (0, infinity)
983 * @param height The height of the area holding the elements, with range (0, infinity)
984 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
985 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
986 * @param numberDesiredFilteredElements The desired number of filtered elements, with range [1, numberElements]
987 * @param indices Optional resulting indices of the selected keypoints, if defined indices will be pushed at the back.
988 * @return Resulting filtered elements
989 * @tparam T The data type of the elements to be distributed
990 * @tparam tFunction The function pointer that returns the 2D position of each element
991 */
992 template <typename T, Vector2 (*tFunction)(const T&)>
993 static std::vector<T> distributeAndFilter(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const size_t numberDesiredFilteredElements, Indices32 *indices = nullptr);
994
995 /**
996 * Distributes the given elements into an array of specified size and returns (at most) one point index from each bin.
997 * The resulting indices can be used to filter the actual set of image points.<br>
998 * @param elements The elements to be distributed and filtered, may be nullptr if numberImagePoints==0
999 * @param numberElements Number of given elements, with range [0, infinity)
1000 * @param left Horizontal position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
1001 * @param top Vertical position of the area, may be 0 for e.g. an entire image, with range (-infinity, infinity)
1002 * @param width The width of the area holding the elements, with range (0, infinity)
1003 * @param height The height of the area holding the elements, with range (0, infinity)
1004 * @param horizontalBins Number of horizontal bins to be used for distribution, with range [1, infinity)
1005 * @param verticalBins Number of vertical bins to be used for distribution, with range [1, infinity)
1006 * @return Resulting indices of the filtered elements
1007 * @tparam T The data type of the elements to be distributed
1008 * @tparam TIndex The data type of the indices (e.g., may be Index32 or Index64)
1009 * @tparam tFunction The function pointer that returns the 2D position of each element
1010 */
1011 template <typename T, typename TIndex, Vector2 (*tFunction)(const T&)>
1012 static std::vector<TIndex> distributeAndFilterIndices(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins);
1013
1014 protected:
1015
1016 /**
1017 * This function simply returns the given object (actually a copy of the object).
1018 * @param value The value to be returned
1019 * @return The given value
1020 * @tparam T The data type of the value
1021 */
1022 template <typename T>
1023 static inline T identity(const T& value);
1024};
1025
1026inline SpatialDistribution::Array::Array(Array&& object) noexcept :
1027 areaLeft_(object.areaLeft_),
1028 areaTop_(object.areaTop_),
1029 areaWidth_(object.areaWidth_),
1030 areaHeight_(object.areaHeight_),
1031 horizontalBins_(object.horizontalBins_),
1032 verticalBins_(object.verticalBins_),
1033 horizontalPoint2Bin_(object.horizontalPoint2Bin_),
1034 verticalPoint2Bin_(object.verticalPoint2Bin_)
1035{
1036 object.areaLeft_ = Scalar(0);
1037 object.areaTop_ = Scalar(0);
1038 object.areaWidth_ = Scalar(0);
1039 object.areaHeight_ = Scalar(0);
1040 object.horizontalBins_ = 0u;
1041 object.verticalBins_ = 0u;
1042 object.horizontalPoint2Bin_ = Scalar(0);
1043 object.verticalPoint2Bin_ = Scalar(0);
1044}
1045
1046inline SpatialDistribution::Array::Array(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins) :
1047 areaLeft_(left),
1048 areaTop_(top),
1049 areaWidth_(width),
1050 areaHeight_(height),
1051 horizontalBins_(horizontalBins),
1052 verticalBins_(verticalBins),
1053 horizontalPoint2Bin_(width > Numeric::eps() ? (Scalar(horizontalBins) / (Scalar(width) + Numeric::eps())) : Scalar(0)),
1054 verticalPoint2Bin_(height > Numeric::eps() ? (Scalar(verticalBins) / (Scalar(height) + Numeric::eps())) : Scalar(0))
1055{
1056 ocean_assert(width > Numeric::eps() && height > Numeric::eps());
1057}
1058
1060{
1061 return areaLeft_;
1062}
1063
1065{
1066 return areaTop_;
1067}
1068
1070{
1071 return areaWidth_;
1072}
1073
1075{
1076 return areaHeight_;
1077}
1078
1080{
1081 return horizontalBins_;
1082}
1083
1085{
1086 return verticalBins_;
1087}
1088
1089inline unsigned int SpatialDistribution::Array::bins() const
1090{
1091 return horizontalBins_ * verticalBins_;
1092}
1093
1094inline unsigned int SpatialDistribution::Array::index(const Scalar x, const Scalar y) const
1095{
1096 const int xBin = horizontalBin(x);
1097 const int yBin = verticalBin(y);
1098
1099 ocean_assert(xBin >= 0 && xBin < int(horizontalBins_));
1100 ocean_assert(yBin >= 0 && yBin < int(verticalBins_));
1101
1102 return yBin * horizontalBins_ + xBin;
1103}
1104
1106{
1107 // for positive values we could avoid to use floor(), however for negative values we e.g., need -0.2 to be -1
1108 return int(Numeric::floor((x - areaLeft_) * horizontalPoint2Bin_));
1109}
1110
1112{
1113 // for positive values we could avoid to use floor(), however for negative values we e.g., need -0.2 to be -1
1114 return int(Numeric::floor((y - areaTop_) * verticalPoint2Bin_));
1115}
1116
1118{
1119 ocean_assert(isValid());
1120 return minmax<int>(0, horizontalBin(x), horizontalBins_ - 1);
1121}
1122
1124{
1125 ocean_assert(isValid());
1126 return minmax<int>(0, verticalBin(y), verticalBins_ - 1);
1127}
1128
1130{
1131 return horizontalBins_ != 0u && verticalBins_ != 0u;
1132}
1133
1134inline bool SpatialDistribution::Array::operator==(const Array& right) const
1135{
1136 return areaLeft_ == right.areaLeft_
1137 && areaTop_ == right.areaTop_
1138 && areaWidth_ == right.areaWidth_
1139 && areaHeight_ == right.areaHeight_
1140 && horizontalBins_ == right.horizontalBins_
1141 && verticalBins_ == right.verticalBins_
1142 && horizontalPoint2Bin_ == right.horizontalPoint2Bin_
1143 && verticalPoint2Bin_ == right.verticalPoint2Bin_;
1144}
1145
1146inline bool SpatialDistribution::Array::operator!=(const Array& right) const
1147{
1148 return !(*this == right);
1149}
1150
1151inline SpatialDistribution::Array::operator bool() const
1152{
1153 return isValid();
1154}
1155
1157{
1158 if (this != &object)
1159 {
1160 areaLeft_ = object.areaLeft_;
1161 areaTop_ = object.areaTop_;
1162 areaWidth_ = object.areaWidth_;
1163 areaHeight_ = object.areaHeight_;
1164 horizontalBins_ = object.horizontalBins_;
1165 verticalBins_ = object.verticalBins_;
1166 horizontalPoint2Bin_ = object.horizontalPoint2Bin_;
1167 verticalPoint2Bin_ = object.verticalPoint2Bin_;
1168 }
1169
1170 return *this;
1171}
1172
1174{
1175 if (this != &object)
1176 {
1177 areaLeft_ = object.areaLeft_;
1178 areaTop_ = object.areaTop_;
1179 areaWidth_ = object.areaWidth_;
1180 areaHeight_ = object.areaHeight_;
1181 horizontalBins_ = object.horizontalBins_;
1182 verticalBins_ = object.verticalBins_;
1183 horizontalPoint2Bin_ = object.horizontalPoint2Bin_;
1184 verticalPoint2Bin_ = object.verticalPoint2Bin_;
1185
1186 object.areaLeft_ = Scalar(0);
1187 object.areaTop_ = Scalar(0);
1188 object.areaWidth_ = Scalar(0);
1189 object.areaHeight_ = Scalar(0);
1190 object.horizontalBins_ = 0u;
1191 object.verticalBins_ = 0u;
1192 object.horizontalPoint2Bin_ = Scalar(0);
1193 object.verticalPoint2Bin_ = Scalar(0);
1194 }
1195
1196 return *this;
1197}
1198
1200 Array(object),
1201 indexGroups_(std::move(object.indexGroups_)),
1202 hasCopiedNeighborhood8_(object.hasCopiedNeighborhood8_)
1203{
1204 object = DistributionArray();
1205}
1206
1207inline SpatialDistribution::DistributionArray::DistributionArray(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins) :
1208 Array(left, top, width, height, horizontalBins, verticalBins),
1209 indexGroups_(horizontalBins * verticalBins),
1210 hasCopiedNeighborhood8_(false)
1211{
1212 // nothing to do here
1213}
1214
1216{
1217 return hasCopiedNeighborhood8_;
1218}
1219
1220inline const Indices32& SpatialDistribution::DistributionArray::operator()(const unsigned int horizontal, const unsigned int vertical) const
1221{
1222 ocean_assert(horizontal < horizontalBins_);
1223 ocean_assert(vertical < verticalBins_);
1224
1225 return indexGroups_[vertical * horizontalBins_ + horizontal];
1226}
1227
1228inline Indices32& SpatialDistribution::DistributionArray::operator()(const unsigned int horizontal, const unsigned int vertical)
1229{
1230 ocean_assert(horizontal < horizontalBins_);
1231 ocean_assert(vertical < verticalBins_);
1232
1233 return indexGroups_[vertical * horizontalBins_ + horizontal];
1234}
1235
1236inline const Indices32& SpatialDistribution::DistributionArray::operator[](const unsigned int index) const
1237{
1238 ocean_assert(index < horizontalBins_ * verticalBins_);
1239 return indexGroups_[index];
1240}
1241
1243{
1244 ocean_assert(index < horizontalBins_ * verticalBins_);
1245 return indexGroups_[index];
1246}
1247
1249{
1250 Array::operator=((Array&)object);
1251 indexGroups_ = object.indexGroups_;
1252 hasCopiedNeighborhood8_ = object.hasCopiedNeighborhood8_;
1253
1254 return *this;
1255}
1256
1258{
1259 if (this != &object)
1260 {
1261 Array::operator=(std::move((Array&)object));
1262 indexGroups_ = std::move(object.indexGroups_);
1263 hasCopiedNeighborhood8_ = object.hasCopiedNeighborhood8_;
1264
1265 object.hasCopiedNeighborhood8_ = false;
1266 }
1267
1268 return *this;
1269}
1270
1272{
1273 if (!Array::operator==(distributionArray))
1274 {
1275 return false;
1276 }
1277
1278 return indexGroups_ == distributionArray.indexGroups_ && hasCopiedNeighborhood8_ && distributionArray.hasCopiedNeighborhood8_;
1279}
1280
1282{
1283 return !(*this == distributionArray);
1284}
1285
1287 Array(std::move((Array&)object)),
1288 occupancy_(std::move(object.occupancy_))
1289{
1290 // nothing to do here
1291}
1292
1293inline SpatialDistribution::OccupancyArray::OccupancyArray(const Box2& boundingBox, const unsigned int horizontalBins, const unsigned int verticalBins, const bool allFree) :
1294 Array(boundingBox.left(), boundingBox.top(), boundingBox.width(), boundingBox.height(), horizontalBins, verticalBins),
1295 occupancy_(horizontalBins * verticalBins, allFree ? 0u : 1u)
1296{
1297 ocean_assert(NumericT<unsigned int>::isInsideValueRange(uint64_t(horizontalBins) * uint64_t(verticalBins)));
1298}
1299
1300inline SpatialDistribution::OccupancyArray::OccupancyArray(const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const bool allFree) :
1301 Array(left, top, width, height, horizontalBins, verticalBins),
1302 occupancy_(horizontalBins * verticalBins, allFree ? 0u : 1u)
1303{
1304 ocean_assert(NumericT<unsigned int>::isInsideValueRange(uint64_t(horizontalBins) * uint64_t(verticalBins)));
1305}
1306
1307inline unsigned int SpatialDistribution::OccupancyArray::countOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
1308{
1309 ocean_assert(horizontal < horizontalBins_);
1310 ocean_assert(vertical < verticalBins_);
1311
1312 unsigned int number = 0u;
1313
1314 for (unsigned int y = max(0, int(vertical) - 1); y < min(vertical + 2u, verticalBins_); ++y)
1315 {
1316 for (unsigned int x = max(0, int(horizontal) - 1); x < min(horizontal + 2u, horizontalBins_); ++x)
1317 {
1318 if ((*this)(x, y))
1319 {
1320 number++;
1321 }
1322 }
1323 }
1324
1325 return number;
1326}
1327
1328inline bool SpatialDistribution::OccupancyArray::isOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
1329{
1330 ocean_assert(horizontal < horizontalBins_);
1331 ocean_assert(vertical < verticalBins_);
1332
1333 for (unsigned int y = max(0, int(vertical) - 1); y < min(vertical + 2u, verticalBins_); ++y)
1334 {
1335 for (unsigned int x = max(0, int(horizontal) - 1); x < min(horizontal + 2u, horizontalBins_); ++x)
1336 {
1337 if ((*this)(x, y))
1338 {
1339 return true;
1340 }
1341 }
1342 }
1343
1344 return false;
1345}
1346
1348{
1349 const unsigned int horizontal = horizontalBin(point.x());
1350 const unsigned int vertical = verticalBin(point.y());
1351
1352 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1353 {
1354 for (unsigned int y = max(0, int(vertical) - 1); y < min(vertical + 2u, verticalBins_); ++y)
1355 {
1356 for (unsigned int x = max(0, int(horizontal) - 1); x < min(horizontal + 2u, horizontalBins_); ++x)
1357 {
1358 if ((*this)(x, y))
1359 {
1360 return true;
1361 }
1362 }
1363 }
1364 }
1365
1366 return false;
1367}
1368
1369inline bool SpatialDistribution::OccupancyArray::isNotOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
1370{
1371 ocean_assert(horizontal < horizontalBins_);
1372 ocean_assert(vertical < verticalBins_);
1373
1374 for (unsigned int y = max(0, int(vertical) - 1); y < min(vertical + 2u, verticalBins_); ++y)
1375 {
1376 for (unsigned int x = max(0, int(horizontal) - 1); x < min(horizontal + 2u, horizontalBins_); ++x)
1377 {
1378 if (!(*this)(x, y))
1379 {
1380 return true;
1381 }
1382 }
1383 }
1384
1385 return false;
1386}
1387
1389{
1390 const unsigned int horizontal = horizontalBin(point.x());
1391 const unsigned int vertical = verticalBin(point.y());
1392
1393 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1394 {
1395 for (unsigned int y = max(0, int(vertical) - 1); y < min(vertical + 2u, verticalBins_); ++y)
1396 {
1397 for (unsigned int x = max(0, int(horizontal) - 1); x < min(horizontal + 2u, horizontalBins_); ++x)
1398 {
1399 if (!(*this)(x, y))
1400 {
1401 return true;
1402 }
1403 }
1404 }
1405 }
1406
1407 return false;
1408}
1409
1411{
1412 unsigned int count = 0u;
1413
1414 for (const Index32& bin : occupancy_)
1415 {
1416 if (bin != 0u)
1417 {
1418 ++count;
1419 }
1420 }
1421
1422 return count;
1423}
1424
1426{
1427 unsigned int count = 0u;
1428
1429 for (const Index32& bin : occupancy_)
1430 {
1431 if (bin == 0u)
1432 {
1433 ++count;
1434 }
1435 }
1436
1437 return count;
1438}
1439
1441{
1442 const unsigned int horizontal = (unsigned int)(horizontalBin(point.x()));
1443 const unsigned int vertical = (unsigned int)(verticalBin(point.y()));
1444
1445 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1446 {
1447 const unsigned int index = vertical * horizontalBins_ + horizontal;
1448
1449 if (!occupancy_[index])
1450 {
1451 occupancy_[index] = 1u;
1452 return true;
1453 }
1454 }
1455
1456 return false;
1457}
1458
1459inline bool SpatialDistribution::OccupancyArray::addPointWithCounter(const Vector2& point, const unsigned int maximalOccupancyCounter)
1460{
1461 const unsigned int horizontal = (unsigned int)(horizontalBin(point.x()));
1462 const unsigned int vertical = (unsigned int)(verticalBin(point.y()));
1463
1464 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1465 {
1466 const unsigned int index = vertical * horizontalBins_ + horizontal;
1467
1468 if (occupancy_[index] <= maximalOccupancyCounter)
1469 {
1470 occupancy_[index]++;
1471 return true;
1472 }
1473 }
1474
1475 return false;
1476}
1477
1479{
1480 const unsigned int horizontal = (unsigned int)(horizontalBin(point.x()));
1481 const unsigned int vertical = (unsigned int)(verticalBin(point.y()));
1482
1483 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1484 {
1485 const unsigned int index = vertical * horizontalBins_ + horizontal;
1486
1487 if (occupancy_[index])
1488 {
1489 occupancy_[index] = 0u;
1490 return true;
1491 }
1492 }
1493
1494 return false;
1495}
1496
1498{
1499 for (size_t n = 0; n < occupancy_.size(); ++n)
1500 {
1501 occupancy_[n] = 0u;
1502 }
1503}
1504
1506{
1507 const unsigned int horizontal = (unsigned int)(horizontalBin(point.x()));
1508 const unsigned int vertical = (unsigned int)(verticalBin(point.y()));
1509
1510 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1511 {
1512 occupancy_[vertical * horizontalBins_ + horizontal] = 1u;
1513 }
1514
1515 return *this;
1516}
1517
1519{
1520 const unsigned int horizontal = (unsigned int)(horizontalBin(point.x()));
1521 const unsigned int vertical = (unsigned int)(verticalBin(point.y()));
1522
1523 if (horizontal < horizontalBins_ && vertical < verticalBins_)
1524 {
1525 occupancy_[vertical * horizontalBins_ + horizontal] = 0u;
1526 }
1527
1528 return *this;
1529}
1530
1531inline bool SpatialDistribution::OccupancyArray::operator()(const unsigned int horizontal, const unsigned int vertical) const
1532{
1533 ocean_assert(horizontal < horizontalBins_);
1534 ocean_assert(vertical < verticalBins_);
1535
1536 return occupancy_[vertical * horizontalBins_ + horizontal] != 0u;
1537}
1538
1539inline unsigned int& SpatialDistribution::OccupancyArray::operator()(const unsigned int horizontal, const unsigned int vertical)
1540{
1541 ocean_assert(horizontal < horizontalBins_);
1542 ocean_assert(vertical < verticalBins_);
1543
1544 return occupancy_[vertical * horizontalBins_ + horizontal];
1545}
1546
1548{
1549 const unsigned int xBin = horizontalBin(point.x());
1550 const unsigned int yBin = verticalBin(point.y());
1551
1552 return xBin < horizontalBins_ && yBin < horizontalBins_ && occupancy_[yBin * horizontalBins_ + xBin] != 0u;
1553}
1554
1555inline bool SpatialDistribution::OccupancyArray::operator[](const unsigned int index) const
1556{
1557 ocean_assert(index < horizontalBins_ * verticalBins_);
1558 return occupancy_[index] != 0u;
1559}
1560
1561inline unsigned int& SpatialDistribution::OccupancyArray::operator[](const unsigned int index)
1562{
1563 ocean_assert(index < horizontalBins_ * verticalBins_);
1564 return occupancy_[index];
1565}
1566
1568{
1569 Array::operator=((Array&)object);
1570 occupancy_ = object.occupancy_;
1571
1572 return *this;
1573}
1574
1576{
1577 if (this != &object)
1578 {
1579 Array::operator=(std::move((Array&)object));
1580 occupancy_ = std::move(object.occupancy_);
1581 }
1582
1583 return *this;
1584}
1585
1587{
1588 if (!Array::operator==(occupancyArray))
1589 {
1590 return false;
1591 }
1592
1593 return occupancy_ == occupancyArray.occupancy_;
1594}
1595
1597{
1598 return !(*this == occupancyArray);
1599}
1600
1601inline SpatialDistribution::DistanceElement::DistanceElement(const unsigned int index, const unsigned int candidateIndex, const Scalar distance) :
1602 index_(index),
1603 candidateIndex_(candidateIndex),
1604 distance_(distance)
1605{
1606 // nothing to do here
1607}
1608
1610{
1611 return index_;
1612}
1613
1615{
1616 return candidateIndex_;
1617}
1618
1620{
1621 return distance_;
1622}
1623
1625{
1626 return left.distance_ < right.distance_;
1627}
1628
1630{
1631 return left.distance_ > right.distance_;
1632}
1633
1635{
1636 // ** TODO** this mismatch between comparison operators should be fixed
1637
1638 return distance_ > element.distance_;
1639}
1640
1641template <unsigned int tMaximalBins>
1642inline SpatialDistribution::DistributionArray SpatialDistribution::distributeToArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const Scalar searchDistance)
1643{
1644 static_assert(tMaximalBins > 0u, "Invalid maximal bin parameter!");
1645
1646 const unsigned int horizontalBins = min(tMaximalBins, (unsigned int)Numeric::ceil(width / max(searchDistance, Scalar(2))));
1647 const unsigned int verticalBins = min(tMaximalBins, (unsigned int)Numeric::ceil(height / max(searchDistance, Scalar(2))));
1648
1649 return distributeToArray(imagePoints, number, left, top, width, height, horizontalBins, verticalBins);
1650}
1651
1652template <typename T, const Vector2& (*tFunction)(const T&)>
1653SpatialDistribution::DistributionArray SpatialDistribution::distributeToArray(const T* elements, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
1654{
1655 ocean_assert(elements);
1656 ocean_assert(width > 0 && height > 0);
1657
1658 ocean_assert(horizontalBins > 0);
1659 ocean_assert(verticalBins > 0);
1660
1661 ocean_assert(Scalar(horizontalBins) <= width);
1662 ocean_assert(Scalar(verticalBins) <= width);
1663
1664 // reserve enough array elements
1665 DistributionArray indexArray(left, top, width, height, horizontalBins, verticalBins);
1666
1667 for (size_t n = 0; n < number; ++n)
1668 {
1669 const Vector2& point = tFunction(*elements);
1670
1671 const unsigned int horizontal = (unsigned int)(indexArray.horizontalBin(point.x()));
1672 const unsigned int vertical = (unsigned int)(indexArray.verticalBin(point.y()));
1673
1674 // discard points with negative bin value or bin value larger than the smallest allowed one (due to unsigned int negative values are discarded as well)
1675 if (horizontal < indexArray.horizontalBins() && vertical < indexArray.verticalBins())
1676 {
1677 indexArray(horizontal, vertical).push_back((unsigned int)n);
1678 }
1679
1680 ++elements;
1681 }
1682
1683 return indexArray;
1684}
1685
1686inline SpatialDistribution::DistributionArray SpatialDistribution::distributeToArray(const ImagePoint* imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int averagePointsPerBin, const unsigned int maxHorizontalBins, const unsigned int maxVerticalBins, unsigned int& horizontalBins, unsigned int& verticalBins)
1687{
1688 ocean_assert(imagePoints || number == 0);
1689
1690 ocean_assert(width > 0 && height > 0);
1691 ocean_assert(averagePointsPerBin > 0);
1692
1693 ocean_assert(maxHorizontalBins >= 1u);
1694 ocean_assert(maxVerticalBins >= 1u);
1695
1696 if (number == 0)
1697 {
1698 return DistributionArray(left, top, width, height, horizontalBins, verticalBins);
1699 }
1700
1701 /**
1702 * averagePointsPerBin * horizontalBins * verticalBins = number
1703 * horizontalBins / verticalBins = width / height
1704 */
1705
1706 const Scalar sqr = max(Scalar(1), (Scalar(number) * width) / (Scalar(averagePointsPerBin) * height));
1707
1708 horizontalBins = min(maxHorizontalBins, max(1u, (unsigned int)(Numeric::sqrt(sqr))));
1709 verticalBins = min(maxVerticalBins, max(1u, (unsigned int)(Scalar(horizontalBins) * height / width)));
1710
1711 return distributeToArray(imagePoints, number, left, top, width, height, horizontalBins, verticalBins);
1712}
1713
1714inline ImagePoints SpatialDistribution::distributeAndFilter(const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
1715{
1716 return distributeAndFilter<ImagePoint, &SpatialDistribution::identity>(imagePoints, numberImagePoints, left, top, width, height, horizontalBins, verticalBins);
1717}
1718
1719template <typename TIndex>
1720inline std::vector<TIndex> SpatialDistribution::distributeAndFilterIndices(const ImagePoint* imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
1721{
1722 return distributeAndFilterIndices<ImagePoint, TIndex, &SpatialDistribution::identity>(imagePoints, numberImagePoints, left, top, width, height, horizontalBins, verticalBins);
1723}
1724
1725template <typename T, Vector2 (*tFunction)(const T&)>
1726typename std::vector<T> SpatialDistribution::distributeAndFilter(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
1727{
1728 ocean_assert(elements || numberElements == 0);
1729 ocean_assert(width >= 0 && height >= 0);
1730 ocean_assert(horizontalBins >= 1u && verticalBins >= 1u);
1731
1732 if (numberElements == 0)
1733 {
1734 return std::vector<T>();
1735 }
1736
1737 OccupancyArray occupancyArray(left, top, width, height, horizontalBins, verticalBins);
1738
1739 const size_t bins = occupancyArray.bins();
1740
1741 std::vector<T> result;
1742 result.reserve(bins);
1743
1744 for (size_t n = 0; n < numberElements && result.size() < bins; ++n)
1745 {
1746 if (occupancyArray.addPoint(tFunction(elements[n])))
1747 {
1748 result.push_back(elements[n]);
1749 }
1750 }
1751
1752 return result;
1753}
1754
1755template <typename T, Vector2 (*tFunction)(const T&)>
1756typename std::vector<T> SpatialDistribution::distributeAndFilter(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const size_t numberDesiredFilteredElements, Indices32* indices)
1757{
1758 ocean_assert(elements != nullptr || numberElements == 0);
1759 ocean_assert(width >= 0 && height >= 0);
1760 ocean_assert(horizontalBins >= 1u && verticalBins >= 1u);
1761 ocean_assert(numberDesiredFilteredElements <= numberElements);
1762
1763 if (numberElements == 0 || numberDesiredFilteredElements == 0)
1764 {
1765 return std::vector<T>();
1766 }
1767
1768 OccupancyArray occupancyArray(left, top, width, height, horizontalBins, verticalBins);
1769
1770 std::vector<unsigned char> usedElements(numberElements, 0u);
1771
1772 const size_t bins = occupancyArray.bins();
1773
1774 std::vector<T> result;
1775 result.reserve(bins);
1776
1777 unsigned int filterIteration = 0u;
1778
1779 while (result.size() < numberDesiredFilteredElements && filterIteration < (unsigned int)numberDesiredFilteredElements)
1780 {
1781 for (size_t n = 0; n < numberElements && result.size() < numberDesiredFilteredElements; ++n)
1782 {
1783 if (usedElements[n] == 0u && occupancyArray.addPointWithCounter(tFunction(elements[n]), filterIteration))
1784 {
1785 result.push_back(elements[n]);
1786 usedElements[n] = 1u;
1787 }
1788 }
1789
1790 filterIteration++;
1791 }
1792
1793 if (indices)
1794 {
1795 for (size_t n = 0; n < numberElements; ++n)
1796 {
1797 if(usedElements[n])
1798 {
1799 indices->push_back(Index32(n));
1800 }
1801 }
1802 }
1803
1804 return result;
1805}
1806
1807template <typename T, typename TIndex, Vector2 (*tFunction)(const T&)>
1808typename std::vector<TIndex> SpatialDistribution::distributeAndFilterIndices(const T* elements, const size_t numberElements, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
1809{
1810 ocean_assert(elements || numberElements == 0);
1811 ocean_assert(width >= 0 && height >= 0);
1812 ocean_assert(horizontalBins >= 1u && verticalBins >= 1u);
1813
1814 if (numberElements == 0)
1815 {
1816 return std::vector<TIndex>();
1817 }
1818
1819 ocean_assert((unsigned long long)(numberElements) <= (unsigned long long)(NumericT<TIndex>::maxValue()));
1820
1821 OccupancyArray occupancyArray(left, top, width, height, horizontalBins, verticalBins);
1822
1823 const size_t bins = occupancyArray.bins();
1824
1825 std::vector<TIndex> result;
1826 result.reserve(bins);
1827
1828 for (size_t n = 0; n < numberElements && result.size() < bins; ++n)
1829 {
1830 if (occupancyArray.addPoint(tFunction(elements[n])))
1831 {
1832 result.push_back(TIndex(n));
1833 }
1834 }
1835
1836 return result;
1837}
1838
1839template <typename T>
1840inline T SpatialDistribution::identity(const T& value)
1841{
1842 return value;
1843}
1844
1845}
1846
1847}
1848
1849#endif // META_OCEAN_GEOMETRY_SPATIAL_DISTRIBUTION_H
This class implements a base class for data arrays.
Definition SpatialDistribution.h:37
unsigned int horizontalBins() const
Returns the number of horizontal distribution bins.
Definition SpatialDistribution.h:1079
Scalar width() const
Returns the width of the distribution area.
Definition SpatialDistribution.h:1069
int horizontalBin(const Scalar x) const
Returns the horizontal bin of a given horizontal position.
Definition SpatialDistribution.h:1105
int verticalBin(const Scalar y) const
Returns the vertical bin of a given vertical position.
Definition SpatialDistribution.h:1111
Scalar horizontalPoint2Bin_
Horizontal position to bin factor.
Definition SpatialDistribution.h:218
Array & operator=(const Array &object)
Assign operator.
Definition SpatialDistribution.h:1156
Scalar areaTop_
Top position of the distribution area.
Definition SpatialDistribution.h:203
Scalar top() const
Returns the top position of the distribution area.
Definition SpatialDistribution.h:1064
unsigned int verticalBins() const
Returns the number of vertical distribution bins.
Definition SpatialDistribution.h:1084
int clampedVerticalBin(const Scalar y) const
Returns the vertical bin of a given vertical position.
Definition SpatialDistribution.h:1123
Scalar areaLeft_
Left position of the distribution area.
Definition SpatialDistribution.h:200
Scalar areaHeight_
Height of the distribution area.
Definition SpatialDistribution.h:209
Array()=default
Creates an empty array object.
int clampedHorizontalBin(const Scalar x) const
Returns the horizontal bin of a given horizontal position.
Definition SpatialDistribution.h:1117
bool isValid() const
Returns whether this object holds a valid distribution.
Definition SpatialDistribution.h:1129
Scalar height() const
Returns the height of the distribution area.
Definition SpatialDistribution.h:1074
Scalar verticalPoint2Bin_
Vertical position to bin factor.
Definition SpatialDistribution.h:221
bool operator==(const Array &right) const
Returns whether two Array objects are identical.
Definition SpatialDistribution.h:1134
bool operator!=(const Array &right) const
Returns whether two Array objects are not identical.
Definition SpatialDistribution.h:1146
Scalar areaWidth_
Width of the distribution area.
Definition SpatialDistribution.h:206
unsigned int verticalBins_
Number of vertical distribution bins.
Definition SpatialDistribution.h:215
Array(const Array &object)=default
Copy constructor.
unsigned int horizontalBins_
Number of horizontal distribution bins.
Definition SpatialDistribution.h:212
Scalar left() const
Returns the left position of the distribution area.
Definition SpatialDistribution.h:1059
unsigned int index(const Scalar x, const Scalar y) const
Returns the bin index for a given position.
Definition SpatialDistribution.h:1094
unsigned int bins() const
Returns the number of bins this distribution holds.
Definition SpatialDistribution.h:1089
Definition of a class holding an index and a distance.
Definition SpatialDistribution.h:585
Scalar distance_
Distance value.
Definition SpatialDistribution.h:645
unsigned int candidateIndex() const
Returns the candidate index of this element.
Definition SpatialDistribution.h:1614
static bool compareLeftSmaller(const DistanceElement &left, const DistanceElement &right)
Compares two distance elements.
Definition SpatialDistribution.h:1624
unsigned int index() const
Returns the interest index of this element.
Definition SpatialDistribution.h:1609
static bool compareLeftHigher(const DistanceElement &left, const DistanceElement &right)
Compares two distance elements.
Definition SpatialDistribution.h:1629
DistanceElement(const unsigned int index, const unsigned int candidateIndex, const Scalar distance)
Creates a new distance element.
Definition SpatialDistribution.h:1601
bool operator<(const DistanceElement &element) const
Returns whether the left element holds a higher distance than the right one.
Definition SpatialDistribution.h:1634
Scalar distance() const
Returns the distance of this element.
Definition SpatialDistribution.h:1619
This class implements a distribution array.
Definition SpatialDistribution.h:228
DistributionArray()=default
Creates an empty distribution array object.
bool hasCopiedNeighborhood8() const
Returns whether this distribution array contains copies of indices within the 8-neighborhood of each ...
Definition SpatialDistribution.h:1215
DistributionArray & operator=(const DistributionArray &object)
Assign operator.
Definition SpatialDistribution.h:1248
bool hasCopiedNeighborhood8_
True, if the array contains copies of indices within the 8-neighborhood of each individual bin; False...
Definition SpatialDistribution.h:363
void clear()
Removes all elements form this array.
DistributionArray(const DistributionArray &object)=default
Copy constructor.
const Indices32 & operator()(const unsigned int horizontal, const unsigned int vertical) const
Returns the distribution indices of a specified bin.
Definition SpatialDistribution.h:1220
IndexGroups32 indexGroups_
Distribution array with point indices.
Definition SpatialDistribution.h:360
const Indices32 & operator[](const unsigned int index) const
Returns the distribution indices of a specified bin.
Definition SpatialDistribution.h:1236
DistributionArray(const DistributionArray &distributionArray, const bool copyNeighborhood8)
Copies a given distribution array and optional copies the indices from the 8-neighborhood of each ind...
bool operator!=(const DistributionArray &distributionArray) const
Returns whether two DistributionArray objects are not identical.
Definition SpatialDistribution.h:1281
bool operator==(const DistributionArray &distributionArray) const
Returns whether two DistributionArray objects are identical.
Definition SpatialDistribution.h:1271
void indicesNeighborhood9(const unsigned int horizontal, const unsigned int vertical, Indices32 &indices) const
Returns the indices of the 8-neighborhood and the specified bin itself.
Indices32 indicesNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
Returns the indices of the 8-neighborhood and the specified bin itself.
This class implements an occupancy array.
Definition SpatialDistribution.h:370
OccupancyArray & operator+=(const Vector2 &point)
Adds an image point to this occupancy array.
Definition SpatialDistribution.h:1505
bool operator!=(const OccupancyArray &occupancyArray) const
Returns whether two OccupancyArray objects are not identical.
Definition SpatialDistribution.h:1596
unsigned int freeBins() const
Returns the number of free bins.
Definition SpatialDistribution.h:1425
bool isNotOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
Returns whether at least one bin in the 8-neighborhood or the specified bin itself is not occupied.
Definition SpatialDistribution.h:1369
OccupancyArray & operator-=(const Vector2 &point)
Removes an image point from this occupancy array.
Definition SpatialDistribution.h:1518
unsigned int occupiedBins() const
Returns the number of occupied bins.
Definition SpatialDistribution.h:1410
unsigned int countOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
Returns the number of occupied bins in the 9-neighborhood (so the specified bin is included).
Definition SpatialDistribution.h:1307
OccupancyArray()=default
Creates an empty distribution array object.
OccupancyArray & operator=(const OccupancyArray &object)
Assign operator.
Definition SpatialDistribution.h:1567
bool isOccupiedNeighborhood9(const unsigned int horizontal, const unsigned int vertical) const
Returns whether at least one bin in the 8-neighborhood or the specified bin itself is occupied.
Definition SpatialDistribution.h:1328
void reset()
Resets all occupied bins so that all bins a free afterwards.
Definition SpatialDistribution.h:1497
bool removePoint(const Vector2 &point)
Removes an image point and returns whether the corresponding bin was occupied before.
Definition SpatialDistribution.h:1478
bool addPointWithCounter(const Vector2 &point, const unsigned int maximalOccupancyCounter)
Adds an image point and returns whether the occupancy counter of the corresponding bin was equal or b...
Definition SpatialDistribution.h:1459
bool addPoint(const Vector2 &point)
Adds an image point and returns whether the corresponding bin was not occupied before (was free befor...
Definition SpatialDistribution.h:1440
OccupancyArray(const OccupancyArray &object)=default
Copy constructor.
bool operator()(const unsigned int horizontal, const unsigned int vertical) const
Returns whether a specified bin is occupied.
Definition SpatialDistribution.h:1531
bool operator==(const OccupancyArray &occupancyArray) const
Returns whether two OccupancyArray objects are identical.
Definition SpatialDistribution.h:1586
Indices32 occupancy_
Occupancy array.
Definition SpatialDistribution.h:578
bool operator[](const unsigned int index) const
Returns whether a specified bin is occupied.
Definition SpatialDistribution.h:1555
This class implements spatial distribution function for 2D geometric data.
Definition SpatialDistribution.h:30
static void determineMinimalSqrDistances(const ImagePoint *imagePoints, const size_t numberImagePoints, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar *sqrDistances)
Determines the minimal square distances for each given 2D image point to all other points in the same...
static Index32 determineNearestNeighbor(const ImagePoint &interestPoint, const ImagePoint *imagePoints, const size_t numberImagePoints, const Scalar radius, const DistributionArray &distributionImagePoints, Scalar *sqrDistance=nullptr)
Determines the nearest image point between an interest point and a set of given image point lying ins...
static DistributionArray distributeToArray(const ImagePoint *imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int averagePointsPerBin, const unsigned int maxHorizontalBins, const unsigned int maxVerticalBins, unsigned int &horizontalBins, unsigned int &verticalBins)
Distributes the given 2D image points into a spatial array.
Definition SpatialDistribution.h:1686
static ImagePoints distributeAndFilter(const ImagePoint *imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins, const size_t size)
Distributes the given image points into an array of specified size and returns as much points as requ...
static OccupancyArray createOccupancyArray(const ImagePoint *imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
Distributes the given 2D image points into a spatial array.
static void idealBins(const unsigned int width, const unsigned int height, const size_t numberBins, unsigned int &horizontalBins, unsigned int &verticalBins, const unsigned int minimalHorizontalBins=2u, const unsigned int minimalVerticalBins=2u)
Calculates the ideal number of horizontal and vertical bins for an array if the overall number of bin...
static DistributionArray distributeToArray(const ImagePoint *imagePoints, const size_t number, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
Distributes a set of given 2D image points into a spatial array.
static Indices32 filterAccordingDistance(const ImagePoint *imagePoints, const size_t number, const unsigned int width, const unsigned int height, const Scalar distance)
Filters the given 2D image points according to their distance to neighboring image points.
std::vector< DistanceElement > DistanceElements
Definition of a vector holding distance elements.
Definition SpatialDistribution.h:651
static void determineMinimalSqrDistances(const ImagePoint *imagePoints, const size_t numberImagePoints, const ImagePoint *candidates, const size_t numberCandidates, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar *sqrDistances)
Determines the minimal square distances for each given 2D image point to another given set of 2D imag...
static DistanceElements sortAccordingDistance(const ImagePoint *imagePoints, const size_t number, const unsigned int width, const unsigned int height, const unsigned int bins, const bool minimalDistanceFirst)
Sorts the given 2D image points according to their minimal distance to neighboring image points.
static std::vector< TIndex > distributeAndFilterIndices(const ImagePoint *imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
Distributes the given image points into an array of specified size and returns (at most) one point in...
Definition SpatialDistribution.h:1720
static void determineMinimalSqrDistances(const ImagePoint *imagePoints, const size_t numberImagePoints, const ImagePoint *candidates, const size_t numberCandidates, const DistributionArray &distributionCandidates, Scalar *sqrDistances, unsigned int *candidateIndices=nullptr)
Determines the minimal square distances for each given image point to another given set of image poin...
static Scalar determineMinimalSqrDistance(const ImagePoint *imagePoints, const size_t numberImagePoints, const unsigned int index, const DistributionArray &distributionImagePoints)
Determines the minimal square distance for one given 2D image point to all other points in the same s...
static DistanceElements sortAccordingDistance(const ImagePoint *imagePoints, const size_t number, const bool minimalDistanceFirst)
Sorts the given 2D image points according to their minimal distance to neighboring image points.
static Indices32 determineNeighbors(const ImagePoint &imagePoint, const ImagePoint *candidatePoints, const size_t numberCandidatePoints, const Scalar radius, const DistributionArray &distributionCandidatePoints)
Determines all candidate points for a given image point (interest point) lying inside a specified cir...
static void idealBinsNeighborhood9(const unsigned int width, const unsigned int height, const Scalar distance, unsigned int &horizontalBins, unsigned int &verticalBins, const unsigned int minimalHorizontalBins=2u, const unsigned int minimalVerticalBins=2u, const unsigned int maximalHorizontalBins=20u, const unsigned int maximalVerticalBins=20u)
Calculates the ideal number of horizontal and vertical bins for an array if bin elements within a cer...
static T identity(const T &value)
This function simply returns the given object (actually a copy of the object).
Definition SpatialDistribution.h:1840
static ImagePoints distributeAndFilter(const ImagePoint *imagePoints, const size_t numberImagePoints, const Scalar left, const Scalar top, const Scalar width, const Scalar height, const unsigned int horizontalBins, const unsigned int verticalBins)
Distributes the given image points into an array of specified size and returns (at most) one point fr...
Definition SpatialDistribution.h:1714
static void filterCandidatePoint(const ImagePoint *imagePoints, const size_t numberImagePoints, const ImagePoint *candidatePoints, const size_t numberCandidatePoints, const unsigned int width, const unsigned int height, const Scalar filterDistance, const unsigned int filterSize, Indices32 *filteredIndices=nullptr, ImagePoints *filteredCandidates=nullptr)
Filters the given 2D candidate points according to the distance to the given image points.
static void determineMinimalSqrDistances(const ImagePoint *imagePoints, const size_t numberImagePoints, const unsigned int *interestIndices, const size_t numberInterestIndices, const unsigned int width, const unsigned int height, const unsigned int bins, Scalar *sqrDistances)
Determines the minimal square distances for each specified image point inside their neighborhood.
This class provides basic numeric functionalities.
Definition Numeric.h:57
static T sqrt(const T value)
Returns the square root of a given value.
Definition Numeric.h:1533
static constexpr T eps()
Returns a small epsilon.
static T floor(const T value)
Returns the largest integer value that is not greater than the given value.
Definition Numeric.h:2026
static T ceil(const T value)
Returns the smallest integer value that is not less than the given value.
Definition Numeric.h:1988
const T & x() const noexcept
Returns the x value.
Definition Vector2.h:710
const T & y() const noexcept
Returns the y value.
Definition Vector2.h:722
std::vector< Indices32 > IndexGroups32
Definition of a vector holding 32 bit indices, so we have groups of indices.
Definition Base.h:102
std::vector< Index32 > Indices32
Definition of a vector holding 32 bit index values.
Definition Base.h:96
unsigned int sqr(const char value)
Returns the square value of a given value.
Definition base/Utilities.h:1029
uint32_t Index32
Definition of a 32 bit index value.
Definition Base.h:84
std::vector< ImagePoint > ImagePoints
Definition of a vector holding 2D image points.
Definition geometry/Geometry.h:123
float Scalar
Definition of a scalar type.
Definition Math.h:129
The namespace covering the entire Ocean framework.
Definition Accessor.h:15