1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-06 23:03:22 +02:00
GPXSee/src/pathview.cpp

729 lines
16 KiB
C++
Raw Normal View History

#include <QGraphicsView>
#include <QGraphicsScene>
#include <QWheelEvent>
2016-12-06 01:48:26 +01:00
#include <QSysInfo>
2016-12-20 00:11:30 +01:00
#include "opengl.h"
#include "rd.h"
2017-01-16 09:54:12 +01:00
#include "wgs84.h"
2016-02-12 10:23:14 +01:00
#include "poi.h"
2016-10-23 11:09:20 +02:00
#include "data.h"
2016-02-12 10:09:17 +01:00
#include "map.h"
#include "trackitem.h"
2016-08-09 01:16:19 +02:00
#include "routeitem.h"
2016-02-19 21:34:55 +01:00
#include "waypointitem.h"
#include "scaleitem.h"
2016-09-26 21:01:58 +02:00
#include "pathview.h"
#define ZOOM_MAX 18
#define ZOOM_MIN 3
#define MARGIN 10.0
#define SCALE_OFFSET 7
static QPoint mercator2tile(const QPointF &m, int z)
{
QPoint tile;
2017-01-07 22:20:04 +01:00
tile.setX((int)(floor((m.x() + 180.0) / 360.0 * (1<<z))));
tile.setY((int)(floor((1.0 - (m.y() / 180.0)) / 2.0 * (1<<z))));
return tile;
}
static QPointF tile2mercator(const QPoint &tile, int z)
{
2017-01-11 22:14:01 +01:00
QPointF m;
2017-01-11 22:14:01 +01:00
m.setX(((360.0 * tile.x()) / (qreal)(1<<z)) - 180.0);
m.setY((1.0 - (2.0 * tile.y()) / (qreal)(1<<z)) * 180.0);
2017-01-11 22:14:01 +01:00
return m;
}
static int scale2zoom(qreal scale)
{
int zoom = (int)log2(360.0/(scale * (qreal)Tile::size()));
if (zoom < ZOOM_MIN)
return ZOOM_MIN;
if (zoom > ZOOM_MAX)
return ZOOM_MAX;
return zoom;
}
2016-11-11 17:58:18 +01:00
qreal mapScale(int zoom)
{
return ((360.0/(qreal)(1<<zoom))/(qreal)Tile::size());
}
2017-01-16 09:54:12 +01:00
static qreal zoom2resolution(int zoom, qreal y)
2016-11-11 17:58:18 +01:00
{
2017-01-16 09:54:12 +01:00
return (WGS84_RADIUS * 2 * M_PI / Tile::size()
* cos(2.0 * atan(exp(deg2rad(y))) - M_PI/2)) / (qreal)(1<<zoom);
2016-11-11 17:58:18 +01:00
}
static void unite(QRectF &rect, const QPointF &p)
{
if (p.x() < rect.left())
rect.setLeft(p.x());
if (p.x() > rect.right())
rect.setRight(p.x());
if (p.y() > rect.bottom())
rect.setBottom(p.y());
if (p.y() < rect.top())
rect.setTop(p.y());
}
static QRectF scaled(const QRectF &rect, qreal factor)
{
return QRectF(QPointF(rect.left() * factor, rect.top() * factor),
QSizeF(rect.width() * factor, rect.height() * factor));
}
2016-09-26 21:01:58 +02:00
PathView::PathView(QWidget *parent)
: QGraphicsView(parent)
{
_scene = new QGraphicsScene(this);
setScene(_scene);
setCacheMode(QGraphicsView::CacheBackground);
setDragMode(QGraphicsView::ScrollHandDrag);
setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
2016-12-06 01:48:26 +01:00
setRenderHint(QPainter::Antialiasing, true);
2016-10-04 10:16:46 +02:00
setAcceptDrops(false);
_mapScale = new ScaleItem();
_mapScale->setZValue(2.0);
2016-03-15 01:20:24 +01:00
_zoom = ZOOM_MAX;
2017-01-16 09:54:12 +01:00
_res = 1.0;
_map = 0;
2016-10-08 14:53:10 +02:00
_poi = 0;
2016-07-25 19:32:36 +02:00
_units = Metric;
2016-08-09 01:16:19 +02:00
_showTracks = true;
_showRoutes = true;
_showWaypoints = true;
_showWaypointLabels = true;
2016-10-08 14:53:10 +02:00
_showPOI = true;
2016-08-09 01:16:19 +02:00
_showPOILabels = true;
_overlapPOIs = true;
2016-08-09 10:47:49 +02:00
_showRouteWaypoints = true;
2016-12-06 01:48:26 +01:00
_trackWidth = 3;
_routeWidth = 3;
_trackStyle = Qt::SolidLine;
_routeStyle = Qt::DashLine;
2016-08-09 01:16:19 +02:00
_plot = false;
}
2016-09-26 21:01:58 +02:00
PathView::~PathView()
{
2016-05-12 09:03:05 +02:00
if (_mapScale->scene() != _scene)
delete _mapScale;
}
2016-09-26 21:01:58 +02:00
PathItem *PathView::addTrack(const Track &track)
{
if (track.isNull()) {
2016-12-06 01:48:26 +01:00
_palette.nextColor();
2016-09-19 00:56:10 +02:00
return 0;
2016-03-23 20:49:40 +01:00
}
2016-08-09 01:16:19 +02:00
TrackItem *ti = new TrackItem(track);
_tracks.append(ti);
2016-11-11 17:58:18 +01:00
_tr |= ti->path().boundingRect();
_zoom = scale2zoom(contentsScale());
ti->setScale(1.0/mapScale(_zoom));
2016-12-06 01:48:26 +01:00
ti->setColor(_palette.nextColor());
ti->setWidth(_trackWidth);
ti->setStyle(_trackStyle);
2016-08-09 01:16:19 +02:00
ti->setVisible(_showTracks);
_scene->addItem(ti);
2016-09-19 00:56:10 +02:00
2016-10-08 14:53:10 +02:00
if (_poi)
addPOI(_poi->points(ti));
2016-09-19 00:56:10 +02:00
return ti;
2016-03-03 09:15:56 +01:00
}
2016-09-26 21:01:58 +02:00
PathItem *PathView::addRoute(const Route &route)
2016-08-09 01:16:19 +02:00
{
if (route.isNull()) {
2016-12-06 01:48:26 +01:00
_palette.nextColor();
2016-09-19 00:56:10 +02:00
return 0;
2016-08-09 01:16:19 +02:00
}
RouteItem *ri = new RouteItem(route);
_routes.append(ri);
2016-11-11 17:58:18 +01:00
_rr |= ri->path().boundingRect();
_zoom = scale2zoom(contentsScale());
ri->setScale(1.0/mapScale(_zoom));
2016-12-06 01:48:26 +01:00
ri->setColor(_palette.nextColor());
ri->setWidth(_routeWidth);
ri->setStyle(_routeStyle);
2016-08-09 01:16:19 +02:00
ri->setVisible(_showRoutes);
2016-08-09 10:47:49 +02:00
ri->showWaypoints(_showRouteWaypoints);
ri->showWaypointLabels(_showWaypointLabels);
2016-08-09 01:16:19 +02:00
_scene->addItem(ri);
2016-09-19 00:56:10 +02:00
2016-10-08 14:53:10 +02:00
if (_poi)
addPOI(_poi->points(ri));
2016-09-19 00:56:10 +02:00
return ri;
2016-08-09 01:16:19 +02:00
}
2016-09-26 21:01:58 +02:00
void PathView::addWaypoints(const QList<Waypoint> &waypoints)
2016-03-15 01:20:24 +01:00
{
2016-11-11 17:58:18 +01:00
qreal scale = mapScale(_zoom);
2016-03-15 01:20:24 +01:00
for (int i = 0; i < waypoints.count(); i++) {
2016-03-19 09:06:43 +01:00
const Waypoint &w = waypoints.at(i);
2016-03-15 01:20:24 +01:00
WaypointItem *wi = new WaypointItem(w);
_waypoints.append(wi);
updateWaypointsBoundingRect(wi->coordinates());
2016-11-11 17:58:18 +01:00
wi->setScale(1.0/scale);
2016-03-15 01:20:24 +01:00
wi->setZValue(1);
2016-08-09 01:16:19 +02:00
wi->showLabel(_showWaypointLabels);
wi->setVisible(_showWaypoints);
2016-03-15 01:20:24 +01:00
_scene->addItem(wi);
}
2016-10-08 14:53:10 +02:00
if (_poi)
addPOI(_poi->points(waypoints));
2016-11-11 17:58:18 +01:00
_zoom = scale2zoom(contentsScale());
2016-03-15 01:20:24 +01:00
}
2016-10-23 11:09:20 +02:00
QList<PathItem *> PathView::loadData(const Data &data)
2016-03-03 09:15:56 +01:00
{
2016-09-19 00:56:10 +02:00
QList<PathItem *> paths;
2016-03-15 01:20:24 +01:00
int zoom = _zoom;
2016-10-23 11:09:20 +02:00
for (int i = 0; i < data.tracks().count(); i++)
paths.append(addTrack(*(data.tracks().at(i))));
2017-01-16 09:54:12 +01:00
2016-10-23 11:09:20 +02:00
for (int i = 0; i < data.routes().count(); i++)
paths.append(addRoute(*(data.routes().at(i))));
2017-01-16 09:54:12 +01:00
2016-10-23 11:09:20 +02:00
addWaypoints(data.waypoints());
2016-03-15 01:20:24 +01:00
2016-08-09 01:16:19 +02:00
if (_tracks.empty() && _routes.empty() && _waypoints.empty())
2016-09-19 00:56:10 +02:00
return paths;
2016-03-15 01:20:24 +01:00
2017-01-16 09:54:12 +01:00
if (_zoom < zoom)
2016-11-11 17:58:18 +01:00
rescale(_zoom);
2017-01-16 09:54:12 +01:00
else {
_scene->setSceneRect(scaled(QRectF(QPointF(-180, -180),
QSizeF(360, 360)), 1.0 / mapScale(_zoom)));
2016-10-08 14:53:10 +02:00
updatePOIVisibility();
2017-01-16 09:54:12 +01:00
}
2017-01-16 09:54:12 +01:00
QPointF center = contentsCenter();
centerOn(center);
2017-01-16 09:54:12 +01:00
_res = zoom2resolution(_zoom, -(center.y() * mapScale(_zoom)));
_mapScale->setResolution(_res);
2016-03-03 09:15:56 +01:00
if (_mapScale->scene() != _scene)
_scene->addItem(_mapScale);
2016-09-19 00:56:10 +02:00
return paths;
}
void PathView::updateWaypointsBoundingRect(const QPointF &wp)
{
if (_wr.isNull()) {
if (_wp.isNull())
_wp = wp;
else {
2017-01-16 09:54:12 +01:00
_wr = QRectF(_wp, wp).normalized();
_wp = QPointF();
}
} else
unite(_wr, wp);
}
2016-11-11 17:58:18 +01:00
qreal PathView::contentsScale() const
{
2016-11-11 17:58:18 +01:00
QRectF br = _tr | _rr | _wr;
if (!br.isNull() && !_wp.isNull())
unite(br, _wp);
2016-03-15 01:20:24 +01:00
2016-11-11 17:58:18 +01:00
if (br.isNull())
2016-03-15 01:20:24 +01:00
return mapScale(ZOOM_MAX);
QPointF sc(br.width() / (viewport()->width() - MARGIN/2),
br.height() / (viewport()->height() - MARGIN/2));
return qMax(sc.x(), sc.y());
}
2017-01-16 09:54:12 +01:00
QPointF PathView::contentsCenter() const
{
QRectF br = _tr | _rr | _wr;
if (!br.isNull() && !_wp.isNull())
unite(br, _wp);
2017-01-16 09:54:12 +01:00
qreal scale = mapScale(_zoom);
if (br.isNull())
2017-01-16 09:54:12 +01:00
return _wp / scale;
else
2017-01-16 09:54:12 +01:00
return scaled(br, 1.0/scale).center();
}
2016-10-08 14:53:10 +02:00
void PathView::updatePOIVisibility()
{
QHash<Waypoint, WaypointItem*>::const_iterator it, jt;
2016-10-08 14:53:10 +02:00
if (!_showPOI)
return;
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
it.value()->show();
if (!_overlapPOIs) {
for (it = _pois.constBegin(); it != _pois.constEnd(); it++) {
for (jt = _pois.constBegin(); jt != _pois.constEnd(); jt++) {
if (it.value()->isVisible() && jt.value()->isVisible()
&& it != jt && it.value()->collidesWithItem(jt.value()))
jt.value()->hide();
}
}
}
}
2016-11-11 17:58:18 +01:00
void PathView::rescale(int zoom)
{
2016-11-11 17:58:18 +01:00
_zoom = zoom;
qreal scale = mapScale(zoom);
2016-10-08 14:53:10 +02:00
2017-01-16 09:54:12 +01:00
_scene->setSceneRect(scaled(QRectF(QPointF(-180, -180), QSizeF(360, 360)),
1.0 / scale));
2016-08-09 01:16:19 +02:00
for (int i = 0; i < _tracks.size(); i++)
_tracks.at(i)->setScale(1.0/scale);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->setScale(1.0/scale);
for (int i = 0; i < _waypoints.size(); i++)
2016-08-02 00:28:56 +02:00
_waypoints.at(i)->setScale(1.0/scale);
2016-03-15 01:20:24 +01:00
QHash<Waypoint, WaypointItem*>::const_iterator it;
2016-10-08 14:53:10 +02:00
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
2016-08-02 00:28:56 +02:00
it.value()->setScale(1.0/scale);
2016-10-08 14:53:10 +02:00
updatePOIVisibility();
}
2016-12-06 01:48:26 +01:00
void PathView::setPalette(const Palette &palette)
{
_palette = palette;
_palette.reset();
for (int i = 0; i < _tracks.count(); i++)
_tracks.at(i)->setColor(_palette.nextColor());
for (int i = 0; i < _routes.count(); i++)
_routes.at(i)->setColor(_palette.nextColor());
}
2016-10-08 14:53:10 +02:00
void PathView::setPOI(POI *poi)
{
2016-10-09 23:46:30 +02:00
if (_poi)
2016-10-11 00:19:42 +02:00
disconnect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
2016-10-09 23:46:30 +02:00
2016-10-08 14:53:10 +02:00
_poi = poi;
2016-10-09 23:46:30 +02:00
if (_poi)
2016-10-11 00:19:42 +02:00
connect(_poi, SIGNAL(pointsChanged()), this, SLOT(updatePOI()));
updatePOI();
2016-10-08 14:53:10 +02:00
}
2016-10-09 23:46:30 +02:00
void PathView::updatePOI()
2016-10-08 14:53:10 +02:00
{
2016-10-09 23:46:30 +02:00
QHash<Waypoint, WaypointItem*>::const_iterator it;
for (it = _pois.constBegin(); it != _pois.constEnd(); it++) {
_scene->removeItem(it.value());
delete it.value();
}
_pois.clear();
2016-10-08 14:53:10 +02:00
if (!_poi)
return;
for (int i = 0; i < _tracks.size(); i++)
addPOI(_poi->points(_tracks.at(i)));
for (int i = 0; i < _routes.size(); i++)
addPOI(_poi->points(_routes.at(i)));
addPOI(_poi->points(_waypoints));
updatePOIVisibility();
}
2016-09-26 21:01:58 +02:00
void PathView::addPOI(const QVector<Waypoint> &waypoints)
{
2016-11-11 17:58:18 +01:00
qreal scale = mapScale(_zoom);
for (int i = 0; i < waypoints.size(); i++) {
2016-03-19 09:06:43 +01:00
const Waypoint &w = waypoints.at(i);
if (_pois.contains(w))
continue;
WaypointItem *pi = new WaypointItem(w);
2016-11-11 17:58:18 +01:00
pi->setScale(1.0/scale);
pi->setZValue(1);
2016-08-09 01:16:19 +02:00
pi->showLabel(_showPOILabels);
2016-10-08 14:53:10 +02:00
pi->setVisible(_showPOI);
_scene->addItem(pi);
2016-03-19 09:06:43 +01:00
_pois.insert(w, pi);
}
}
2016-09-26 21:01:58 +02:00
void PathView::setMap(Map *map)
{
if (_map)
disconnect(_map, SIGNAL(loaded()), this, SLOT(redraw()));
_map = map;
if (_map)
connect(_map, SIGNAL(loaded()), this, SLOT(redraw()));
resetCachedContent();
}
2016-09-26 21:01:58 +02:00
void PathView::setUnits(enum Units units)
{
2016-07-25 19:32:36 +02:00
_units = units;
_mapScale->setUnits(units);
2016-07-25 19:32:36 +02:00
2016-08-09 01:16:19 +02:00
for (int i = 0; i < _tracks.count(); i++)
_tracks[i]->setUnits(units);
for (int i = 0; i < _routes.count(); i++)
_routes[i]->setUnits(units);
2016-08-02 00:28:56 +02:00
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->setUnits(units);
QHash<Waypoint, WaypointItem*>::const_iterator it;
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
it.value()->setUnits(units);
}
2016-09-26 21:01:58 +02:00
void PathView::redraw()
{
resetCachedContent();
}
void PathView::zoom(int z, const QPoint &pos)
{
2016-08-09 01:16:19 +02:00
if (_tracks.isEmpty() && _routes.isEmpty() && _waypoints.isEmpty())
return;
QPoint offset = pos - viewport()->rect().center();
QPointF spos = mapToScene(pos);
2016-11-11 17:58:18 +01:00
qreal os = mapScale(_zoom);
_zoom = z;
2016-11-11 17:58:18 +01:00
rescale(_zoom);
2017-01-16 09:54:12 +01:00
QPointF center = (spos * (os/mapScale(_zoom))) - offset;
centerOn(center);
2017-01-16 09:54:12 +01:00
_res = zoom2resolution(_zoom, -(center.y() * mapScale(_zoom)));
_mapScale->setResolution(_res);
resetCachedContent();
}
2016-09-26 21:01:58 +02:00
void PathView::wheelEvent(QWheelEvent *event)
{
int z = (event->delta() > 0) ?
qMin(_zoom + 1, ZOOM_MAX) : qMax(_zoom - 1, ZOOM_MIN);
zoom(z, event->pos());
}
void PathView::mouseDoubleClickEvent(QMouseEvent *event)
{
if (event->button() != Qt::LeftButton && event->button() != Qt::RightButton)
return;
int z = (event->button() == Qt::LeftButton) ?
qMin(_zoom + 1, ZOOM_MAX) : qMax(_zoom - 1, ZOOM_MIN);
zoom(z, event->pos());
}
2016-09-26 21:01:58 +02:00
void PathView::keyPressEvent(QKeyEvent *event)
{
int z = -1;
if (event->matches(QKeySequence::ZoomIn))
z = qMin(_zoom + 1, ZOOM_MAX);
if (event->matches(QKeySequence::ZoomOut))
z = qMax(_zoom - 1, ZOOM_MIN);
if (z >= 0)
zoom(z, QRect(QPoint(), size()).center());
else
QWidget::keyPressEvent(event);
}
2016-09-26 21:01:58 +02:00
void PathView::plot(QPainter *painter, const QRectF &target)
{
QRect orig, adj;
qreal ratio, diff;
2016-05-20 22:44:03 +02:00
2016-05-15 13:19:07 +02:00
orig = viewport()->rect();
2016-05-27 22:45:58 +02:00
if (orig.height() * (target.width() / target.height()) - orig.width() < 0) {
ratio = target.height()/target.width();
2016-05-27 22:45:58 +02:00
diff = (orig.width() * ratio) - orig.height();
adj = orig.adjusted(0, -diff/2, 0, diff/2);
2016-05-27 22:45:58 +02:00
} else {
ratio = target.width() / target.height();
diff = (orig.height() * ratio) - orig.width();
adj = orig.adjusted(-diff/2, 0, diff/2, 0);
}
2016-05-20 22:44:03 +02:00
setUpdatesEnabled(false);
_plot = true;
2016-05-20 22:44:03 +02:00
QPointF pos = _mapScale->pos();
_mapScale->setPos(mapToScene(QPoint(adj.bottomRight() + QPoint(
-(SCALE_OFFSET + _mapScale->boundingRect().width()),
-(SCALE_OFFSET + _mapScale->boundingRect().height())))));
render(painter, target, adj);
2016-05-20 22:44:03 +02:00
_mapScale->setPos(pos);
_plot = false;
2016-05-20 22:44:03 +02:00
setUpdatesEnabled(true);
}
2016-09-26 21:01:58 +02:00
void PathView::clear()
{
if (_mapScale->scene() == _scene)
_scene->removeItem(_mapScale);
_pois.clear();
2016-08-09 01:16:19 +02:00
_tracks.clear();
_routes.clear();
_waypoints.clear();
_scene->clear();
2016-03-02 09:34:39 +01:00
_palette.reset();
2016-03-15 01:20:24 +01:00
_zoom = ZOOM_MAX;
2017-01-16 09:54:12 +01:00
_res = 1.0;
2016-11-11 17:58:18 +01:00
_tr = QRectF(); _rr = QRectF(); _wr = QRectF();
_wp = QPointF();
2016-03-03 09:15:56 +01:00
_scene->setSceneRect(QRectF());
}
2016-09-26 21:01:58 +02:00
void PathView::showTracks(bool show)
2016-08-09 01:16:19 +02:00
{
_showTracks = show;
for (int i = 0; i < _tracks.count(); i++)
_tracks.at(i)->setVisible(show);
}
2016-09-26 21:01:58 +02:00
void PathView::showRoutes(bool show)
2016-08-09 01:16:19 +02:00
{
_showRoutes = show;
for (int i = 0; i < _routes.count(); i++)
_routes.at(i)->setVisible(show);
}
2016-09-26 21:01:58 +02:00
void PathView::showWaypoints(bool show)
2016-08-09 01:16:19 +02:00
{
_showWaypoints = show;
for (int i = 0; i < _waypoints.count(); i++)
_waypoints.at(i)->setVisible(show);
}
2016-09-26 21:01:58 +02:00
void PathView::showWaypointLabels(bool show)
2016-08-09 01:16:19 +02:00
{
_showWaypointLabels = show;
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->showLabel(show);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->showWaypointLabels(show);
2016-08-09 01:16:19 +02:00
}
2016-09-26 21:01:58 +02:00
void PathView::showRouteWaypoints(bool show)
2016-08-09 10:47:49 +02:00
{
_showRouteWaypoints = show;
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->showWaypoints(show);
}
2016-10-08 14:53:10 +02:00
void PathView::showPOI(bool show)
{
_showPOI = show;
QHash<Waypoint, WaypointItem*>::const_iterator it;
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
it.value()->setVisible(show);
updatePOIVisibility();
}
2016-09-26 21:01:58 +02:00
void PathView::showPOILabels(bool show)
2016-08-09 01:16:19 +02:00
{
_showPOILabels = show;
QHash<Waypoint, WaypointItem*>::const_iterator it;
for (it = _pois.constBegin(); it != _pois.constEnd(); it++)
it.value()->showLabel(show);
2016-10-08 14:53:10 +02:00
updatePOIVisibility();
2016-08-09 01:16:19 +02:00
}
2016-09-26 21:01:58 +02:00
void PathView::setPOIOverlap(bool overlap)
{
2016-08-09 01:16:19 +02:00
_overlapPOIs = overlap;
2016-10-08 14:53:10 +02:00
updatePOIVisibility();
}
2016-12-06 01:48:26 +01:00
void PathView::setTrackWidth(int width)
{
_trackWidth = width;
for (int i = 0; i < _tracks.count(); i++)
_tracks.at(i)->setWidth(width);
}
void PathView::setRouteWidth(int width)
{
_routeWidth = width;
for (int i = 0; i < _routes.count(); i++)
_routes.at(i)->setWidth(width);
}
void PathView::setTrackStyle(Qt::PenStyle style)
{
_trackStyle = style;
for (int i = 0; i < _tracks.count(); i++)
_tracks.at(i)->setStyle(style);
}
void PathView::setRouteStyle(Qt::PenStyle style)
{
_routeStyle = style;
for (int i = 0; i < _routes.count(); i++)
_routes.at(i)->setStyle(style);
}
2016-09-26 21:01:58 +02:00
void PathView::drawBackground(QPainter *painter, const QRectF &rect)
{
2016-08-09 01:16:19 +02:00
if ((_tracks.isEmpty() && _routes.isEmpty() && _waypoints.isEmpty())
|| !_map) {
painter->fillRect(rect, Qt::white);
return;
}
2016-11-11 17:58:18 +01:00
qreal scale = mapScale(_zoom);
QRectF rr(rect.topLeft() * scale, rect.size());
QPoint tile = mercator2tile(QPointF(rr.topLeft().x(), -rr.topLeft().y()),
_zoom);
QPointF tm = tile2mercator(tile, _zoom);
2017-01-11 22:14:01 +01:00
QPoint tl = QPoint((int)(tm.x() / scale), (int)(-tm.y() / scale));
QList<Tile> tiles;
2017-01-16 21:45:50 +01:00
QSizeF s(rect.right() - tl.x(), rect.bottom() - tl.y());
for (int i = 0; i < ceil(s.width() / Tile::size()); i++)
for (int j = 0; j < ceil(s.height() / Tile::size()); j++)
tiles.append(Tile(QPoint(tile.x() + i, tile.y() + j), _zoom));
_map->loadTiles(tiles, _plot);
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * Tile::size(),
tl.y() + (t.xy().y() - tile.y()) * Tile::size());
painter->drawPixmap(tp, t.pixmap());
}
}
void PathView::resizeEvent(QResizeEvent *event)
{
2017-01-16 09:54:12 +01:00
Q_UNUSED(event);
2016-08-09 01:16:19 +02:00
if (_tracks.isEmpty() && _routes.isEmpty() && _waypoints.isEmpty())
return;
2017-01-16 09:54:12 +01:00
int zoom = scale2zoom(contentsScale());
if (zoom != _zoom)
rescale(zoom);
2017-01-16 09:54:12 +01:00
QPointF center = contentsCenter();
centerOn(center);
2017-01-16 09:54:12 +01:00
_res = zoom2resolution(_zoom, -(center.y() * mapScale(_zoom)));
_mapScale->setResolution(_res);
resetCachedContent();
}
void PathView::paintEvent(QPaintEvent *event)
{
2016-05-20 22:44:03 +02:00
QPointF scenePos = mapToScene(rect().bottomRight() + QPoint(
-(SCALE_OFFSET + _mapScale->boundingRect().width()),
-(SCALE_OFFSET + _mapScale->boundingRect().height())));
if (_mapScale->pos() != scenePos && !_plot)
_mapScale->setPos(scenePos);
QGraphicsView::paintEvent(event);
}
2016-12-06 01:48:26 +01:00
2017-01-16 09:54:12 +01:00
void PathView::scrollContentsBy(int dx, int dy)
{
QGraphicsView::scrollContentsBy(dx, dy);
QPointF center = mapToScene(viewport()->rect().center());
qreal res = zoom2resolution(_zoom, -(center.y() * mapScale(_zoom)));
if (qMax(res, _res) / qMin(res, _res) > 1.1) {
_mapScale->setResolution(res);
_res = res;
}
}
2016-12-06 01:48:26 +01:00
void PathView::useOpenGL(bool use)
{
if (use) {
#ifdef Q_OS_WIN32
if (QSysInfo::WindowsVersion >= QSysInfo::WV_VISTA)
#endif // Q_OS_WIN32
2017-01-02 23:01:50 +01:00
setViewport(new OPENGL_WIDGET);
2016-12-06 01:48:26 +01:00
} else
setViewport(new QWidget);
}