From 547d7a5f23e2f2a06ff053d2ce7927a914d7fdb0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 3 Dec 2020 21:12:41 +0100 Subject: [PATCH] Fix the POI search algorithm (At least so, that it does not trigger the rtree assert. The whole RectC logic has to be fixed to properly handle poles/dateline "overflows") --- src/common/rectc.cpp | 17 +++++++++++++++++ src/common/rectc.h | 1 + src/data/poi.cpp | 41 +++++++++++++++++++++-------------------- 3 files changed, 39 insertions(+), 20 deletions(-) diff --git a/src/common/rectc.cpp b/src/common/rectc.cpp index 9cd42daf..fa651115 100644 --- a/src/common/rectc.cpp +++ b/src/common/rectc.cpp @@ -1,3 +1,4 @@ +#include #include "wgs84.h" #include "rectc.h" @@ -6,6 +7,16 @@ #define MIN_LON deg2rad(-180.0) #define MAX_LON deg2rad(180.0) +static inline double WLON(double lon) +{ + return remainder(lon, 360.0); +} + +static inline double LLAT(double lat) +{ + return (lat < 0.0) ? qMax(lat, -90.0) : qMin(lat, 90.0); +} + RectC::RectC(const Coordinates ¢er, double radius) { double radDist = radius / WGS84_RADIUS; @@ -151,6 +162,12 @@ RectC RectC::united(const Coordinates &c) const return RectC(Coordinates(l, t), Coordinates(r, b)); } +RectC RectC::adjusted(double lon1, double lat1, double lon2, double lat2) const +{ + return RectC(Coordinates(WLON(_tl.lon() + lon1), LLAT(_tl.lat() + lat1)), + Coordinates(WLON(_br.lon() + lon2), LLAT(_br.lat() + lat2))); +} + #ifndef QT_NO_DEBUG QDebug operator<<(QDebug dbg, const RectC &rect) { diff --git a/src/common/rectc.h b/src/common/rectc.h index abdbf4b2..f10191b9 100644 --- a/src/common/rectc.h +++ b/src/common/rectc.h @@ -40,6 +40,7 @@ public: RectC &operator&=(const RectC &r) {*this = *this & r; return *this;} RectC united(const Coordinates &c) const; + RectC adjusted(double lon1, double lat1, double lon2, double lat2) const; bool intersects(const RectC &r) const {return (right() >= r.left() && bottom() <= r.top() && left() <= r.right() diff --git a/src/data/poi.cpp b/src/data/poi.cpp index 7d16afa5..d535e7e1 100644 --- a/src/data/poi.cpp +++ b/src/data/poi.cpp @@ -80,12 +80,25 @@ void POI::search(const RectC &rect, QSet &set) const { qreal min[2], max[2]; - min[0] = rect.topLeft().lon(); - min[1] = rect.bottomRight().lat(); - max[0] = rect.bottomRight().lon(); - max[1] = rect.topLeft().lat(); + if (rect.left() > rect.right()) { + min[0] = rect.topLeft().lon(); + min[1] = rect.bottomRight().lat(); + max[0] = 180.0; + max[1] = rect.topLeft().lat(); + _tree.Search(min, max, cb, &set); - _tree.Search(min, max, cb, &set); + min[0] = -180.0; + min[1] = rect.bottomRight().lat(); + max[0] = rect.bottomRight().lon(); + max[1] = rect.topLeft().lat(); + _tree.Search(min, max, cb, &set); + } else { + min[0] = rect.topLeft().lon(); + min[1] = rect.bottomRight().lat(); + max[0] = rect.bottomRight().lon(); + max[1] = rect.topLeft().lat(); + _tree.Search(min, max, cb, &set); + } } QList POI::points(const Path &path) const @@ -130,16 +143,10 @@ QList POI::points(const Waypoint &point) const { QList ret; QSet set; - qreal min[2], max[2]; QSet::const_iterator it; RectC br(point.coordinates(), _radius); - min[0] = br.topLeft().lon(); - min[1] = br.bottomRight().lat(); - max[0] = br.bottomRight().lon(); - max[1] = br.topLeft().lat(); - - _tree.Search(min, max, cb, &set); + search(br, set); for (it = set.constBegin(); it != set.constEnd(); ++it) ret.append(_data.at(*it)); @@ -150,18 +157,12 @@ QList POI::points(const Waypoint &point) const QList POI::points(const RectC &rect) const { QList ret; - qreal min[2], max[2]; QSet set; QSet::const_iterator it; double offset = rad2deg(_radius / WGS84_RADIUS); - - min[0] = rect.topLeft().lon() - offset; - min[1] = rect.bottomRight().lat() - offset; - max[0] = rect.bottomRight().lon() + offset; - max[1] = rect.topLeft().lat() + offset; - - _tree.Search(min, max, cb, &set); + RectC br(rect.adjusted(-offset, offset, offset, -offset)); + search(br, set); for (it = set.constBegin(); it != set.constEnd(); ++it) ret.append(_data.at(*it));