QGroundControl
Ground Control Station for MAVLink Drones
Loading...
Searching...
No Matches
MapMarkerGrouping.cc
Go to the documentation of this file.
1#include "MapMarkerGrouping.h"
2
3#include <cmath>
4#include <limits>
5#include <utility>
6
7#include <QtCore/QHash>
8
10 : QObject(parent)
11{}
12
13QList<int> MapMarkerGrouping::representatives(const QList<QPointF>& points, double distance)
14{
15 QList<int> result;
16 result.reserve(points.size());
17
18 // Representatives bucketed by distance-sized cells: only the 3x3 neighborhood can be in range
19 QHash<std::pair<qint64, qint64>, QList<int>> cells;
20 const double distanceSquared = distance * distance;
21
22 for (qsizetype i = 0; i < points.size(); i++) {
23 const QPointF& point = points[i];
24 const int index = static_cast<int>(i);
25 if ((distance <= 0.0) || !std::isfinite(point.x()) || !std::isfinite(point.y())) {
26 result.append(index);
27 continue;
28 }
29
30 const qint64 cellX = static_cast<qint64>(std::floor(point.x() / distance));
31 const qint64 cellY = static_cast<qint64>(std::floor(point.y() / distance));
32 int closest = -1;
33 double closestDistanceSquared = std::numeric_limits<double>::infinity();
34 for (qint64 x = cellX - 1; x <= cellX + 1; x++) {
35 for (qint64 y = cellY - 1; y <= cellY + 1; y++) {
36 for (const int representative : cells.value({x, y})) {
37 const QPointF delta = point - points[representative];
38 const double candidate = QPointF::dotProduct(delta, delta);
39 if ((candidate <= distanceSquared) &&
40 ((candidate < closestDistanceSquared) ||
41 ((candidate == closestDistanceSquared) && (representative < closest)))) {
42 closest = representative;
43 closestDistanceSquared = candidate;
44 }
45 }
46 }
47 }
48
49 if (closest >= 0) {
50 result.append(closest);
51 } else {
52 result.append(index);
53 cells[{cellX, cellY}].append(index);
54 }
55 }
56
57 return result;
58}
static Q_INVOKABLE QList< int > representatives(const QList< QPointF > &points, double distance)
MapMarkerGrouping(QObject *parent=nullptr)