QGIS API Documentation 4.3.0-Master (7c7bd4d7018)
Loading...
Searching...
No Matches
qgsdistanceutils.cpp
Go to the documentation of this file.
1/***************************************************************************
2 qgsdistanceutils.cpp
3 ---------------------
4 begin : June 2026
5 copyright : (C) 2026 by Alexander Bruy
6 email : alexander dot bruy at gmail dot com
7 ***************************************************************************/
8
9/***************************************************************************
10 * *
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the GNU General Public License as published by *
13 * the Free Software Foundation; either version 2 of the License, or *
14 * (at your option) any later version. *
15 * *
16 ***************************************************************************/
17
18#include "qgsdistanceutils.h"
19
20#include <algorithm>
21
22#include "qgsdistancearea.h"
24
25#include <QString>
26#include <queue>
27
28using namespace Qt::StringLiterals;
29
31
32std::vector<QgsDistanceUtils::NeighborResult> QgsDistanceUtils::nearestNeighbors(
33 const QgsPointXY &sourcePoint, const std::vector<std::pair<QgsFeatureId, QgsPointXY>> &targetPoints, const QgsDistanceArea &da, long long k, QgsProcessingFeedback *feedback
34)
35{
36 if ( targetPoints.empty() )
37 {
38 return {};
39 }
40
41 std::vector<QgsDistanceUtils::NeighborResult> result;
42
43 // If k is 0 or greater than total targets, we just calculate and sort all of them
44 if ( k <= 0 || static_cast<size_t>( k ) >= targetPoints.size() )
45 {
46 result.reserve( targetPoints.size() );
47 for ( const auto &target : targetPoints )
48 {
49 if ( feedback && feedback->isCanceled() )
50 {
51 break;
52 }
53
54 double dist = da.measureLine( sourcePoint, target.second );
55 result.push_back( { target.first, dist, target.second } );
56 }
57 std::sort( result.begin(), result.end(), []( const NeighborResult &a, const NeighborResult &b ) { return a.distance < b.distance; } );
58 return result;
59 }
60
61 // If we only need top K, we use a priority queue, sorted from largest to smallest distance
62 auto cmp = []( const NeighborResult &a, const NeighborResult &b ) { return a.distance < b.distance; };
63 std::priority_queue<NeighborResult, std::vector<NeighborResult>, decltype( cmp )> points_queue( cmp );
64
65 for ( const auto &target : targetPoints )
66 {
67 if ( feedback && feedback->isCanceled() )
68 {
69 break;
70 }
71
72 double dist = da.measureLine( sourcePoint, target.second );
73
74 if ( points_queue.size() < static_cast<size_t>( k ) )
75 {
76 points_queue.push( { target.first, dist, target.second } );
77 }
78 else if ( dist < points_queue.top().distance )
79 {
80 points_queue.pop();
81 points_queue.push( { target.first, dist, target.second } );
82 }
83 }
84
85 result.reserve( points_queue.size() );
86 while ( !points_queue.empty() )
87 {
88 result.push_back( points_queue.top() );
89 points_queue.pop();
90 }
91
92 // reverse to return nearest to furthers points
93 std::reverse( result.begin(), result.end() );
94
95 return result;
96}
97
A general purpose distance and area calculator, capable of performing ellipsoid based calculations.
double measureLine(const QVector< QgsPointXY > &points) const
Measures the length of a line with multiple segments.
bool isCanceled() const
Tells whether the operation has been canceled already.
Definition qgsfeedback.h:56
Represents a 2D point.
Definition qgspointxy.h:62
Base class for providing feedback from a processing algorithm.