Fishnet 2.0.1
Framework for Graph-Based Analysis of GIS Vector Data
Loading...
Searching...
No Matches
NearestNeighbours.hpp
Go to the documentation of this file.
1#pragma once
2#include <set>
3#include <ranges>
4#include <fishnet/Vec2D.hpp>
6
7namespace fishnet::geometry {
8
9namespace __impl{
10
11template<math::Number T>
12constexpr Vec2D<T> nearestNeighbourBinarySearch(const Vec2D<T> & query, const std::set<Vec2D<T>,LexicographicOrder> & points, util::Predicate<Vec2D<T>> auto const & predicate = util::TruePredicate{}) noexcept {
13 fishnet::math::DEFAULT_FLOATING_POINT minDistance = std::numeric_limits<fishnet::math::DEFAULT_FLOATING_POINT>::max();
14 Vec2D<T> nearest;
15 if(points.size()==1)
16 return *points.begin();
17 //https://www.codeproject.com/Articles/882739/Simple-Approach-to-Voronoi-Diagrams --> stop computation when x difference is greater than current minimum
18 for( auto it = (points.lower_bound(query)==points.end()?--points.lower_bound(query):points.lower_bound(query)) /*make sure <it> is valid, moving one position back if at the end*/;
19 std::make_reverse_iterator(it) != points.rend() /*make sure <it> does not go past the beginning*/ && fabs(it->x - query.x) < minDistance /* stop early when distance exceeds current minimum*/ ; --it)
20 {
21 const Vec2D<T> & neighbour = *it;
22 if(query.distance(neighbour) < minDistance and neighbour != query and predicate(neighbour)){
23 minDistance = query.distance(neighbour);
24 nearest= neighbour;
25 }
26 }
27 for( auto it = points.upper_bound(query); it != points.end() && fabs(it->x - query.x) < minDistance; ++it){
28 const Vec2D<T> & neighbour = *it;
29 if(query.distance(neighbour) < minDistance and neighbour != query and predicate(neighbour)){
30 minDistance = query.distance(neighbour);
31 nearest = neighbour;
32 }
33 }
34 return nearest;
35}
36
37}
38
47template<math::Number T>
48constexpr Vec2D<T> nearestNeighbour(const Vec2D<T> & query, std::set<Vec2D<T>,LexicographicOrder> const & points) noexcept {
49 return __impl::nearestNeighbourBinarySearch<T>(query,points,[](const auto & e){return true;});
50}
51
61template<math::Number T>
62constexpr std::vector<Vec2D<T>> kNearestNeighbours(const Vec2D<T> & query, std::set<Vec2D<T>,LexicographicOrder> const & points, const size_t k) noexcept {
63 const size_t _k = std::min(k,util::size(points) - 1 ); // make sure k does not exceed the amount of points
64 std::vector<Vec2D<T>> neighbours;
65 neighbours.resize(_k); // default construct k points in the vector
66 for(size_t i = 0; i < _k; i++){
67 auto notYetNeigbourPredicate = [neighbours](const Vec2D<T> & p){return std::ranges::find(neighbours,p) == neighbours.end();}; // predicate to avoid duplicate nearest neighbours in the output list
68 neighbours[i] = __impl::nearestNeighbourBinarySearch(query,points,notYetNeigbourPredicate);
69 }
70 return neighbours;
71}
72
81template<typename T>
82constexpr std::vector<std::pair<Vec2D<T>,std::vector<Vec2D<T>>>> AllKNearestNeighbours(util::forward_range_of<Vec2D<T>> auto const & points, const size_t k) noexcept {
83 std::set<Vec2D<T>,LexicographicOrder> orderedSetOfPoints;
84 std::vector<std::pair<Vec2D<T>,std::vector<Vec2D<T>>>> result;
85 for(const auto & p: points){
86 orderedSetOfPoints.emplace(p);
87 }
88 for( auto & point : orderedSetOfPoints){
89 result.emplace_back(std::make_pair(point,kNearestNeighbours(point,orderedSetOfPoints,k)));
90 }
91 return result;
92}
93}
Implementation of a two-dimensional vector.
Definition Vec2D.hpp:16
Definition CollectionConcepts.hpp:27
Definition BoundingBoxWrapper.hpp:5
constexpr std::vector< Vec2D< T > > kNearestNeighbours(const Vec2D< T > &query, std::set< Vec2D< T >, LexicographicOrder > const &points, const size_t k) noexcept
Compute the k nearest neighours for a query point.
Definition NearestNeighbours.hpp:62
constexpr std::vector< std::pair< Vec2D< T >, std::vector< Vec2D< T > > > > AllKNearestNeighbours(util::forward_range_of< Vec2D< T > > auto const &points, const size_t k) noexcept
Compute the k nearest neighbours for each point.
Definition NearestNeighbours.hpp:82
constexpr Vec2D< T > nearestNeighbour(const Vec2D< T > &query, std::set< Vec2D< T >, LexicographicOrder > const &points) noexcept
Compute the nearest neighbour for a query point.
Definition NearestNeighbours.hpp:48
double DEFAULT_FLOATING_POINT
Definition NumericConcepts.hpp:12
constexpr size_t size(std::ranges::range auto &&range) noexcept
Definition CollectionConcepts.hpp:50
Comparator for lexigraphically-ordering of Vec2D objects Compares first the x-Coordinate and then the...
Definition Vec2D.hpp:195