1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/map/wmtsmap.cpp

207 lines
5.2 KiB
C++
Raw Normal View History

2018-02-20 23:37:19 +01:00
#include <QPainter>
#include "common/rectc.h"
#include "common/wgs84.h"
2018-02-20 23:37:19 +01:00
#include "config.h"
#include "transform.h"
2018-04-28 19:08:21 +02:00
#include "tileloader.h"
2018-02-20 23:37:19 +01:00
#include "wmts.h"
#include "wmtsmap.h"
#define CAPABILITIES_FILE "capabilities.xml"
bool WMTSMap::loadWMTS()
2018-02-20 23:37:19 +01:00
{
QString file = tilesDir() + "/" + CAPABILITIES_FILE;
2018-02-20 23:37:19 +01:00
WMTS wmts(file, _setup);
if (!wmts.isValid()) {
2018-02-20 23:37:19 +01:00
_errorString = wmts.errorString();
return false;
2018-02-20 23:37:19 +01:00
}
_bounds = wmts.bounds();
2018-02-20 23:37:19 +01:00
_zooms = wmts.zooms();
_projection = wmts.projection();
_tileLoader->setUrl(wmts.tileUrl());
2018-04-07 18:42:25 +02:00
if (_setup.coordinateSystem().axisOrder() == CoordinateSystem::Unknown)
_cs = _projection.coordinateSystem();
else
2018-04-07 18:42:25 +02:00
_cs = _setup.coordinateSystem();
2018-02-20 23:37:19 +01:00
updateTransform();
return true;
}
2018-08-18 21:06:36 +02:00
WMTSMap::WMTSMap(const QString &name, const WMTS::Setup &setup, qreal tileRatio,
QObject *parent) : Map(parent), _name(name), _setup(setup), _tileLoader(0),
_zoom(0), _deviceRatio(1.0), _tileRatio(tileRatio), _valid(false)
{
2018-09-24 22:49:10 +02:00
_tileLoader = new TileLoader(tilesDir(), this);
2018-04-27 23:08:44 +02:00
_tileLoader->setAuthorization(_setup.authorization());
connect(_tileLoader, SIGNAL(finished()), this, SIGNAL(loaded()));
_valid = loadWMTS();
}
void WMTSMap::clearCache()
{
_tileLoader->clearCache();
_zoom = 0;
if (!loadWMTS())
2018-09-24 23:07:11 +02:00
qWarning("%s: %s", qPrintable(_name), qPrintable(_errorString));
}
QString WMTSMap::tilesDir() const
{
return QString(TILES_DIR + "/" + _name);
2018-02-20 23:37:19 +01:00
}
double WMTSMap::sd2res(double scaleDenominator) const
2018-02-20 23:37:19 +01:00
{
return scaleDenominator * 0.28e-3 * _projection.units().fromMeters(1.0);
}
void WMTSMap::updateTransform()
{
const WMTS::Zoom &z = _zooms.at(_zoom);
PointD topLeft = (_cs.axisOrder() == CoordinateSystem::YX)
? PointD(z.topLeft().y(), z.topLeft().x()) : z.topLeft();
double pixelSpan = sd2res(z.scaleDenominator());
if (_projection.isGeographic())
pixelSpan /= deg2rad(WGS84_RADIUS);
PointD tileSpan(z.tile().width() * pixelSpan, z.tile().height() * pixelSpan);
PointD bottomRight(topLeft.x() + tileSpan.x() * z.matrix().width(),
topLeft.y() - tileSpan.y() * z.matrix().height());
2018-02-20 23:37:19 +01:00
ReferencePoint tl(PointD(0, 0), topLeft);
ReferencePoint br(PointD(z.tile().width() * z.matrix().width(),
z.tile().height() * z.matrix().height()), bottomRight);
_transform = Transform(tl, br);
2018-02-20 23:37:19 +01:00
}
2018-07-13 09:51:41 +02:00
QRectF WMTSMap::bounds()
2018-02-20 23:37:19 +01:00
{
const WMTS::Zoom &z = _zooms.at(_zoom);
QRectF tileBounds, bounds;
tileBounds = (z.limits().isNull()) ?
QRectF(QPointF(0, 0), QSize(z.tile().width() * z.matrix().width(),
z.tile().height() * z.matrix().height()))
: QRectF(QPointF(z.limits().left() * z.tile().width(), z.limits().top()
* z.tile().height()), QSize(z.tile().width() * z.limits().width(),
z.tile().height() * z.limits().height()));
bounds = _bounds.isValid() ? QRectF(ll2xy(_bounds.topLeft()),
ll2xy(_bounds.bottomRight())) : QRectF();
return _bounds.isValid() ? tileBounds.intersected(bounds) : tileBounds;
2018-02-20 23:37:19 +01:00
}
int WMTSMap::zoomFit(const QSize &size, const RectC &rect)
2018-02-20 23:37:19 +01:00
{
if (rect.isValid()) {
PointD tl(_projection.ll2xy(rect.topLeft()));
PointD br(_projection.ll2xy(rect.bottomRight()));
PointD sc((br.x() - tl.x()) / size.width(), (tl.y() - br.y())
/ size.height());
double resolution = qMax(qAbs(sc.x()), qAbs(sc.y()));
if (_projection.isGeographic())
resolution *= deg2rad(WGS84_RADIUS);
2018-02-20 23:37:19 +01:00
_zoom = 0;
2018-02-20 23:37:19 +01:00
for (int i = 0; i < _zooms.size(); i++) {
2018-08-18 21:06:36 +02:00
if (sd2res(_zooms.at(i).scaleDenominator()) < resolution
/ coordinatesRatio())
2018-02-20 23:37:19 +01:00
break;
_zoom = i;
}
} else
_zoom = _zooms.size() - 1;
2018-02-20 23:37:19 +01:00
updateTransform();
return _zoom;
}
2018-04-28 22:18:11 +02:00
void WMTSMap::setZoom(int zoom)
{
_zoom = zoom;
updateTransform();
}
int WMTSMap::zoomIn()
2018-02-20 23:37:19 +01:00
{
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
updateTransform();
return _zoom;
}
int WMTSMap::zoomOut()
2018-02-20 23:37:19 +01:00
{
_zoom = qMax(_zoom - 1, 0);
updateTransform();
return _zoom;
}
2018-08-18 21:06:36 +02:00
qreal WMTSMap::coordinatesRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio / _tileRatio : 1.0;
}
qreal WMTSMap::imageRatio() const
{
return _deviceRatio > 1.0 ? _deviceRatio : _tileRatio;
}
QSizeF WMTSMap::tileSize(const WMTS::Zoom &zoom) const
{
return QSizeF(zoom.tile().width() / coordinatesRatio(),
zoom.tile().height() / coordinatesRatio());
}
2018-08-23 20:26:10 +02:00
void WMTSMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
2018-02-20 23:37:19 +01:00
{
const WMTS::Zoom &z = _zooms.at(_zoom);
2018-08-18 21:06:36 +02:00
QSizeF ts(tileSize(z));
QPoint tl = QPoint((int)floor(rect.left() / ts.width()),
(int)floor(rect.top() / ts.height()));
QPoint br = QPoint((int)ceil(rect.right() / ts.width()),
(int)ceil(rect.bottom() / ts.height()));
2018-02-20 23:37:19 +01:00
QList<Tile> tiles;
for (int i = tl.x(); i < br.x(); i++)
for (int j = tl.y(); j < br.y(); j++)
tiles.append(Tile(QPoint(i, j), z.id()));
2018-02-20 23:37:19 +01:00
2018-08-23 20:26:10 +02:00
if (flags & Map::Block)
_tileLoader->loadTilesSync(tiles);
2018-02-20 23:37:19 +01:00
else
_tileLoader->loadTilesAsync(tiles);
2018-02-20 23:37:19 +01:00
for (int i = 0; i < tiles.count(); i++) {
Tile &t = tiles[i];
2018-08-18 21:06:36 +02:00
QPointF tp(t.xy().x() * ts.width(), t.xy().y() * ts.height());
if (!t.pixmap().isNull()) {
#ifdef ENABLE_HIDPI
t.pixmap().setDevicePixelRatio(imageRatio());
#endif // ENABLE_HIDPI
2018-02-20 23:37:19 +01:00
painter->drawPixmap(tp, t.pixmap());
2018-08-18 21:06:36 +02:00
}
2018-02-20 23:37:19 +01:00
}
}
2018-07-13 09:51:41 +02:00
QPointF WMTSMap::ll2xy(const Coordinates &c)
2018-02-20 23:37:19 +01:00
{
2018-08-18 21:06:36 +02:00
return _transform.proj2img(_projection.ll2xy(c)) / coordinatesRatio();
2018-02-20 23:37:19 +01:00
}
2018-07-13 09:51:41 +02:00
Coordinates WMTSMap::xy2ll(const QPointF &p)
2018-02-20 23:37:19 +01:00
{
2018-08-18 21:06:36 +02:00
return _projection.xy2ll(_transform.img2proj(p * coordinatesRatio()));
2018-02-20 23:37:19 +01:00
}