diff --git a/src/GUI/pathitem.cpp b/src/GUI/pathitem.cpp index 39dee9f2..ad99b3c3 100644 --- a/src/GUI/pathitem.cpp +++ b/src/GUI/pathitem.cpp @@ -51,11 +51,14 @@ void PathItem::updatePainterPath(Map *map) unsigned n = qAbs(c1.lon() - c2.lon()); if (n) { + double prev = c1.lon(); + GreatCircle gc(c1, c2); + if (n > 180) n = n - 180; - double prev = c1.lon(); + for (unsigned j = 1; j <= n * 60; j++) { - Coordinates c(GreatCircle::pointAt(c1, c2, j/(n * 60.0))); + Coordinates c(gc.pointAt(j/(n * 60.0))); double current = c.lon(); if (fabs(current - prev) > 180.0) _painterPath.moveTo(map->ll2xy(c)); @@ -172,9 +175,10 @@ QPointF PathItem::position(qreal x) const p1 = _path.at(mid-1).distance(); p2 = _path.at(mid).distance(); } - if ((unsigned)qAbs(c1.lon() - c2.lon())) - return _map->ll2xy(GreatCircle::pointAt(c1, c2, (x - p1) / (p2 - p1))); - else { + if ((unsigned)qAbs(c1.lon() - c2.lon())) { + GreatCircle gc(c1, c2); + return _map->ll2xy(gc.pointAt((x - p1) / (p2 - p1))); + } else { QLineF l(_map->ll2xy(c1), _map->ll2xy(c2)); return l.pointAt((x - p1) / (p2 - p1)); } diff --git a/src/common/greatcircle.cpp b/src/common/greatcircle.cpp index dda5a6e2..607dc23d 100644 --- a/src/common/greatcircle.cpp +++ b/src/common/greatcircle.cpp @@ -1,23 +1,26 @@ #include "greatcircle.h" -Coordinates GreatCircle::pointAt(const Coordinates &c1, const Coordinates &c2, - double f) +GreatCircle::GreatCircle(const Coordinates &c1, const Coordinates &c2) { - double lat1 = deg2rad(c1.lat()); - double lon1 = deg2rad(c1.lon()); - double lat2 = deg2rad(c2.lat()); - double lon2 = deg2rad(c2.lon()); + _lat1 = deg2rad(c1.lat()); + _lon1 = deg2rad(c1.lon()); + _lat2 = deg2rad(c2.lat()); + _lon2 = deg2rad(c2.lon()); - double cosLat1 = cos(lat1); - double cosLat2 = cos(lat2); - double d = 2 * asin(sqrt(pow((sin((lat1 - lat2) / 2)), 2) + cosLat1 - * cosLat2 * pow(sin((lon1 - lon2) / 2), 2))); - double sinD = sin(d); - double A = sin((1.0-f)*d) / sinD; - double B = sin(f*d) / sinD; - double x = A * cosLat1 * cos(lon1) + B * cosLat2 * cos(lon2); - double y = A * cosLat1 * sin(lon1) + B * cosLat2 * sin(lon2); - double z = A * sin(lat1) + B * sin(lat2); + _cosLat1 = cos(_lat1); + _cosLat2 = cos(_lat2); + _d = 2 * asin(sqrt(pow((sin((_lat1 - _lat2) / 2)), 2) + _cosLat1 + * _cosLat2 * pow(sin((_lon1 - _lon2) / 2), 2))); + _sinD = sin(_d); +} + +Coordinates GreatCircle::pointAt(double f) const +{ + double A = sin((1.0 - f) * _d) / _sinD; + double B = sin(f*_d) / _sinD; + double x = A * _cosLat1 * cos(_lon1) + B * _cosLat2 * cos(_lon2); + double y = A * _cosLat1 * sin(_lon1) + B * _cosLat2 * sin(_lon2); + double z = A * sin(_lat1) + B * sin(_lat2); return Coordinates(rad2deg(atan2(y, x)), rad2deg(atan2(z, sqrt(x*x + y*y)))); } diff --git a/src/common/greatcircle.h b/src/common/greatcircle.h index e71b3fa1..5ed1db98 100644 --- a/src/common/greatcircle.h +++ b/src/common/greatcircle.h @@ -3,9 +3,18 @@ #include "coordinates.h" -namespace GreatCircle +class GreatCircle { - Coordinates pointAt(const Coordinates &c1, const Coordinates &c2, double f); -} +public: + GreatCircle(const Coordinates &c1, const Coordinates &c2); + + Coordinates pointAt(double f) const; + +private: + double _lat1, _lon1, _lat2, _lon2; + double _cosLat1, _cosLat2; + double _d; + double _sinD; +}; #endif // GREATCIRCLE_H diff --git a/src/data/poi.cpp b/src/data/poi.cpp index 2896bc29..ab226820 100644 --- a/src/data/poi.cpp +++ b/src/data/poi.cpp @@ -95,38 +95,43 @@ static bool cb(size_t data, void* context) return true; } +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(); + + _tree.Search(min, max, cb, &set); +} + QList POI::points(const Path &path) const { QList ret; QSet set; - qreal min[2], max[2]; QSet::const_iterator it; for (int i = 1; i < path.count(); i++) { double ds = path.at(i).distance() - path.at(i-1).distance(); unsigned n = (unsigned)ceil(ds / _radius); - for (unsigned j = 0; j < n; j++) { - RectC br(n > 1 ? GreatCircle::pointAt(path.at(i-1).coordinates(), - path.at(i).coordinates(), (double)j/n) - : path.at(i-1).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); + if (n > 1) { + GreatCircle gc(path.at(i-1).coordinates(), path.at(i).coordinates()); + for (unsigned j = 0; j < n; j++) { + RectC br(gc.pointAt((double)j/n), _radius); + search(br, set); + } + } else { + RectC br(path.at(i-1).coordinates(), _radius); + search(br, set); } } RectC br(path.last().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) diff --git a/src/data/poi.h b/src/data/poi.h index a3cb9207..c1bda44b 100644 --- a/src/data/poi.h +++ b/src/data/poi.h @@ -45,6 +45,7 @@ private: }; bool loadFile(const QString &path, bool dir); + void search(const RectC &rect, QSet &set) const; POITree _tree; QVector _data;