mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Now drawing path segments > 1 arc minute as great circle curves instead of rhumb lines
This commit is contained in:
parent
8d1be76043
commit
9957e1834e
@ -141,7 +141,8 @@ HEADERS += src/config.h \
|
|||||||
src/data/locparser.h \
|
src/data/locparser.h \
|
||||||
src/data/slfparser.h \
|
src/data/slfparser.h \
|
||||||
src/map/geotiffmap.h \
|
src/map/geotiffmap.h \
|
||||||
src/map/image.h
|
src/map/image.h \
|
||||||
|
src/common/greatcircle.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/common/coordinates.cpp \
|
src/common/coordinates.cpp \
|
||||||
src/common/rectc.cpp \
|
src/common/rectc.cpp \
|
||||||
@ -246,7 +247,8 @@ SOURCES += src/main.cpp \
|
|||||||
src/data/locparser.cpp \
|
src/data/locparser.cpp \
|
||||||
src/data/slfparser.cpp \
|
src/data/slfparser.cpp \
|
||||||
src/map/geotiffmap.cpp \
|
src/map/geotiffmap.cpp \
|
||||||
src/map/image.cpp
|
src/map/image.cpp \
|
||||||
|
src/common/greatcircle.cpp
|
||||||
|
|
||||||
RESOURCES += gpxsee.qrc
|
RESOURCES += gpxsee.qrc
|
||||||
TRANSLATIONS = lang/gpxsee_cs.ts \
|
TRANSLATIONS = lang/gpxsee_cs.ts \
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
#include <QCursor>
|
#include <QCursor>
|
||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
|
#include "common/greatcircle.h"
|
||||||
#include "map/map.h"
|
#include "map/map.h"
|
||||||
#include "tooltip.h"
|
#include "tooltip.h"
|
||||||
#include "nicenum.h"
|
#include "nicenum.h"
|
||||||
@ -44,8 +45,27 @@ void PathItem::updatePainterPath(Map *map)
|
|||||||
_painterPath = QPainterPath();
|
_painterPath = QPainterPath();
|
||||||
|
|
||||||
_painterPath.moveTo(map->ll2xy(_path.first().coordinates()));
|
_painterPath.moveTo(map->ll2xy(_path.first().coordinates()));
|
||||||
for (int i = 1; i < _path.size(); i++)
|
for (int i = 1; i < _path.size(); i++) {
|
||||||
_painterPath.lineTo(map->ll2xy(_path.at(i).coordinates()));
|
Coordinates c1(_path.at(i-1).coordinates());
|
||||||
|
Coordinates c2(_path.at(i).coordinates());
|
||||||
|
unsigned n = qAbs(c1.lon() - c2.lon());
|
||||||
|
|
||||||
|
if (n) {
|
||||||
|
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)));
|
||||||
|
double current = c.lon();
|
||||||
|
if (fabs(current - prev) > 180.0)
|
||||||
|
_painterPath.moveTo(map->ll2xy(c));
|
||||||
|
else
|
||||||
|
_painterPath.lineTo(map->ll2xy(c));
|
||||||
|
prev = current;
|
||||||
|
}
|
||||||
|
} else
|
||||||
|
_painterPath.lineTo(map->ll2xy(c2));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
void PathItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
|
||||||
@ -141,20 +161,24 @@ QPointF PathItem::position(qreal x) const
|
|||||||
return _map->ll2xy(_path.at(mid).coordinates());
|
return _map->ll2xy(_path.at(mid).coordinates());
|
||||||
}
|
}
|
||||||
|
|
||||||
QLineF l;
|
Coordinates c1, c2;
|
||||||
qreal p1, p2;
|
qreal p1, p2;
|
||||||
|
|
||||||
if (_path.at(mid).distance() < x) {
|
if (_path.at(mid).distance() < x) {
|
||||||
l = QLineF(_map->ll2xy(_path.at(mid).coordinates()),
|
c1 = _path.at(mid).coordinates(); c2 = _path.at(mid+1).coordinates();
|
||||||
_map->ll2xy(_path.at(mid+1).coordinates()));
|
|
||||||
p1 = _path.at(mid).distance(); p2 = _path.at(mid+1).distance();
|
p1 = _path.at(mid).distance(); p2 = _path.at(mid+1).distance();
|
||||||
} else {
|
} else {
|
||||||
l = QLineF(_map->ll2xy(_path.at(mid-1).coordinates()),
|
c1 = _path.at(mid-1).coordinates(); c2 = _path.at(mid).coordinates();
|
||||||
_map->ll2xy(_path.at(mid).coordinates()));
|
|
||||||
p1 = _path.at(mid-1).distance(); p2 = _path.at(mid).distance();
|
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 {
|
||||||
|
QLineF l(_map->ll2xy(c1), _map->ll2xy(c2));
|
||||||
return l.pointAt((x - p1) / (p2 - p1));
|
return l.pointAt((x - p1) / (p2 - p1));
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void PathItem::moveMarker(qreal distance)
|
void PathItem::moveMarker(qreal distance)
|
||||||
{
|
{
|
||||||
|
23
src/common/greatcircle.cpp
Normal file
23
src/common/greatcircle.cpp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "greatcircle.h"
|
||||||
|
|
||||||
|
Coordinates GreatCircle::pointAt(const Coordinates &c1, const Coordinates &c2,
|
||||||
|
double f)
|
||||||
|
{
|
||||||
|
double lat1 = deg2rad(c1.lat());
|
||||||
|
double lon1 = deg2rad(c1.lon());
|
||||||
|
double lat2 = deg2rad(c2.lat());
|
||||||
|
double 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);
|
||||||
|
|
||||||
|
return Coordinates(rad2deg(atan2(y, x)), rad2deg(atan2(z, sqrt(x*x + y*y))));
|
||||||
|
}
|
11
src/common/greatcircle.h
Normal file
11
src/common/greatcircle.h
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
#ifndef GREATCIRCLE_H
|
||||||
|
#define GREATCIRCLE_H
|
||||||
|
|
||||||
|
#include "coordinates.h"
|
||||||
|
|
||||||
|
namespace GreatCircle
|
||||||
|
{
|
||||||
|
Coordinates pointAt(const Coordinates &c1, const Coordinates &c2, double f);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // GREATCIRCLE_H
|
@ -1,6 +1,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include "common/rectc.h"
|
#include "common/rectc.h"
|
||||||
|
#include "common/greatcircle.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
#include "poi.h"
|
#include "poi.h"
|
||||||
|
|
||||||
@ -94,28 +95,6 @@ static bool cb(size_t data, void* context)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Coordinates intermediate(const Coordinates &c1, const Coordinates &c2,
|
|
||||||
double f)
|
|
||||||
{
|
|
||||||
double lat1 = deg2rad(c1.lat());
|
|
||||||
double lon1 = deg2rad(c1.lon());
|
|
||||||
double lat2 = deg2rad(c2.lat());
|
|
||||||
double 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);
|
|
||||||
|
|
||||||
return Coordinates(rad2deg(atan2(y, x)), rad2deg(atan2(z, sqrt(x*x + y*y))));
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<Waypoint> POI::points(const Path &path) const
|
QList<Waypoint> POI::points(const Path &path) const
|
||||||
{
|
{
|
||||||
QList<Waypoint> ret;
|
QList<Waypoint> ret;
|
||||||
@ -128,8 +107,8 @@ QList<Waypoint> POI::points(const Path &path) const
|
|||||||
double ds = path.at(i).distance() - path.at(i-1).distance();
|
double ds = path.at(i).distance() - path.at(i-1).distance();
|
||||||
unsigned n = (unsigned)ceil(ds / _radius);
|
unsigned n = (unsigned)ceil(ds / _radius);
|
||||||
for (unsigned j = 0; j < n; j++) {
|
for (unsigned j = 0; j < n; j++) {
|
||||||
RectC br(n > 1 ? intermediate(path.at(i-1).coordinates(),
|
RectC br(n > 1 ? GreatCircle::pointAt(path.at(i-1).coordinates(),
|
||||||
path.at(i).coordinates(), (double)j/(double)n)
|
path.at(i).coordinates(), (double)j/n)
|
||||||
: path.at(i-1).coordinates(), _radius);
|
: path.at(i-1).coordinates(), _radius);
|
||||||
|
|
||||||
min[0] = br.topLeft().lon();
|
min[0] = br.topLeft().lon();
|
||||||
|
Loading…
Reference in New Issue
Block a user