1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-12-05 00:39:09 +01:00

Compare commits

...

3 Commits

Author SHA1 Message Date
a4a54101a3 Removed forgotten debug stuff 2023-05-04 09:51:42 +02:00
af58893cbe Version++ 2023-05-04 09:41:02 +02:00
97e12d809f Map API refactoring
Including several map providers refactoring/rewrite
especial KML, JNX and TrekBuddy atlases.
2023-05-04 09:38:35 +02:00
63 changed files with 755 additions and 819 deletions

View File

@ -1,4 +1,4 @@
version: 13.0.{build} version: 13.1.{build}
configuration: configuration:
- Release - Release

View File

@ -3,7 +3,7 @@ unix:!macx:!android {
} else { } else {
TARGET = GPXSee TARGET = GPXSee
} }
VERSION = 13.0 VERSION = 13.1
QT += core \ QT += core \
gui \ gui \

View File

@ -37,7 +37,7 @@ Unicode true
; The name of the installer ; The name of the installer
Name "GPXSee" Name "GPXSee"
; Program version ; Program version
!define VERSION "13.0" !define VERSION "13.1"
; The file to write ; The file to write
OutFile "GPXSee-${VERSION}_x64.exe" OutFile "GPXSee-${VERSION}_x64.exe"

View File

@ -25,7 +25,6 @@ ToolTip AreaItem::info() const
AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent) AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
: PlaneItem(parent), _area(area) : PlaneItem(parent), _area(area)
{ {
_map = map;
_digitalZoom = 0; _digitalZoom = 0;
_width = 2; _width = 2;
_opacity = 0.5; _opacity = 0.5;
@ -35,34 +34,34 @@ AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent)
_pen = QPen(strokeColor(), width()); _pen = QPen(strokeColor(), width());
_brush = QBrush(fillColor()); _brush = QBrush(fillColor());
updatePainterPath(); updatePainterPath(map);
setCursor(Qt::ArrowCursor); setCursor(Qt::ArrowCursor);
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
} }
QPainterPath AreaItem::painterPath(const Polygon &polygon) QPainterPath AreaItem::painterPath(Map *map, const Polygon &polygon)
{ {
QPainterPath path; QPainterPath path;
for (int i = 0; i < polygon.size(); i++) { for (int i = 0; i < polygon.size(); i++) {
const QVector<Coordinates> &subpath = polygon.at(i); const QVector<Coordinates> &subpath = polygon.at(i);
path.moveTo(_map->ll2xy(subpath.first())); path.moveTo(map->ll2xy(subpath.first()));
for (int j = 1; j < subpath.size(); j++) for (int j = 1; j < subpath.size(); j++)
path.lineTo(_map->ll2xy(subpath.at(j))); path.lineTo(map->ll2xy(subpath.at(j)));
path.closeSubpath(); path.closeSubpath();
} }
return path; return path;
} }
void AreaItem::updatePainterPath() void AreaItem::updatePainterPath(Map *map)
{ {
_painterPath = QPainterPath(); _painterPath = QPainterPath();
for (int i = 0; i < _area.polygons().size(); i++) for (int i = 0; i < _area.polygons().size(); i++)
_painterPath.addPath(painterPath(_area.polygons().at(i))); _painterPath.addPath(painterPath(map, _area.polygons().at(i)));
} }
void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
@ -85,10 +84,7 @@ void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
void AreaItem::setMap(Map *map) void AreaItem::setMap(Map *map)
{ {
prepareGeometryChange(); prepareGeometryChange();
updatePainterPath(map);
_map = map;
updatePainterPath();
} }
const QColor &AreaItem::strokeColor() const const QColor &AreaItem::strokeColor() const

View File

@ -33,8 +33,8 @@ protected:
void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); void hoverLeaveEvent(QGraphicsSceneHoverEvent *event);
private: private:
QPainterPath painterPath(const Polygon &polygon); QPainterPath painterPath(Map *map, const Polygon &polygon);
void updatePainterPath(); void updatePainterPath(Map *map);
void updateColor(); void updateColor();
void updateWidth(); void updateWidth();
void updatePenStyle(); void updatePenStyle();
@ -45,8 +45,6 @@ private:
Area _area; Area _area;
Map *_map;
qreal _width; qreal _width;
QColor _color; QColor _color;
qreal _opacity; qreal _opacity;

View File

@ -1721,8 +1721,7 @@ bool GUI::loadMapNode(const TreeNode<Map*> &node, MapAction *&action,
bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent) bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent)
{ {
TreeNode<Map*> maps(MapList::loadMaps(fileName, TreeNode<Map*> maps(MapList::loadMaps(fileName));
CRS::projection(_options.inputProjection)));
QList<QAction*> existingActions(_mapsActionGroup->actions()); QList<QAction*> existingActions(_mapsActionGroup->actions());
return loadMapNode(maps, action, silent, existingActions); return loadMapNode(maps, action, silent, existingActions);
@ -1812,8 +1811,7 @@ void GUI::loadMapDir()
return; return;
QFileInfo fi(dir); QFileInfo fi(dir);
TreeNode<Map*> maps(MapList::loadMaps(dir, TreeNode<Map*> maps(MapList::loadMaps(dir));
CRS::projection(_options.inputProjection)));
QList<QAction*> existingActions(_mapsActionGroup->actions()); QList<QAction*> existingActions(_mapsActionGroup->actions());
QList<MapAction*> actions; QList<MapAction*> actions;
QMenu *menu = new QMenu(maps.name()); QMenu *menu = new QMenu(maps.name());
@ -2741,13 +2739,9 @@ void GUI::loadOptions()
_mapView->setPOIColor(_options.poiColor); _mapView->setPOIColor(_options.poiColor);
_mapView->setRenderHint(QPainter::Antialiasing, _options.pathAntiAliasing); _mapView->setRenderHint(QPainter::Antialiasing, _options.pathAntiAliasing);
_mapView->setMarkerColor(_options.sliderColor); _mapView->setMarkerColor(_options.sliderColor);
if (_options.useOpenGL) _mapView->useOpenGL(_options.useOpenGL);
_mapView->useOpenGL(true); _mapView->setMapConfig(CRS::projection(_options.inputProjection),
_mapView->setDevicePixelRatio(devicePixelRatioF(), CRS::projection(4326, _options.outputProjection), _options.hidpiMap);
_options.hidpiMap ? devicePixelRatioF() : 1.0);
_mapView->setOutputProjection(CRS::projection(4326,
_options.outputProjection));
_mapView->setInputProjection(CRS::projection(_options.inputProjection));
_mapView->setTimeZone(_options.timeZone.zone()); _mapView->setTimeZone(_options.timeZone.zone());
_mapView->setPositionSource(_positionSource); _mapView->setPositionSource(_positionSource);
@ -2856,14 +2850,12 @@ void GUI::updateOptions(const Options &options)
_positionSource = source; _positionSource = source;
} }
if (options.hidpiMap != _options.hidpiMap) if (options.hidpiMap != _options.hidpiMap
_mapView->setDevicePixelRatio(devicePixelRatioF(), || options.outputProjection != _options.outputProjection
options.hidpiMap ? devicePixelRatioF() : 1.0); || options.inputProjection != _options.inputProjection)
if (options.outputProjection != _options.outputProjection) _mapView->setMapConfig(CRS::projection(options.inputProjection),
_mapView->setOutputProjection(CRS::projection(4326, CRS::projection(4326, options.outputProjection), options.hidpiMap);
options.outputProjection));
if (options.inputProjection != _options.inputProjection)
_mapView->setInputProjection(CRS::projection(options.inputProjection));
if (options.timeZone != _options.timeZone) { if (options.timeZone != _options.timeZone) {
_mapView->setTimeZone(options.timeZone.zone()); _mapView->setTimeZone(options.timeZone.zone());
_dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone()); _dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone());
@ -2941,8 +2933,7 @@ void GUI::loadInitialMaps(const QString &selected)
if (mapDir.isNull()) if (mapDir.isNull())
return; return;
TreeNode<Map*> maps(MapList::loadMaps(mapDir, TreeNode<Map*> maps(MapList::loadMaps(mapDir));
CRS::projection(_options.inputProjection)));
createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd); createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd);
// Select the active map according to the user settings // Select the active map according to the user settings
@ -3044,8 +3035,7 @@ void GUI::show()
void GUI::screenChanged(QScreen *screen) void GUI::screenChanged(QScreen *screen)
{ {
_mapView->setDevicePixelRatio(devicePixelRatioF(), _mapView->setDevicePixelRatio(devicePixelRatioF());
_options.hidpiMap ? devicePixelRatioF() : 1.0);
disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this, disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this,
SLOT(logicalDotsPerInchChanged(qreal))); SLOT(logicalDotsPerInchChanged(qreal)));
@ -3057,6 +3047,5 @@ void GUI::logicalDotsPerInchChanged(qreal dpi)
{ {
Q_UNUSED(dpi) Q_UNUSED(dpi)
_mapView->setDevicePixelRatio(devicePixelRatioF(), _mapView->setDevicePixelRatio(devicePixelRatioF());
_options.hidpiMap ? devicePixelRatioF() : 1.0);
} }

View File

@ -81,19 +81,18 @@ ToolTip MapItem::info() const
return tt; return tt;
} }
MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent) MapItem::MapItem(MapAction *action, Map *map, const Projection &proj,
: PlaneItem(parent) GraphicsItem *parent) : PlaneItem(parent)
{ {
Map *src = action->data().value<Map*>(); Map *src = action->data().value<Map*>();
Q_ASSERT(map->isReady()); Q_ASSERT(map->isReady());
_name = src->name(); _name = src->name();
_fileName = src->path(); _fileName = src->path();
_bounds = src->llBounds(); _bounds = src->llBounds(proj);
connect(this, &MapItem::triggered, action, &MapAction::trigger); connect(this, &MapItem::triggered, action, &MapAction::trigger);
_map = map;
_digitalZoom = 0; _digitalZoom = 0;
_width = 2; _width = 2;
@ -101,23 +100,23 @@ MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent)
QBrush brush(Qt::SolidPattern); QBrush brush(Qt::SolidPattern);
_pen = QPen(brush, _width); _pen = QPen(brush, _width);
updatePainterPath(); updatePainterPath(map);
setCursor(Qt::ArrowCursor); setCursor(Qt::ArrowCursor);
setAcceptHoverEvents(true); setAcceptHoverEvents(true);
} }
void MapItem::updatePainterPath() void MapItem::updatePainterPath(Map *map)
{ {
_painterPath = QPainterPath(); _painterPath = QPainterPath();
QRectF r(bbox(_bounds, _map)); QRectF r(bbox(_bounds, map));
if (r.left() > r.right()) { if (r.left() > r.right()) {
QRectF r1(bbox(RectC(_bounds.topLeft(), QRectF r1(bbox(RectC(_bounds.topLeft(),
Coordinates(180, _bounds.bottomRight().lat())), _map)); Coordinates(180, _bounds.bottomRight().lat())), map));
QRectF r2(bbox(RectC(Coordinates(-180, _bounds.topLeft().lat()), QRectF r2(bbox(RectC(Coordinates(-180, _bounds.topLeft().lat()),
_bounds.bottomRight()), _map)); _bounds.bottomRight()), map));
_painterPath.addRect(r1); _painterPath.addRect(r1);
_painterPath.addRect(r2); _painterPath.addRect(r2);
@ -143,10 +142,7 @@ void MapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option,
void MapItem::setMap(Map *map) void MapItem::setMap(Map *map)
{ {
prepareGeometryChange(); prepareGeometryChange();
updatePainterPath(map);
_map = map;
updatePainterPath();
} }
void MapItem::setColor(const QColor &color) void MapItem::setColor(const QColor &color)

View File

@ -4,13 +4,15 @@
#include "planeitem.h" #include "planeitem.h"
class MapAction; class MapAction;
class Projection;
class MapItem : public QObject, public PlaneItem class MapItem : public QObject, public PlaneItem
{ {
Q_OBJECT Q_OBJECT
public: public:
MapItem(MapAction *action, Map *map, GraphicsItem *parent = 0); MapItem(MapAction *action, Map *map, const Projection &proj,
GraphicsItem *parent = 0);
QPainterPath shape() const {return _painterPath;} QPainterPath shape() const {return _painterPath;}
QRectF boundingRect() const {return _painterPath.boundingRect();} QRectF boundingRect() const {return _painterPath.boundingRect();}
@ -37,13 +39,12 @@ protected:
void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
private: private:
void updatePainterPath(); void updatePainterPath(Map *map);
RectC _bounds; RectC _bounds;
QString _name; QString _name;
QString _fileName; QString _fileName;
Map *_map;
int _digitalZoom; int _digitalZoom;
qreal _width; qreal _width;

View File

@ -60,12 +60,12 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent)
_cursorCoordinates->setVisible(false); _cursorCoordinates->setVisible(false);
_scene->addItem(_cursorCoordinates); _scene->addItem(_cursorCoordinates);
_deviceRatio = devicePixelRatioF();
_outputProjection = PCS::pcs(3857); _outputProjection = PCS::pcs(3857);
_inputProjection = GCS::gcs(4326); _inputProjection = GCS::gcs(4326);
_hidpi = true;
_map = map; _map = map;
_map->load(); _map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
_map->setOutputProjection(_outputProjection);
_map->setInputProjection(_inputProjection);
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
_poi = poi; _poi = poi;
@ -119,8 +119,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent)
_showPositionCoordinates = false; _showPositionCoordinates = false;
_showMotionInfo = false; _showMotionInfo = false;
_deviceRatio = 1.0;
_mapRatio = 1.0;
_opengl = false; _opengl = false;
_plot = false; _plot = false;
_digitalZoom = 0; _digitalZoom = 0;
@ -247,7 +245,7 @@ void MapView::addWaypoints(const QVector<Waypoint> &waypoints)
MapItem *MapView::addMap(MapAction *map) MapItem *MapView::addMap(MapAction *map)
{ {
MapItem *mi = new MapItem(map, _map); MapItem *mi = new MapItem(map, _map, _inputProjection);
mi->setColor(_palette.nextColor()); mi->setColor(_palette.nextColor());
mi->setWidth(_areaWidth); mi->setWidth(_areaWidth);
mi->setPenStyle(_areaStyle); mi->setPenStyle(_areaStyle);
@ -328,7 +326,7 @@ int MapView::fitMapZoom() const
RectC br = _tr | _rr | _wr | _ar; RectC br = _tr | _rr | _wr | _ar;
return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN), return _map->zoomFit(viewport()->size() - QSize(2*MARGIN, 2*MARGIN),
br.isNull() ? _map->llBounds() : br); br.isNull() ? _map->llBounds(_inputProjection) : br);
} }
QPointF MapView::contentCenter() const QPointF MapView::contentCenter() const
@ -402,36 +400,18 @@ void MapView::setMap(Map *map)
.intersected(_map->bounds())); .intersected(_map->bounds()));
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight())); RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
_map->unload();
disconnect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); disconnect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
_map->unload();
_map = map; _map = map;
_map->load(); _map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi);
_map->setOutputProjection(_outputProjection);
_map->setInputProjection(_inputProjection);
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap);
digitalZoom(0); digitalZoom(0);
_map->zoomFit(viewport()->rect().size(), cr); _map->zoomFit(viewport()->rect().size(), cr);
_scene->setSceneRect(_map->bounds());
for (int i = 0; i < _tracks.size(); i++) rescale();
_tracks.at(i)->setMap(_map);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->setMap(_map);
for (int i = 0; i < _areas.size(); i++)
_areas.at(i)->setMap(_map);
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->setMap(_map);
for (POIHash::const_iterator it = _pois.constBegin();
it != _pois.constEnd(); it++)
it.value()->setMap(_map);
updatePOIVisibility();
_crosshair->setMap(_map);
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()), QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
_map->ll2xy(cr.bottomRight())).center(); _map->ll2xy(cr.bottomRight())).center();
@ -702,8 +682,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
PlotFlags flags) PlotFlags flags)
{ {
QRect orig, adj; QRect orig, adj;
qreal mapRatio, ratio, diff, q, p; qreal ratio, diff, q, p;
QPointF scenePos, scalePos, posPos, motionPos; QPointF scenePos, scalePos, posPos, motionPos;
bool hidpi = _hidpi && _deviceRatio > 1.0;
int zoom; int zoom;
@ -728,8 +709,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
} }
// Expand the view if plotting into a bitmap // Expand the view if plotting into a bitmap
mapRatio = _mapRatio; if (hidpi)
setDevicePixelRatio(_deviceRatio, 1.0); setHidpi(false);
if (flags & Expand) { if (flags & Expand) {
qreal xdiff = (target.width() - adj.width()) / 2.0; qreal xdiff = (target.width() - adj.width()) / 2.0;
@ -784,7 +765,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale,
centerOn(scenePos); centerOn(scenePos);
} }
setDevicePixelRatio(_deviceRatio, mapRatio); if (hidpi)
setHidpi(true);
_mapScale->setDigitalZoom(_digitalZoom); _mapScale->setDigitalZoom(_digitalZoom);
_mapScale->setPos(scalePos); _mapScale->setPos(scalePos);
@ -1236,6 +1218,9 @@ bool MapView::gestureEvent(QGestureEvent *event)
void MapView::useOpenGL(bool use) void MapView::useOpenGL(bool use)
{ {
if (_opengl == use)
return;
_opengl = use; _opengl = use;
if (use) if (use)
@ -1286,60 +1271,21 @@ void MapView::reloadMap()
_scene->invalidate(); _scene->invalidate();
} }
void MapView::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void MapView::setMapConfig(const Projection &in, const Projection &out,
bool hidpi)
{ {
if (_deviceRatio == deviceRatio && _mapRatio == mapRatio) _inputProjection = in;
return; _outputProjection = out;
_hidpi = hidpi;
_deviceRatio = deviceRatio; setMap(_map);
_mapRatio = mapRatio;
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
.intersected(_map->bounds()));
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
_map->setDevicePixelRatio(_deviceRatio, _mapRatio);
_scene->setSceneRect(_map->bounds());
for (int i = 0; i < _tracks.size(); i++)
_tracks.at(i)->setMap(_map);
for (int i = 0; i < _routes.size(); i++)
_routes.at(i)->setMap(_map);
for (int i = 0; i < _areas.size(); i++)
_areas.at(i)->setMap(_map);
for (int i = 0; i < _waypoints.size(); i++)
_waypoints.at(i)->setMap(_map);
for (POIHash::const_iterator it = _pois.constBegin();
it != _pois.constEnd(); it++)
it.value()->setMap(_map);
updatePOIVisibility();
_crosshair->setMap(_map);
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
_map->ll2xy(cr.bottomRight())).center();
centerOn(nc);
reloadMap();
} }
void MapView::setOutputProjection(const Projection &proj) void MapView::setDevicePixelRatio(qreal ratio)
{ {
_outputProjection = proj; _deviceRatio = ratio;
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
_map->setOutputProjection(_outputProjection);
rescale();
centerOn(_map->ll2xy(center));
}
void MapView::setInputProjection(const Projection &proj) setMap(_map);
{
_inputProjection = proj;
Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center()));
_map->setInputProjection(_inputProjection);
rescale();
centerOn(_map->ll2xy(center));
} }
void MapView::fitContentToSize() void MapView::fitContentToSize()
@ -1436,3 +1382,20 @@ void MapView::drawInfoBackground(bool draw)
_positionCoordinates->drawBackground(draw); _positionCoordinates->drawBackground(draw);
_motionInfo->drawBackground(draw); _motionInfo->drawBackground(draw);
} }
void MapView::setHidpi(bool hidpi)
{
QRectF vr(mapToScene(viewport()->rect()).boundingRect()
.intersected(_map->bounds()));
RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight()));
_map->unload();
_map->load(_inputProjection, _outputProjection, _deviceRatio, hidpi);
rescale();
QPointF nc = QRectF(_map->ll2xy(cr.topLeft()),
_map->ll2xy(cr.bottomRight())).center();
centerOn(nc);
reloadMap();
}

View File

@ -92,9 +92,8 @@ public:
void useAntiAliasing(bool use); void useAntiAliasing(bool use);
void setCoordinatesFormat(CoordinatesFormat format); void setCoordinatesFormat(CoordinatesFormat format);
void setTimeZone(const QTimeZone &zone); void setTimeZone(const QTimeZone &zone);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void setMapConfig(const Projection &in, const Projection &out, bool hidpi);
void setOutputProjection(const Projection &proj); void setDevicePixelRatio(qreal ratio);
void setInputProjection(const Projection &proj);
void clearMapCache(); void clearMapCache();
void fitContentToSize(); void fitContentToSize();
@ -156,6 +155,7 @@ private:
bool gestureEvent(QGestureEvent *event); bool gestureEvent(QGestureEvent *event);
void pinchGesture(QPinchGesture *gesture); void pinchGesture(QPinchGesture *gesture);
void skipColor() {_palette.nextColor();} void skipColor() {_palette.nextColor();}
void setHidpi(bool hidpi);
void mouseMoveEvent(QMouseEvent *event); void mouseMoveEvent(QMouseEvent *event);
void mousePressEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event);
@ -209,7 +209,7 @@ private:
QCursor _cursor; QCursor _cursor;
qreal _deviceRatio; qreal _deviceRatio;
qreal _mapRatio; bool _hidpi;
bool _opengl; bool _opengl;
int _pinchZoom; int _pinchZoom;

View File

@ -252,8 +252,13 @@ AQMMap::AQMMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void AQMMap::load() void AQMMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_file.open(QIODevice::ReadOnly); _file.open(QIODevice::ReadOnly);
} }
@ -305,12 +310,6 @@ int AQMMap::zoomOut()
return _zoom; return _zoom;
} }
void AQMMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
}
QPointF AQMMap::ll2xy(const Coordinates &c) QPointF AQMMap::ll2xy(const Coordinates &c)
{ {
const Zoom &z = _zooms.at(_zoom); const Zoom &z = _zooms.at(_zoom);
@ -406,7 +405,7 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
painter->drawPixmap(tp, pixmap); painter->drawPixmap(tp, pixmap);
} }
Map *AQMMap::create(const QString &path, const Projection &, bool *isDir) Map *AQMMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -17,7 +17,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
@ -26,9 +26,9 @@ public:
int zoomIn(); int zoomIn();
int zoomOut(); int zoomOut();
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
@ -38,7 +38,7 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
struct File { struct File {

View File

@ -14,12 +14,7 @@
static bool resCmp(OziMap *m1, OziMap *m2) static bool resCmp(OziMap *m1, OziMap *m2)
{ {
qreal r1, r2; return m1->resolution(m1->bounds()) > m2->resolution(m2->bounds());
r1 = m1->resolution(m1->bounds());
r2 = m2->resolution(m2->bounds());
return r1 > r2;
} }
static bool xCmp(OziMap *m1, OziMap *m2) static bool xCmp(OziMap *m1, OziMap *m2)
@ -38,7 +33,7 @@ void Atlas::computeZooms()
_zooms.append(Zoom(0, _maps.count() - 1)); _zooms.append(Zoom(0, _maps.count() - 1));
for (int i = 1; i < _maps.count(); i++) { for (int i = 1; i < _maps.count(); i++) {
qreal last = _maps.at(i-1)->resolution(_maps.at(i)->bounds()); qreal last = _maps.at(i-1)->resolution(_maps.at(i-1)->bounds());
qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds()); qreal cur = _maps.at(i)->resolution(_maps.at(i)->bounds());
if (cur < last * ZOOM_THRESHOLD) { if (cur < last * ZOOM_THRESHOLD) {
_zooms.last().last = i-1; _zooms.last().last = i-1;
@ -136,18 +131,17 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
return; return;
} }
computeZooms();
computeBounds();
_valid = true; _valid = true;
} }
void Atlas::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) RectC Atlas::llBounds(const Projection &proj)
{ {
for (int i = 0; i < _maps.size(); i++) RectC bounds;
_maps[i]->setDevicePixelRatio(deviceRatio, mapRatio);
computeBounds(); for (int i = 0; i < _maps.size(); i++)
bounds |= _maps.at(i)->llBounds(proj);
return bounds;
} }
QRectF Atlas::bounds() QRectF Atlas::bounds()
@ -277,20 +271,31 @@ void Atlas::draw(QPainter *painter, const QRectF &rect, int mapIndex,
const QPointF offset = _bounds.at(mapIndex).xy.topLeft(); const QPointF offset = _bounds.at(mapIndex).xy.topLeft();
QRectF pr = QRectF(rect.topLeft() - offset, rect.size()); QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
map->load();
painter->translate(offset); painter->translate(offset);
map->draw(painter, pr, flags); map->draw(painter, pr, flags);
painter->translate(-offset); painter->translate(-offset);
} }
void Atlas::load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi)
{
for (int i = 0; i < _maps.count(); i++)
_maps.at(i)->load(in, out, deviceRatio, hidpi);
computeZooms();
computeBounds();
}
void Atlas::unload() void Atlas::unload()
{ {
for (int i = 0; i < _maps.count(); i++) for (int i = 0; i < _maps.count(); i++)
_maps.at(i)->unload(); _maps.at(i)->unload();
_zooms.clear();
_bounds.clear();
} }
Map *Atlas::createTAR(const QString &path, const Projection &, bool *isDir) Map *Atlas::createTAR(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = true; *isDir = true;
@ -298,7 +303,7 @@ Map *Atlas::createTAR(const QString &path, const Projection &, bool *isDir)
return new Atlas(path, true); return new Atlas(path, true);
} }
Map *Atlas::createTBA(const QString &path, const Projection &, bool *isDir) Map *Atlas::createTBA(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = true; *isDir = true;

View File

@ -3,6 +3,7 @@
#include "map.h" #include "map.h"
#include "rectd.h" #include "rectd.h"
#include "projection.h"
class OziMap; class OziMap;
@ -16,6 +17,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds(const Projection &proj);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -28,14 +30,15 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *createTAR(const QString &path, const Projection &, bool *isDir); static Map *createTAR(const QString &path, bool *isDir);
static Map *createTBA(const QString &path, const Projection &, bool *isDir); static Map *createTBA(const QString &path, bool *isDir);
private: private:
struct Zoom { struct Zoom {

View File

@ -390,7 +390,7 @@ QImage BSBMap::readImage()
} }
BSBMap::BSBMap(const QString &fileName, QObject *parent) BSBMap::BSBMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _img(0), _ratio(1.0), _dataOffset(-1), _valid(false) : Map(fileName, parent), _img(0), _mapRatio(1.0), _dataOffset(-1), _valid(false)
{ {
QFile file(fileName); QFile file(fileName);
@ -414,19 +414,19 @@ BSBMap::~BSBMap()
QPointF BSBMap::ll2xy(const Coordinates &c) QPointF BSBMap::ll2xy(const Coordinates &c)
{ {
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _ratio; return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _mapRatio;
} }
Coordinates BSBMap::xy2ll(const QPointF &p) Coordinates BSBMap::xy2ll(const QPointF &p)
{ {
return _projection.xy2ll(_transform.img2proj(p * _ratio)); return _projection.xy2ll(_transform.img2proj(p * _mapRatio));
} }
QRectF BSBMap::bounds() QRectF BSBMap::bounds()
{ {
return _skewSize.isValid() return _skewSize.isValid()
? QRectF(QPointF(0, 0), _skewSize / _ratio) ? QRectF(QPointF(0, 0), _skewSize / _mapRatio)
: QRectF(QPointF(0, 0), _size / _ratio); : QRectF(QPointF(0, 0), _size / _mapRatio);
} }
void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
@ -435,17 +435,14 @@ void BSBMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
_img->draw(painter, rect, flags); _img->draw(painter, rect, flags);
} }
void BSBMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void BSBMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(deviceRatio); Q_UNUSED(in);
Q_UNUSED(out);
_ratio = mapRatio; _mapRatio = hidpi ? deviceRatio : 1.0;
if (_img)
_img->setDevicePixelRatio(_ratio);
}
void BSBMap::load()
{
if (!_img) { if (!_img) {
if (_skew > 0.0 && _skew < 360.0) { if (_skew > 0.0 && _skew < 360.0) {
QTransform matrix; QTransform matrix;
@ -454,6 +451,9 @@ void BSBMap::load()
} else } else
_img = new Image(readImage()); _img = new Image(readImage());
} }
if (_img)
_img->setDevicePixelRatio(_mapRatio);
} }
void BSBMap::unload() void BSBMap::unload()
@ -462,7 +462,7 @@ void BSBMap::unload()
_img = 0; _img = 0;
} }
Map *BSBMap::create(const QString &path, const Projection &, bool *isMap) Map *BSBMap::create(const QString &path, bool *isMap)
{ {
if (isMap) if (isMap)
*isMap = false; *isMap = false;

View File

@ -25,14 +25,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isMap); static Map *create(const QString &path, bool *isMap);
private: private:
bool parseBSB(const QByteArray &line); bool parseBSB(const QByteArray &line);
@ -56,7 +56,7 @@ private:
Image *_img; Image *_img;
QSize _size; QSize _size;
QSize _skewSize; QSize _skewSize;
qreal _ratio; qreal _mapRatio;
qint64 _dataOffset; qint64 _dataOffset;
QVector<QRgb> _palette; QVector<QRgb> _palette;

View File

@ -14,7 +14,7 @@ public:
QString name() const {return QString();} QString name() const {return QString();}
QRectF bounds(); QRectF bounds();
RectC llBounds() {return OSM::BOUNDS;} RectC llBounds(const Projection &) {return OSM::BOUNDS;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}

View File

@ -22,9 +22,16 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent)
} }
} }
void ENCMap::load() void ENCMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(hidpi);
_tileRatio = deviceRatio;
_projection = out;
_data.load(); _data.load();
QPixmapCache::clear();
} }
void ENCMap::unload() void ENCMap::unload()
@ -218,24 +225,7 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
void ENCMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Map *ENCMap::create(const QString &path, bool *isMap)
{
Q_UNUSED(mapRatio);
_tileRatio = deviceRatio;
}
void ENCMap::setOutputProjection(const Projection &projection)
{
if (!projection.isValid() || projection == _projection)
return;
_projection = projection;
updateTransform();
QPixmapCache::clear();
}
Map *ENCMap::create(const QString &path, const Projection &, bool *isMap)
{ {
if (isMap) if (isMap)
*isMap = false; *isMap = false;

View File

@ -53,7 +53,7 @@ public:
QString name() const {return _data.name();} QString name() const {return _data.name();}
QRectF bounds() {return _bounds;} QRectF bounds() {return _bounds;}
RectC llBounds() {return _llBounds;} RectC llBounds(const Projection &) {return _llBounds;}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -61,10 +61,9 @@ public:
int zoomIn(); int zoomIn();
int zoomOut(); int zoomOut();
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setOutputProjection(const Projection &projection);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
QPointF ll2xy(const Coordinates &c) QPointF ll2xy(const Coordinates &c)
{return _transform.proj2img(_projection.ll2xy(c));} {return _transform.proj2img(_projection.ll2xy(c));}
@ -76,7 +75,7 @@ public:
bool isValid() const {return _data.isValid();} bool isValid() const {return _data.isValid();}
QString errorString() const {return _data.errorString();} QString errorString() const {return _data.errorString();}
static Map *create(const QString &path, const Projection &, bool *isMap); static Map *create(const QString &path, bool *isMap);
private slots: private slots:
void jobFinished(ENCMapJob *job); void jobFinished(ENCMapJob *job);

View File

@ -182,8 +182,13 @@ Coordinates GEMFMap::xy2ll(const QPointF &p)
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio); return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
} }
void GEMFMap::load() void GEMFMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_file.open(QIODevice::ReadOnly); _file.open(QIODevice::ReadOnly);
} }
@ -296,7 +301,7 @@ void GEMFMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp)
painter->drawPixmap(tp, pixmap); painter->drawPixmap(tp, pixmap);
} }
Map *GEMFMap::create(const QString &path, const Projection &, bool *isDir) Map *GEMFMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -14,7 +14,7 @@ public:
GEMFMap(const QString &fileName, QObject *parent = 0); GEMFMap(const QString &fileName, QObject *parent = 0);
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
int zoom() const {return _zi;} int zoom() const {return _zi;}
void setZoom(int zoom) {_zi = zoom;} void setZoom(int zoom) {_zi = zoom;}
@ -26,18 +26,16 @@ public:
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
struct Region { struct Region {

View File

@ -54,28 +54,26 @@ void GeoTIFFMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
_img->draw(painter, rect, flags); _img->draw(painter, rect, flags);
} }
void GeoTIFFMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void GeoTIFFMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(deviceRatio); Q_UNUSED(in);
Q_UNUSED(out);
_ratio = mapRatio; _ratio = hidpi ? deviceRatio : 1.0;
_img = new Image(path());
if (_img) if (_img)
_img->setDevicePixelRatio(_ratio); _img->setDevicePixelRatio(_ratio);
} }
void GeoTIFFMap::load()
{
if (!_img)
_img = new Image(path());
}
void GeoTIFFMap::unload() void GeoTIFFMap::unload()
{ {
delete _img; delete _img;
_img = 0; _img = 0;
} }
Map *GeoTIFFMap::create(const QString &path, const Projection &, bool *isDir) Map *GeoTIFFMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -21,14 +21,15 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
Projection _projection; Projection _projection;

View File

@ -18,6 +18,21 @@ using namespace IMG;
#define TILE_SIZE 384 #define TILE_SIZE 384
#define TEXT_EXTENT 160 #define TEXT_EXTENT 160
static RectC limitBounds(const RectC &bounds, const Projection &proj)
{
/* Limit the bounds for some well known projections
(world maps have N/S bounds up to 90/-90!) */
if (proj == PCS::pcs(3857) || proj == PCS::pcs(3395))
return bounds & OSM::BOUNDS;
else if (proj == PCS::pcs(3031) || proj == PCS::pcs(3976))
return bounds & RectC(Coordinates(-180, -60), Coordinates(180, -90));
else if (proj == PCS::pcs(3995) || proj == PCS::pcs(3413))
return bounds & RectC(Coordinates(-180, 90), Coordinates(180, 60));
else
return bounds;
}
static QList<MapData*> overlays(const QString &fileName) static QList<MapData*> overlays(const QString &fileName)
{ {
QList<MapData*> list; QList<MapData*> list;
@ -56,17 +71,27 @@ IMGMap::IMGMap(const QString &fileName, bool GMAP, QObject *parent)
return; return;
} }
_dataBounds = _data.first()->bounds() & OSM::BOUNDS;
_zoom = _data.first()->zooms().min(); _zoom = _data.first()->zooms().min();
updateTransform();
_valid = true; _valid = true;
} }
void IMGMap::load() void IMGMap::load(const Projection &in, const Projection &out,
qreal devicelRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(hidpi);
_tileRatio = devicelRatio;
_projection = out;
_dataBounds = limitBounds(_data.first()->bounds(), _projection);
for (int i = 0; i < _data.size(); i++) for (int i = 0; i < _data.size(); i++)
_data.at(i)->load(); _data.at(i)->load();
updateTransform();
QPixmapCache::clear();
} }
void IMGMap::unload() void IMGMap::unload()
@ -261,37 +286,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Map* IMGMap::createIMG(const QString &path, bool *isDir)
{
Q_UNUSED(mapRatio);
_tileRatio = deviceRatio;
}
void IMGMap::setOutputProjection(const Projection &projection)
{
if (!projection.isValid() || projection == _projection)
return;
_projection = projection;
// Limit the bounds for some well known projections
// (world maps have N/S bounds up to 90/-90!)
if (_projection == PCS::pcs(3857) || _projection == PCS::pcs(3395))
_dataBounds = _data.first()->bounds() & OSM::BOUNDS;
else if (_projection == PCS::pcs(3031) || _projection == PCS::pcs(3976))
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, -60),
Coordinates(180, -90));
else if (_projection == PCS::pcs(3995) || _projection == PCS::pcs(3413))
_dataBounds = _data.first()->bounds() & RectC(Coordinates(-180, 90),
Coordinates(180, 60));
else
_dataBounds = _data.first()->bounds();
updateTransform();
QPixmapCache::clear();
}
Map* IMGMap::createIMG(const QString &path, const Projection &, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;
@ -299,7 +294,7 @@ Map* IMGMap::createIMG(const QString &path, const Projection &, bool *isDir)
return new IMGMap(path, false); return new IMGMap(path, false);
} }
Map* IMGMap::createGMAP(const QString &path, const Projection &, bool *isDir) Map* IMGMap::createGMAP(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = true; *isDir = true;

View File

@ -55,7 +55,7 @@ public:
QString name() const {return _data.first()->name();} QString name() const {return _data.first()->name();}
QRectF bounds() {return _bounds;} QRectF bounds() {return _bounds;}
RectC llBounds() {return _dataBounds;} RectC llBounds(const Projection &) {return _data.first()->bounds();}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -70,17 +70,15 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setOutputProjection(const Projection &projection); void load(const Projection &in, const Projection &out, qreal devicelRatio,
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool hidpi);
void load();
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map* createIMG(const QString &path, const Projection &, bool *isDir); static Map* createIMG(const QString &path, bool *isDir);
static Map* createGMAP(const QString &path, const Projection &, bool *isDir); static Map* createGMAP(const QString &path, bool *isDir);
private slots: private slots:
void jobFinished(IMGMapJob *job); void jobFinished(IMGMapJob *job);

View File

@ -11,22 +11,6 @@
#define ic2dc(x) ((x) * 180.0 / 0x7FFFFFFF) #define ic2dc(x) ((x) * 180.0 / 0x7FFFFFFF)
struct Level {
quint32 count;
quint32 offset;
quint32 scale;
};
struct Ctx {
QPainter *painter;
QFile *file;
qreal ratio;
Ctx(QPainter *painter, QFile *file, qreal ratio)
: painter(painter), file(file), ratio(ratio) {}
};
template<class T> bool JNXMap::readValue(T &val) template<class T> bool JNXMap::readValue(T &val)
{ {
T data; T data;
@ -53,7 +37,7 @@ bool JNXMap::readString(QByteArray& ba)
} }
} }
bool JNXMap::readTiles() bool JNXMap::readHeader()
{ {
qint32 lat1, lon2, lat2, lon1; qint32 lat1, lon2, lat2, lon1;
quint32 version, dummy, levels; quint32 version, dummy, levels;
@ -88,16 +72,22 @@ bool JNXMap::readTiles()
} }
_zooms.reserve(lh.size()); _zooms.reserve(lh.size());
for (int i = 0; i < lh.count(); i++) { for (int i = 0; i < lh.count(); i++)
_zooms.append(new Zoom()); _zooms.append(new Zoom(lh.at(i)));
Zoom *z = _zooms.last();
const Level &l = lh.at(i);
if (!_file.seek(l.offset)) return true;
}
bool JNXMap::readTiles()
{
for (int i = 0; i < _zooms.size(); i++) {
Zoom *z = _zooms[i];
if (!_file.seek(z->level.offset))
return false; return false;
z->tiles = QVector<Tile>(l.count); z->tiles = QVector<Tile>(z->level.count);
for (quint32 j = 0; j < l.count; j++) { for (quint32 j = 0; j < z->level.count; j++) {
Tile &tile = z->tiles[j]; Tile &tile = z->tiles[j];
if (!(readValue(tile.top) && readValue(tile.right) if (!(readValue(tile.top) && readValue(tile.right)
@ -134,16 +124,25 @@ bool JNXMap::readTiles()
return true; return true;
} }
JNXMap::JNXMap(const QString &fileName, const Projection &proj, QObject *parent) void JNXMap::clearTiles()
: Map(fileName, parent), _file(fileName), _zoom(0), _projection(proj), {
_mapRatio(1.0), _valid(false) for (int i = 0; i < _zooms.size(); i++) {
Zoom *z = _zooms[i];
z->tiles.clear();
z->tree.RemoveAll();
}
}
JNXMap::JNXMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _file(fileName), _zoom(0), _mapRatio(1.0),
_valid(false)
{ {
if (!_file.open(QIODevice::ReadOnly)) { if (!_file.open(QIODevice::ReadOnly)) {
_errorString = fileName + ": " + _file.errorString(); _errorString = _file.errorString();
return; return;
} }
if (!readTiles()) { if (!readHeader()) {
_errorString = "JNX file format error"; _errorString = "JNX file format error";
return; return;
} }
@ -158,14 +157,22 @@ JNXMap::~JNXMap()
qDeleteAll(_zooms); qDeleteAll(_zooms);
} }
void JNXMap::load() void JNXMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
_file.open(QIODevice::ReadOnly); Q_UNUSED(out);
_projection = in;
_mapRatio = hidpi ? deviceRatio : 1.0;
if (_file.open(QIODevice::ReadOnly))
readTiles();
} }
void JNXMap::unload() void JNXMap::unload()
{ {
_file.close(); _file.close();
clearTiles();
} }
QPointF JNXMap::ll2xy(const Coordinates &c) QPointF JNXMap::ll2xy(const Coordinates &c)
@ -267,51 +274,10 @@ void JNXMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
tree.Search(min, max, cb, &ctx); tree.Search(min, max, cb, &ctx);
} }
void JNXMap::setInputProjection(const Projection &projection) Map *JNXMap::create(const QString &path, bool *isDir)
{
if (!projection.isValid() || projection == _projection)
return;
_projection = projection;
for (int i = 0; i < _zooms.size(); i++) {
Zoom *z = _zooms[i];
z->tree.RemoveAll();
for (int j = 0; j < z->tiles.size(); j++) {
Tile &tile = z->tiles[j];
RectC llrect(Coordinates(ic2dc(tile.left), ic2dc(tile.top)),
Coordinates(ic2dc(tile.right), ic2dc(tile.bottom)));
RectD rect(_projection.ll2xy(llrect.topLeft()),
_projection.ll2xy(llrect.bottomRight()));
if (j == 0) {
ReferencePoint tl(PointD(0, 0), rect.topLeft());
ReferencePoint br(PointD(tile.width, tile.height),
rect.bottomRight());
z->transform = Transform(tl, br);
}
QRectF trect(z->transform.proj2img(rect.topLeft()),
z->transform.proj2img(rect.bottomRight()));
tile.pos = trect.topLeft();
qreal min[2], max[2];
min[0] = trect.left();
min[1] = trect.top();
max[0] = trect.right();
max[1] = trect.bottom();
z->tree.Insert(min, max, &tile);
}
}
}
Map *JNXMap::create(const QString &path, const Projection &proj, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;
return new JNXMap(path, proj); return new JNXMap(path);
} }

View File

@ -15,11 +15,11 @@ public:
Q_OBJECT Q_OBJECT
public: public:
JNXMap(const QString &fileName, const Projection &proj, QObject *parent = 0); JNXMap(const QString &fileName, QObject *parent = 0);
~JNXMap(); ~JNXMap();
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom) {_zoom = zoom;} void setZoom(int zoom) {_zoom = zoom;}
@ -30,19 +30,16 @@ public:
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setInputProjection(const Projection &projection);
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
struct Tile { struct Tile {
@ -54,15 +51,37 @@ private:
QPointF pos; QPointF pos;
}; };
struct Level {
quint32 count;
quint32 offset;
quint32 scale;
};
struct Zoom { struct Zoom {
Zoom() {}
Zoom(const Level &level) : level(level) {}
Level level;
Transform transform; Transform transform;
QVector<Tile> tiles; QVector<Tile> tiles;
RTree<Tile*, qreal, 2> tree; RTree<Tile*, qreal, 2> tree;
}; };
struct Ctx {
QPainter *painter;
QFile *file;
qreal ratio;
Ctx(QPainter *painter, QFile *file, qreal ratio)
: painter(painter), file(file), ratio(ratio) {}
};
template<class T> bool readValue(T &val); template<class T> bool readValue(T &val);
bool readString(QByteArray &ba); bool readString(QByteArray &ba);
bool readHeader();
bool readTiles(); bool readTiles();
void clearTiles();
static bool cb(Tile *tile, void *context); static bool cb(Tile *tile, void *context);
static QPixmap pixmap(const Tile *tile, QFile *file); static QPixmap pixmap(const Tile *tile, QFile *file);

View File

@ -13,14 +13,12 @@
#include <QFileInfo> #include <QFileInfo>
#include <QXmlStreamReader> #include <QXmlStreamReader>
#include <QImage>
#include <QImageReader>
#include <QBuffer> #include <QBuffer>
#include <QImageReader>
#include <QPainter> #include <QPainter>
#include <QPixmapCache>
#include <private/qzipreader_p.h> #include <private/qzipreader_p.h>
#include"common/util.h" #include "common/util.h"
#include "pcs.h"
#include "image.h"
#include "kmzmap.h" #include "kmzmap.h"
@ -29,162 +27,140 @@
#define TL(m) ((m).bbox().topLeft()) #define TL(m) ((m).bbox().topLeft())
#define BR(m) ((m).bbox().bottomRight()) #define BR(m) ((m).bbox().bottomRight())
bool KMZMap::resCmp(const Tile &m1, const Tile &m2)
KMZMap::Overlay::Overlay(const QString &path, const QSize &size,
const RectC &bbox, double rotation, const Projection *proj, qreal ratio)
: _path(path), _size(size), _bbox(bbox), _rotation(rotation), _img(0),
_proj(proj), _ratio(ratio)
{ {
ReferencePoint tl(PointD(0, 0), _proj->ll2xy(bbox.topLeft())); return m1.resolution() > m2.resolution();
ReferencePoint br(PointD(size.width(), size.height()),
_proj->ll2xy(bbox.bottomRight()));
QTransform t;
t.rotate(-rotation);
QRectF b(0, 0, size.width(), size.height());
QPolygonF ma = t.map(b);
_bounds = ma.boundingRect();
_transform = Transform(tl, br);
} }
qreal KMZMap::Overlay::resolution(const QRectF &rect) const bool KMZMap::xCmp(const Tile &m1, const Tile &m2)
{
qreal cy = rect.center().y();
QPointF cl(rect.left(), cy);
QPointF cr(rect.right(), cy);
qreal ds = xy2ll(cl).distanceTo(xy2ll(cr));
qreal ps = QLineF(cl, cr).length();
return ds/ps;
}
void KMZMap::Overlay::draw(QPainter *painter, const QRectF &rect, Flags flags)
{
if (_img) {
QRectF rr(rect.topLeft() / _ratio, rect.size());
if (_rotation) {
painter->save();
painter->rotate(-_rotation);
_img->draw(painter, rr, flags);
painter->restore();
} else
_img->draw(painter, rr, flags);
}
//painter->setPen(Qt::red);
//painter->drawRect(_bounds);
}
void KMZMap::Overlay::load(QZipReader *zip)
{
if (!_img) {
QByteArray ba(zip->fileData(_path));
_img = new Image(QImage::fromData(ba));
_img->setDevicePixelRatio(_ratio);
}
}
void KMZMap::Overlay::unload()
{
delete _img;
_img = 0;
}
void KMZMap::Overlay::setProjection(const Projection *proj)
{
_proj = proj;
ReferencePoint tl(PointD(0, 0), _proj->ll2xy(_bbox.topLeft()));
ReferencePoint br(PointD(_size.width(), _size.height()),
_proj->ll2xy(_bbox.bottomRight()));
QTransform t;
t.rotate(-_rotation);
QRectF b(0, 0, _size.width(), _size.height());
QPolygonF ma = t.map(b);
_bounds = ma.boundingRect();
_transform = Transform(tl, br);
}
void KMZMap::Overlay::setDevicePixelRatio(qreal ratio)
{
_ratio = ratio;
if (_img)
_img->setDevicePixelRatio(_ratio);
}
bool KMZMap::resCmp(const Overlay &m1, const Overlay &m2)
{
qreal r1, r2;
r1 = m1.resolution(m1.bounds());
r2 = m2.resolution(m2.bounds());
return r1 > r2;
}
bool KMZMap::xCmp(const Overlay &m1, const Overlay &m2)
{ {
return TL(m1).lon() < TL(m2).lon(); return TL(m1).lon() < TL(m2).lon();
} }
bool KMZMap::yCmp(const Overlay &m1, const Overlay &m2) bool KMZMap::yCmp(const Tile &m1, const Tile &m2)
{ {
return TL(m1).lat() > TL(m2).lat(); return TL(m1).lat() > TL(m2).lat();
} }
KMZMap::Tile::Tile(const Overlay &overlay, QZipReader &zip)
: _overlay(overlay)
{
QByteArray ba(zip.fileData(overlay.path()));
QBuffer img(&ba);
QImageReader ir(&img);
_size = ir.size();
}
void KMZMap::Tile::configure(const Projection &proj)
{
ReferencePoint tl(PointD(0, 0), proj.ll2xy(bbox().topLeft()));
ReferencePoint br(PointD(_size.width(), _size.height()),
proj.ll2xy(bbox().bottomRight()));
_transform = Transform(tl, br);
}
QRectF KMZMap::Tile::bounds() const
{
QTransform t;
t.rotate(-rotation());
QRectF b(0, 0, _size.width(), _size.height());
QPolygonF ma(t.map(b));
return ma.boundingRect();
}
qreal KMZMap::Tile::resolution() const
{
QRectF d(0, 0, _size.width(), _size.height());
qreal dy = d.center().y();
QPointF dl(d.left(), dy);
QPointF dr(d.right(), dy);
double cy = bbox().center().lat();
Coordinates cl(bbox().left(), cy);
Coordinates cr(bbox().right(), cy);
qreal ds = cl.distanceTo(cr);
qreal ps = QLineF(dl, dr).length();
return ds/ps;
}
bool KMZMap::createTiles(const QList<Overlay> &overlays, QZipReader &zip)
{
if (overlays.isEmpty()) {
_errorString = "No usable overlay found";
return false;
}
_tiles.reserve(overlays.size());
for (int i = 0; i < overlays.size(); i++) {
const Overlay &ol = overlays.at(i);
Tile tile(ol, zip);
if (tile.isValid())
_tiles.append(tile);
else {
_errorString = ol.path() + ": invalid/missing overlay image";
return false;
}
}
return true;
}
void KMZMap::computeLLBounds()
{
for (int i = 0; i < _tiles.size(); i++)
_llbounds |= _tiles.at(i).bbox();
}
void KMZMap::computeZooms() void KMZMap::computeZooms()
{ {
std::sort(_maps.begin(), _maps.end(), resCmp); std::sort(_tiles.begin(), _tiles.end(), resCmp);
_zooms.append(Zoom(0, _maps.count() - 1)); _zooms.append(Zoom(0, _tiles.count() - 1));
for (int i = 1; i < _maps.count(); i++) { for (int i = 1; i < _tiles.count(); i++) {
qreal last = _maps.at(i-1).resolution(_maps.at(i).bounds()); qreal last = _tiles.at(i-1).resolution();
qreal cur = _maps.at(i).resolution(_maps.at(i).bounds()); qreal cur = _tiles.at(i).resolution();
if (cur < last * ZOOM_THRESHOLD) { if (cur < last * ZOOM_THRESHOLD) {
_zooms.last().last = i-1; _zooms.last().last = i-1;
_zooms.append(Zoom(i, _maps.count() - 1)); _zooms.append(Zoom(i, _tiles.count() - 1));
} }
} }
} }
void KMZMap::computeBounds() void KMZMap::computeBounds()
{ {
QVector<QPointF> offsets(_maps.count()); QVector<QPointF> offsets(_tiles.count());
for (int z = 0; z < _zooms.count(); z++) { for (int z = 0; z < _zooms.count(); z++) {
QList<Overlay> m; QList<Tile> m;
for (int i = _zooms.at(z).first; i <= _zooms.at(z).last; i++) for (int i = _zooms.at(z).first; i <= _zooms.at(z).last; i++)
m.append(_maps.at(i)); m.append(_tiles.at(i));
std::sort(m.begin(), m.end(), xCmp); std::sort(m.begin(), m.end(), xCmp);
offsets[_maps.indexOf(m.first())].setX(m.first().bounds().left()); offsets[_tiles.indexOf(m.first())].setX(m.first().bounds().left());
for (int i = 1; i < m.size(); i++) { for (int i = 1; i < m.size(); i++) {
qreal w = m.first().ll2xy(TL(m.at(i))).x(); qreal w = ll2xy(TL(m.at(i)), m.first().transform()).x();
offsets[_maps.indexOf(m.at(i))].setX(w + m.at(i).bounds().left()); offsets[_tiles.indexOf(m.at(i))].setX(w + m.at(i).bounds().left());
} }
std::sort(m.begin(), m.end(), yCmp); std::sort(m.begin(), m.end(), yCmp);
offsets[_maps.indexOf(m.first())].setY(m.first().bounds().top()); offsets[_tiles.indexOf(m.first())].setY(m.first().bounds().top());
for (int i = 1; i < m.size(); i++) { for (int i = 1; i < m.size(); i++) {
qreal h = m.first().ll2xy(TL(m.at(i))).y(); qreal h = ll2xy(TL(m.at(i)), m.first().transform()).y();
offsets[_maps.indexOf(m.at(i))].setY(h + m.at(i).bounds().top()); offsets[_tiles.indexOf(m.at(i))].setY(h + m.at(i).bounds().top());
} }
} }
_adjust = 0; _adjust = 0;
_bounds = QVector<Bounds>(_maps.count()); _bounds = QVector<Bounds>(_tiles.count());
for (int i = 0; i < _maps.count(); i++) { for (int i = 0; i < _tiles.count(); i++) {
QRectF xy(offsets.at(i), _maps.at(i).bounds().size()); QRectF xy(offsets.at(i), _tiles.at(i).bounds().size());
_bounds[i] = Bounds(_maps.at(i).bbox(), xy); _bounds[i] = Bounds(_tiles.at(i).bbox(), xy);
_adjust = qMin(qMin(_maps.at(i).bounds().left(), _adjust = qMin(qMin(_tiles.at(i).bounds().left(),
_maps.at(i).bounds().top()), _adjust); _tiles.at(i).bounds().top()), _adjust);
} }
_adjust = -_adjust; _adjust = -_adjust;
} }
@ -236,7 +212,7 @@ RectC KMZMap::latLonBox(QXmlStreamReader &reader, double *rotation)
return RectC(Coordinates(left, top), Coordinates(right, bottom)); return RectC(Coordinates(left, top), Coordinates(right, bottom));
} }
void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip) void KMZMap::groundOverlay(QXmlStreamReader &reader, QList<Overlay> &overlays)
{ {
QString image; QString image;
RectC rect; RectC rect;
@ -251,93 +227,87 @@ void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip)
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
if (rect.isValid()) { if (rect.isValid())
QByteArray ba(zip.fileData(image)); overlays.append(Overlay(image, rect, rotation));
QBuffer img(&ba); else
QImageReader ir(&img);
QSize size(ir.size());
if (size.isValid())
_maps.append(Overlay(image, size, rect, rotation, &_projection,
_ratio));
else
reader.raiseError(image + ": Invalid image file");
} else
reader.raiseError("Invalid LatLonBox"); reader.raiseError("Invalid LatLonBox");
} }
void KMZMap::document(QXmlStreamReader &reader, QZipReader &zip) void KMZMap::document(QXmlStreamReader &reader, QList<Overlay> &overlays)
{ {
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("Document")) if (reader.name() == QLatin1String("Document"))
document(reader, zip); document(reader, overlays);
else if (reader.name() == QLatin1String("GroundOverlay")) else if (reader.name() == QLatin1String("GroundOverlay"))
groundOverlay(reader, zip); groundOverlay(reader, overlays);
else if (reader.name() == QLatin1String("Folder")) else if (reader.name() == QLatin1String("Folder"))
folder(reader, zip); folder(reader, overlays);
else else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
} }
void KMZMap::folder(QXmlStreamReader &reader, QZipReader &zip) void KMZMap::folder(QXmlStreamReader &reader, QList<Overlay> &overlays)
{ {
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("GroundOverlay")) if (reader.name() == QLatin1String("GroundOverlay"))
groundOverlay(reader, zip); groundOverlay(reader, overlays);
else if (reader.name() == QLatin1String("Folder")) else if (reader.name() == QLatin1String("Folder"))
folder(reader, zip); folder(reader, overlays);
else else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
} }
void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip) void KMZMap::kml(QXmlStreamReader &reader, QList<Overlay> &overlays)
{ {
while (reader.readNextStartElement()) { while (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("Document")) if (reader.name() == QLatin1String("Document"))
document(reader, zip); document(reader, overlays);
else if (reader.name() == QLatin1String("GroundOverlay")) else if (reader.name() == QLatin1String("GroundOverlay"))
groundOverlay(reader, zip); groundOverlay(reader, overlays);
else if (reader.name() == QLatin1String("Folder")) else if (reader.name() == QLatin1String("Folder"))
folder(reader, zip); folder(reader, overlays);
else else
reader.skipCurrentElement(); reader.skipCurrentElement();
} }
} }
KMZMap::KMZMap(const QString &fileName, const Projection &proj, QObject *parent) KMZMap::KMZMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _projection(proj), : Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _mapRatio(1.0),
_ratio(1.0), _valid(false) _valid(false)
{ {
QZipReader zip(fileName, QIODevice::ReadOnly); QZipReader zip(fileName, QIODevice::ReadOnly);
QByteArray xml(zip.fileData("doc.kml")); QByteArray xml(zip.fileData("doc.kml"));
QXmlStreamReader reader(xml); QXmlStreamReader reader(xml);
QList<Overlay> overlays;
if (reader.readNextStartElement()) { if (reader.readNextStartElement()) {
if (reader.name() == QLatin1String("kml")) if (reader.name() == QLatin1String("kml"))
kml(reader, zip); kml(reader, overlays);
else else
reader.raiseError("Not a KMZ file"); reader.raiseError("Not a KMZ file");
} }
if (reader.error()) { if (reader.error()) {
_errorString = "doc.kml:" + QString::number(reader.lineNumber()) + ": " _errorString = "doc.kml:" + QString::number(reader.lineNumber()) + ": "
+ reader.errorString(); + reader.errorString();
return; return;
} }
if (_maps.isEmpty()) {
_errorString = "No usable GroundOverlay found";
return;
}
if (!createTiles(overlays, zip))
return;
computeLLBounds();
computeZooms(); computeZooms();
computeBounds();
_valid = true; _valid = true;
} }
KMZMap::~KMZMap()
{
delete _zip;
}
QRectF KMZMap::bounds() QRectF KMZMap::bounds()
{ {
QRectF rect; QRectF rect;
@ -364,8 +334,9 @@ int KMZMap::zoomFit(const QSize &size, const RectC &br)
if (!_bounds.at(i).ll.contains(br.center())) if (!_bounds.at(i).ll.contains(br.center()))
continue; continue;
QRect sbr = QRectF(_maps.at(i).ll2xy(br.topLeft()), QRect sbr = QRectF(ll2xy(br.topLeft(), _tiles.at(i).transform()),
_maps.at(i).ll2xy(br.bottomRight())).toRect().normalized(); ll2xy(br.bottomRight(), _tiles.at(i).transform()))
.toRect().normalized();
if (sbr.size().width() > size.width() if (sbr.size().width() > size.width()
|| sbr.size().height() > size.height()) || sbr.size().height() > size.height())
@ -413,10 +384,10 @@ QPointF KMZMap::ll2xy(const Coordinates &c)
} }
} }
QPointF p = _maps.at(_mapIndex).ll2xy(c); QPointF p = ll2xy(c, _tiles.at(_mapIndex).transform());
if (_maps.at(_mapIndex).rotation()) { if (_tiles.at(_mapIndex).rotation()) {
QTransform matrix; QTransform matrix;
matrix.rotate(-_maps.at(_mapIndex).rotation()); matrix.rotate(-_tiles.at(_mapIndex).rotation());
return matrix.map(p) + _bounds.at(_mapIndex).xy.topLeft(); return matrix.map(p) + _bounds.at(_mapIndex).xy.topLeft();
} else } else
return p + _bounds.at(_mapIndex).xy.topLeft(); return p + _bounds.at(_mapIndex).xy.topLeft();
@ -434,90 +405,89 @@ Coordinates KMZMap::xy2ll(const QPointF &p)
} }
QPointF p2 = p - _bounds.at(idx).xy.topLeft(); QPointF p2 = p - _bounds.at(idx).xy.topLeft();
if (_maps.at(idx).rotation()) { if (_tiles.at(idx).rotation()) {
QTransform matrix; QTransform matrix;
matrix.rotate(_maps.at(idx).rotation()); matrix.rotate(_tiles.at(idx).rotation());
return _maps.at(idx).xy2ll(matrix.map(p2)); return xy2ll(matrix.map(p2), _tiles.at(idx).transform());
} else } else
return _maps.at(idx).xy2ll(p2); return xy2ll(p2, _tiles.at(idx).transform());
} }
void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
{ {
QRectF er = rect.adjusted(-_adjust * _ratio, -_adjust * _ratio, Q_UNUSED(flags);
_adjust * _ratio, _adjust * _ratio);
QRectF er = rect.adjusted(-_adjust * _mapRatio, -_adjust * _mapRatio,
_adjust * _mapRatio, _adjust * _mapRatio);
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) { for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
QRectF ir = er.intersected(_bounds.at(i).xy); QRectF ir = er.intersected(_bounds.at(i).xy);
if (!ir.isNull()) if (!ir.isNull())
draw(painter, ir, i, flags); draw(painter, ir, i);
} }
} }
void KMZMap::load() void KMZMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(out);
_projection = in;
_mapRatio = hidpi ? deviceRatio : 1.0;
for (int i = 0; i < _tiles.size(); i++)
_tiles[i].configure(_projection);
computeBounds();
Q_ASSERT(!_zip); Q_ASSERT(!_zip);
_zip = new QZipReader(path(), QIODevice::ReadOnly); _zip = new QZipReader(path(), QIODevice::ReadOnly);
} }
void KMZMap::unload() void KMZMap::unload()
{ {
for (int i = 0; i < _maps.count(); i++) _bounds.clear();
_maps[i].unload();
delete _zip; delete _zip;
_zip = 0; _zip = 0;
} }
void KMZMap::setInputProjection(const Projection &projection) void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex)
{ {
if (!projection.isValid() || projection == _projection) const Tile &map = _tiles.at(mapIndex);
return;
_projection = projection;
for (int i = 0; i < _maps.size(); i++)
_maps[i].setProjection(&_projection);
_bounds.clear();
computeBounds();
}
void KMZMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
Q_UNUSED(deviceRatio);
if (mapRatio == _ratio)
return;
_ratio = mapRatio;
for (int i = 0; i < _maps.size(); i++)
_maps[i].setDevicePixelRatio(_ratio);
_bounds.clear();
computeBounds();
}
void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex,
Flags flags)
{
Overlay &map = _maps[mapIndex];
const QPointF offset = _bounds.at(mapIndex).xy.topLeft(); const QPointF offset = _bounds.at(mapIndex).xy.topLeft();
QRectF pr = QRectF(rect.topLeft() - offset, rect.size()); QRectF pr = QRectF(rect.topLeft() - offset, rect.size());
QRectF sr(pr.topLeft() * _mapRatio, pr.size() * _mapRatio);
map.load(_zip); QString key(path() + "/" + map.path());
QPixmap pm;
painter->save(); painter->save();
painter->translate(offset); painter->translate(offset);
map.draw(painter, pr, flags); if (map.rotation())
painter->rotate(-map.rotation());
if (QPixmapCache::find(key, &pm)) {
pm.setDevicePixelRatio(_mapRatio);
painter->drawPixmap(pr.topLeft(), pm, sr);
} else {
QByteArray ba(_zip->fileData(map.path()));
QImage img(QImage::fromData(ba));
pm = QPixmap::fromImage(img);
pm.setDevicePixelRatio(_mapRatio);
painter->drawPixmap(pr.topLeft(), pm, sr);
QPixmapCache::insert(key, pm);
}
//painter->setPen(Qt::red);
//painter->drawRect(map.bounds());
painter->restore(); painter->restore();
} }
Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir) Map *KMZMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;
return new KMZMap(path, proj); return new KMZMap(path);
} }

View File

@ -1,6 +1,7 @@
#ifndef KMZMAP_H #ifndef KMZMAP_H
#define KMZMAP_H #define KMZMAP_H
#include <QImage>
#include "projection.h" #include "projection.h"
#include "transform.h" #include "transform.h"
#include "rectd.h" #include "rectd.h"
@ -8,15 +9,16 @@
class QXmlStreamReader; class QXmlStreamReader;
class QZipReader; class QZipReader;
class Image;
class KMZMap : public Map class KMZMap : public Map
{ {
Q_OBJECT Q_OBJECT
public: public:
KMZMap(const QString &fileName, const Projection &proj, QObject *parent = 0); KMZMap(const QString &fileName, QObject *parent = 0);
~KMZMap();
RectC llBounds(const Projection &) {return _llbounds;}
QRectF bounds(); QRectF bounds();
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
@ -30,54 +32,52 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setInputProjection(const Projection &projection);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
class Overlay { class Overlay {
public: public:
Overlay(const QString &path, const QSize &size, const RectC &bbox, Overlay(const QString &path, const RectC &bbox, double rotation)
double rotation, const Projection *proj, qreal ratio); : _path(path), _bbox(bbox), _rotation(rotation) {}
bool operator==(const Overlay &other) const
{return _path == other._path;}
QPointF ll2xy(const Coordinates &c) const
{return QPointF(_transform.proj2img(_proj->ll2xy(c))) / _ratio;}
Coordinates xy2ll(const QPointF &p) const
{return _proj->xy2ll(_transform.img2proj(p * _ratio));}
const QString &path() const {return _path;} const QString &path() const {return _path;}
const RectC &bbox() const {return _bbox;} const RectC &bbox() const {return _bbox;}
const QRectF &bounds() const {return _bounds;}
qreal resolution(const QRectF &rect) const;
qreal rotation() const {return _rotation;} qreal rotation() const {return _rotation;}
void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(QZipReader *zip);
void unload();
void setProjection(const Projection *proj);
void setDevicePixelRatio(qreal ratio);
private: private:
QString _path; QString _path;
QSize _size;
QRectF _bounds;
RectC _bbox; RectC _bbox;
qreal _rotation; qreal _rotation;
Image *_img; };
const Projection *_proj;
class Tile {
public:
Tile(const Overlay &overlay, QZipReader &zip);
bool operator==(const Tile &other) const
{return _overlay.path() == other._overlay.path();}
bool isValid() const {return _size.isValid();}
const QString &path() const {return _overlay.path();}
qreal rotation() const {return _overlay.rotation();}
const RectC &bbox() const {return _overlay.bbox();}
const Transform &transform() const {return _transform;}
QRectF bounds() const;
qreal resolution() const;
void configure(const Projection &proj);
private:
Overlay _overlay;
QSize _size;
Transform _transform; Transform _transform;
qreal _ratio;
}; };
struct Zoom { struct Zoom {
@ -96,23 +96,32 @@ private:
Bounds(const RectC &ll, const QRectF &xy) : ll(ll), xy(xy) {} Bounds(const RectC &ll, const QRectF &xy) : ll(ll), xy(xy) {}
}; };
void kml(QXmlStreamReader &reader, QZipReader &zip); void kml(QXmlStreamReader &reader, QList<Overlay> &overlays);
void document(QXmlStreamReader &reader, QZipReader &zip); void document(QXmlStreamReader &reader, QList<Overlay> &overlays);
void folder(QXmlStreamReader &reader, QZipReader &zip); void folder(QXmlStreamReader &reader, QList<Overlay> &overlays);
void groundOverlay(QXmlStreamReader &reader, QZipReader &zip); void groundOverlay(QXmlStreamReader &reader, QList<Overlay> &overlays);
RectC latLonBox(QXmlStreamReader &reader, double *rotation); RectC latLonBox(QXmlStreamReader &reader, double *rotation);
QString icon(QXmlStreamReader &reader); QString icon(QXmlStreamReader &reader);
double number(QXmlStreamReader &reader); double number(QXmlStreamReader &reader);
void draw(QPainter *painter, const QRectF &rect, int mapIndex, Flags flags); void draw(QPainter *painter, const QRectF &rect, int mapIndex);
bool createTiles(const QList<Overlay> &overlays, QZipReader &zip);
void computeZooms(); void computeZooms();
void computeBounds(); void computeBounds();
void computeLLBounds();
static bool resCmp(const Overlay &m1, const Overlay &m2); QPointF ll2xy(const Coordinates &c, const Transform &transform) const
static bool xCmp(const Overlay &m1, const Overlay &m2); {return QPointF(transform.proj2img(_projection.ll2xy(c))) / _mapRatio;}
static bool yCmp(const Overlay &m1, const Overlay &m2); Coordinates xy2ll(const QPointF &p, const Transform &transform) const
{return _projection.xy2ll(transform.img2proj(p * _mapRatio));}
QList<Overlay> _maps; static bool resCmp(const Tile &m1, const Tile &m2);
static bool xCmp(const Tile &m1, const Tile &m2);
static bool yCmp(const Tile &m1, const Tile &m2);
RectC _llbounds;
QList<Tile> _tiles;
QVector<Zoom> _zooms; QVector<Zoom> _zooms;
QVector<Bounds> _bounds; QVector<Bounds> _bounds;
int _zoom; int _zoom;
@ -120,7 +129,7 @@ private:
QZipReader *_zip; QZipReader *_zip;
qreal _adjust; qreal _adjust;
Projection _projection; Projection _projection;
qreal _ratio; qreal _mapRatio;
bool _valid; bool _valid;
QString _errorString; QString _errorString;

View File

@ -37,8 +37,12 @@ void Map::growBottom(const QPointF &p, RectC &rect)
rect.setBottom(c.lat()); rect.setBottom(c.lat());
} }
RectC Map::llBounds() RectC Map::llBounds(const Projection &proj)
{ {
Q_UNUSED(proj);
/* We use bounds() and xy2ll() here as this fallback implementation is
used ONLY for maps providing those functions since map creation. */
QRectF b(bounds()); QRectF b(bounds());
double dx = b.width() / SAMPLES; double dx = b.width() / SAMPLES;
double dy = b.height() / SAMPLES; double dy = b.height() / SAMPLES;

View File

@ -28,10 +28,19 @@ public:
: QObject(parent), _path(path) {} : QObject(parent), _path(path) {}
virtual ~Map() {} virtual ~Map() {}
/* Functions available since map creation */
const QString &path() const {return _path;} const QString &path() const {return _path;}
virtual QString name() const {return Util::file2name(path());} virtual QString name() const {return Util::file2name(path());}
virtual RectC llBounds(const Projection &proj);
virtual bool isValid() const {return true;}
virtual bool isReady() const {return true;}
virtual QString errorString() const {return QString();}
/* Functions that shall be called after load() */
virtual void load(const Projection &, const Projection &, qreal, bool) {}
virtual void unload() {}
virtual RectC llBounds();
virtual QRectF bounds() = 0; virtual QRectF bounds() = 0;
virtual qreal resolution(const QRectF &rect); virtual qreal resolution(const QRectF &rect);
@ -47,15 +56,6 @@ public:
virtual void draw(QPainter *painter, const QRectF &rect, Flags flags) = 0; virtual void draw(QPainter *painter, const QRectF &rect, Flags flags) = 0;
virtual void clearCache() {} virtual void clearCache() {}
virtual void load() {}
virtual void unload() {}
virtual void setDevicePixelRatio(qreal, qreal) {}
virtual void setOutputProjection(const Projection &) {}
virtual void setInputProjection(const Projection &) {}
virtual bool isValid() const {return true;}
virtual bool isReady() const {return true;}
virtual QString errorString() const {return QString();}
signals: signals:
void tilesLoaded(); void tilesLoaded();

View File

@ -62,7 +62,7 @@ MapList::ParserMap MapList::parsers()
MapList::ParserMap MapList::_parsers = parsers(); MapList::ParserMap MapList::_parsers = parsers();
Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir) Map *MapList::loadFile(const QString &path, bool *isDir)
{ {
ParserMap::iterator it; ParserMap::iterator it;
QFileInfo fi(path); QFileInfo fi(path);
@ -73,7 +73,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
if ((it = _parsers.find(suffix)) != _parsers.end()) { if ((it = _parsers.find(suffix)) != _parsers.end()) {
while (it != _parsers.end() && it.key() == suffix) { while (it != _parsers.end() && it.key() == suffix) {
delete map; delete map;
map = it.value()(path, proj, isDir); map = it.value()(path, isDir);
if (map->isValid()) if (map->isValid())
return map; return map;
else else
@ -82,7 +82,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
} }
} else { } else {
for (it = _parsers.begin(); it != _parsers.end(); it++) { for (it = _parsers.begin(); it != _parsers.end(); it++) {
map = it.value()(path, proj, isDir); map = it.value()(path, isDir);
if (map->isValid()) if (map->isValid())
return map; return map;
else { else {
@ -100,8 +100,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir)
return map ? map : new InvalidMap(path, "Unknown file format"); return map ? map : new InvalidMap(path, "Unknown file format");
} }
TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj, TreeNode<Map*> MapList::loadDir(const QString &path, TreeNode<Map*> *parent)
TreeNode<Map *> *parent)
{ {
QDir md(path); QDir md(path);
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
@ -118,12 +117,12 @@ TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
QString suffix = fi.suffix().toLower(); QString suffix = fi.suffix().toLower();
if (fi.isDir()) { if (fi.isDir()) {
TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), proj, &tree)); TreeNode<Map*> child(loadDir(fi.absoluteFilePath(), &tree));
if (!child.isEmpty()) if (!child.isEmpty())
tree.addChild(child); tree.addChild(child);
} else if (filter().contains("*." + suffix)) { } else if (filter().contains("*." + suffix)) {
bool isDir = false; bool isDir = false;
Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir); Map *map = loadFile(fi.absoluteFilePath(), &isDir);
if (isDir) { if (isDir) {
if (parent) if (parent)
parent->addItem(map); parent->addItem(map);
@ -138,13 +137,13 @@ TreeNode<Map *> MapList::loadDir(const QString &path, const Projection &proj,
return tree; return tree;
} }
TreeNode<Map *> MapList::loadMaps(const QString &path, const Projection &proj) TreeNode<Map *> MapList::loadMaps(const QString &path)
{ {
if (QFileInfo(path).isDir()) if (QFileInfo(path).isDir())
return loadDir(path, proj); return loadDir(path);
else { else {
TreeNode<Map*> tree; TreeNode<Map*> tree;
tree.addItem(loadFile(path, proj)); tree.addItem(loadFile(path));
return tree; return tree;
} }
} }

View File

@ -10,18 +10,16 @@ class Projection;
class MapList class MapList
{ {
public: public:
static TreeNode<Map*> loadMaps(const QString &path, const Projection &proj); static TreeNode<Map*> loadMaps(const QString &path);
static QString formats(); static QString formats();
static QStringList filter(); static QStringList filter();
private: private:
typedef Map*(*ParserCb)(const QString &, const Projection &, bool *isDir); typedef Map*(*ParserCb)(const QString &, bool *isDir);
typedef QMultiMap<QString, ParserCb> ParserMap; typedef QMultiMap<QString, ParserCb> ParserMap;
static Map *loadFile(const QString &path, const Projection &proj, static Map *loadFile(const QString &path, bool *isDir = 0);
bool *isDir = 0); static TreeNode<Map*> loadDir(const QString &path, TreeNode<Map*> *parent = 0);
static TreeNode<Map*> loadDir(const QString &path, const Projection &proj,
TreeNode<Map *> *parent = 0);
static ParserMap parsers(); static ParserMap parsers();
static ParserMap _parsers; static ParserMap _parsers;

View File

@ -15,16 +15,25 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent)
: Map(fileName, parent), _data(fileName), _zoom(0), : Map(fileName, parent), _data(fileName), _zoom(0),
_projection(PCS::pcs(3857)), _tileRatio(1.0) _projection(PCS::pcs(3857)), _tileRatio(1.0)
{ {
if (_data.isValid()) { if (_data.isValid())
_zoom = _data.zooms().min(); _zoom = _data.zooms().min();
updateTransform();
}
} }
void MapsforgeMap::load() void MapsforgeMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(hidpi);
_tileRatio = deviceRatio;
_projection = out;
_data.load(); _data.load();
_style.load(_data, _tileRatio); _style.load(_data, _tileRatio);
updateTransform();
QPixmapCache::clear();
} }
void MapsforgeMap::unload() void MapsforgeMap::unload()
@ -225,24 +234,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Map *MapsforgeMap::create(const QString &path, bool *isMap)
{
Q_UNUSED(mapRatio);
_tileRatio = deviceRatio;
}
void MapsforgeMap::setOutputProjection(const Projection &projection)
{
if (!projection.isValid() || projection == _projection)
return;
_projection = projection;
updateTransform();
QPixmapCache::clear();
}
Map *MapsforgeMap::create(const QString &path, const Projection &, bool *isMap)
{ {
if (isMap) if (isMap)
*isMap = false; *isMap = false;

View File

@ -52,7 +52,7 @@ public:
MapsforgeMap(const QString &fileName, QObject *parent = 0); MapsforgeMap(const QString &fileName, QObject *parent = 0);
QRectF bounds() {return _bounds;} QRectF bounds() {return _bounds;}
RectC llBounds() {return _data.bounds();} RectC llBounds(const Projection &) {return _data.bounds();}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -60,10 +60,9 @@ public:
int zoomIn(); int zoomIn();
int zoomOut(); int zoomOut();
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setOutputProjection(const Projection &projection);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
QPointF ll2xy(const Coordinates &c) QPointF ll2xy(const Coordinates &c)
{return _transform.proj2img(_projection.ll2xy(c));} {return _transform.proj2img(_projection.ll2xy(c));}
@ -75,7 +74,7 @@ public:
bool isValid() const {return _data.isValid();} bool isValid() const {return _data.isValid();}
QString errorString() const {return _data.errorString();} QString errorString() const {return _data.errorString();}
static Map *create(const QString &path, const Projection &, bool *isMap); static Map *create(const QString &path, bool *isMap);
private slots: private slots:
void jobFinished(MapsforgeMapJob *job); void jobFinished(MapsforgeMapJob *job);

View File

@ -206,9 +206,8 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
} }
} }
Map *MapSource::create(const QString &path, const Projection &proj, bool *isDir) Map *MapSource::create(const QString &path, bool *isDir)
{ {
Q_UNUSED(proj);
Config config; Config config;
QFile file(path); QFile file(path);

View File

@ -15,7 +15,7 @@ class Projection;
class MapSource class MapSource
{ {
public: public:
static Map *create(const QString &path, const Projection &proj, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
enum Type { enum Type {

View File

@ -165,8 +165,19 @@ MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void MBTilesMap::load() void MBTilesMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
if (_scalable) {
_scaledSize = _tileSize * deviceRatio;
_tileRatio = deviceRatio;
}
_db.open(); _db.open();
} }
@ -218,16 +229,6 @@ int MBTilesMap::zoomOut()
return _zi; return _zi;
} }
void MBTilesMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
_mapRatio = mapRatio;
if (_scalable) {
_scaledSize = _tileSize * deviceRatio;
_tileRatio = deviceRatio;
}
}
qreal MBTilesMap::coordinatesRatio() const qreal MBTilesMap::coordinatesRatio() const
{ {
return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0; return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0;
@ -337,7 +338,7 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p)
* coordinatesRatio()); * coordinatesRatio());
} }
Map *MBTilesMap::create(const QString &path, const Projection &, bool *isDir) Map *MBTilesMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -13,7 +13,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zi;} int zoom() const {return _zi;}
@ -27,14 +27,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
qreal tileSize() const; qreal tileSize() const;

View File

@ -13,8 +13,8 @@ OnlineMap::OnlineMap(const QString &fileName, const QString &name,
const Authorization &authorization, int tileSize, bool scalable, bool invertY, const Authorization &authorization, int tileSize, bool scalable, bool invertY,
bool quadTiles, QObject *parent) bool quadTiles, QObject *parent)
: Map(fileName, parent), _name(name), _zooms(zooms), _bounds(bounds), : Map(fileName, parent), _name(name), _zooms(zooms), _bounds(bounds),
_zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio), _zoom(_zooms.max()), _tileSize(tileSize), _mapRatio(1.0),
_tileSize(tileSize), _scalable(scalable), _invertY(invertY) _tileRatio(tileRatio), _scalable(scalable), _invertY(invertY)
{ {
_tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name), _tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name),
this); this);
@ -70,9 +70,13 @@ int OnlineMap::zoomOut()
return _zoom; return _zoom;
} }
void OnlineMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void OnlineMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
_mapRatio = mapRatio; Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
if (_scalable) { if (_scalable) {
_tileLoader->setScaledSize(_tileSize * deviceRatio); _tileLoader->setScaledSize(_tileSize * deviceRatio);

View File

@ -19,7 +19,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
@ -33,7 +33,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void clearCache() {_tileLoader->clearCache();} void clearCache() {_tileLoader->clearCache();}
private: private:
@ -47,8 +48,8 @@ private:
Range _zooms; Range _zooms;
RectC _bounds; RectC _bounds;
int _zoom; int _zoom;
qreal _mapRatio, _tileRatio;
int _tileSize; int _tileSize;
qreal _mapRatio, _tileRatio;
bool _scalable; bool _scalable;
bool _invertY; bool _invertY;
}; };

View File

@ -487,8 +487,14 @@ int OruxMap::zoomOut()
return _zoom; return _zoom;
} }
void OruxMap::load() void OruxMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
if (_db.isValid()) if (_db.isValid())
_db.open(); _db.open();
} }
@ -499,12 +505,6 @@ void OruxMap::unload()
_db.close(); _db.close();
} }
void OruxMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
}
QPixmap OruxMap::tile(const Zoom &z, int x, int y) const QPixmap OruxMap::tile(const Zoom &z, int x, int y) const
{ {
if (_db.isValid()) { if (_db.isValid()) {
@ -590,7 +590,7 @@ Coordinates OruxMap::xy2ll(const QPointF &p)
return z.projection.xy2ll(z.transform.img2proj(p * _mapRatio)); return z.projection.xy2ll(z.transform.img2proj(p * _mapRatio));
} }
Map *OruxMap::create(const QString &path, const Projection &, bool *isDir) Map *OruxMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = true; *isDir = true;

View File

@ -33,14 +33,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void load(const Projection &in, const Projection &out, qreal deviceRatio,
void load(); bool hidpi);
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
struct Zoom { struct Zoom {

View File

@ -152,8 +152,13 @@ OsmdroidMap::OsmdroidMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void OsmdroidMap::load() void OsmdroidMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_db.open(); _db.open();
} }
@ -208,12 +213,6 @@ int OsmdroidMap::zoomOut()
return _zoom; return _zoom;
} }
void OsmdroidMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
}
qreal OsmdroidMap::tileSize() const qreal OsmdroidMap::tileSize() const
{ {
return (_tileSize / _mapRatio); return (_tileSize / _mapRatio);
@ -310,7 +309,7 @@ Coordinates OsmdroidMap::xy2ll(const QPointF &p)
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio); return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
} }
Map *OsmdroidMap::create(const QString &path, const Projection &, bool *isDir) Map *OsmdroidMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -11,7 +11,7 @@ public:
OsmdroidMap(const QString &fileName, QObject *parent = 0); OsmdroidMap(const QString &fileName, QObject *parent = 0);
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
@ -25,14 +25,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
int limitZoom(int zoom) const; int limitZoom(int zoom) const;

View File

@ -182,6 +182,9 @@ bool OZF::open()
if (!_file.open(QIODevice::ReadOnly)) if (!_file.open(QIODevice::ReadOnly))
return false; return false;
if (!_zooms.isEmpty())
return true;
if (!readHeaders()) { if (!readHeaders()) {
qWarning("%s: Invalid header", qPrintable(_file.fileName())); qWarning("%s: Invalid header", qPrintable(_file.fileName()));
_file.close(); _file.close();
@ -232,7 +235,6 @@ QPixmap OZF::tile(int zoom, int x, int y)
QSize OZF::size(int zoom) const QSize OZF::size(int zoom) const
{ {
Q_ASSERT(_file.isOpen());
Q_ASSERT(0 <= zoom && zoom < _zooms.count()); Q_ASSERT(0 <= zoom && zoom < _zooms.count());
return _zooms.at(zoom).size; return _zooms.at(zoom).size;

View File

@ -16,6 +16,7 @@ public:
_file(name) {} _file(name) {}
bool open(); bool open();
void close() {_file.close();}
QString fileName() const {return _file.fileName();} QString fileName() const {return _file.fileName();}
bool isOpen() const {return _file.isOpen();} bool isOpen() const {return _file.isOpen();}

View File

@ -50,6 +50,8 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
if (!setTileInfo(_tar->files())) if (!setTileInfo(_tar->files()))
return; return;
_tar->close();
} else { } else {
QFile file(fileName); QFile file(fileName);
MapFile mf(file); MapFile mf(file);
@ -105,6 +107,16 @@ OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
_transform = mf.transform(); _transform = mf.transform();
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar"); _tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
if (!_tar->open()) {
_errorString = _tar->fileName() + ": error reading tar file";
return;
}
if (!setTileInfo(_tar->files())) {
_errorString = _tar->fileName() + ": " + _errorString;
return;
}
_tar->close();
_valid = true; _valid = true;
} }
@ -144,6 +156,7 @@ bool OziMap::setImageInfo(const QString &path)
return false; return false;
} }
_scale = _ozf->scale(_zoom); _scale = _ozf->scale(_zoom);
_ozf->close();
} else { } else {
QImageReader ir(_map.path); QImageReader ir(_map.path);
if (!ir.canRead()) { if (!ir.canRead()) {
@ -192,28 +205,42 @@ bool OziMap::setTileInfo(const QStringList &tiles, const QString &path)
return false; return false;
} }
void OziMap::load() void OziMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
if (_tar && !_tar->isOpen()) { Q_UNUSED(in);
if (!_tar->open()) { Q_UNUSED(out);
qWarning("%s: error loading tar file",
qPrintable(_tar->fileName()));
return;
}
if (!setTileInfo(_tar->files()))
qWarning("%s: %s", qPrintable(_tar->fileName()),
qPrintable(_errorString));
return;
}
if (!_tile.isValid() && !_ozf && !_img) _mapRatio = hidpi ? deviceRatio : 1.0;
if (_tar) {
Q_ASSERT(!_tar->isOpen());
if (!_tar->open())
return;
}
if (_ozf) {
Q_ASSERT(!_ozf->isOpen());
if (!_ozf->open())
return;
}
if (!_tile.isValid() && !_ozf) {
Q_ASSERT(!_img);
_img = new Image(_map.path); _img = new Image(_map.path);
if (_img)
_img->setDevicePixelRatio(_mapRatio);
}
} }
void OziMap::unload() void OziMap::unload()
{ {
delete _img; delete _img;
_img = 0; _img = 0;
if (_tar && _tar->isOpen())
_tar->close();
if (_ozf && _ozf->isOpen())
_ozf->close();
} }
void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const
@ -368,16 +395,7 @@ void OziMap::rescale(int zoom)
_scale = _ozf->scale(zoom); _scale = _ozf->scale(zoom);
} }
void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Map *OziMap::createTAR(const QString &path, bool *isDir)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
if (_img)
_img->setDevicePixelRatio(_mapRatio);
}
Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;
@ -385,7 +403,7 @@ Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir)
return new OziMap(path, true); return new OziMap(path, true);
} }
Map *OziMap::createMAP(const QString &path, const Projection &, bool *isDir) Map *OziMap::createMAP(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -33,8 +33,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void load(const Projection &in, const Projection &out, qreal deviceRatio,
void load(); bool hidpi);
void unload(); void unload();
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
@ -47,8 +47,8 @@ public:
QPointF pp2xy(const PointD &p) const QPointF pp2xy(const PointD &p) const
{return _transform.proj2img(p) / _mapRatio;} {return _transform.proj2img(p) / _mapRatio;}
static Map *createTAR(const QString &path, const Projection &, bool *isDir); static Map *createTAR(const QString &path, bool *isDir);
static Map *createMAP(const QString &path, const Projection &, bool *isDir); static Map *createMAP(const QString &path, bool *isDir);
private: private:
struct ImageInfo { struct ImageInfo {

View File

@ -354,8 +354,13 @@ QCTMap::QCTMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void QCTMap::load() void QCTMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_file.open(QIODevice::ReadOnly); _file.open(QIODevice::ReadOnly);
} }
@ -486,7 +491,7 @@ void QCTMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
Map *QCTMap::create(const QString &path, const Projection &, bool *isDir) Map *QCTMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -21,16 +21,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio)
{_mapRatio = mapRatio;}
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
bool readName(QDataStream &stream); bool readName(QDataStream &stream);

View File

@ -355,8 +355,13 @@ Coordinates RMap::xy2ll(const QPointF &p)
p.y() / scale.y()) * _mapRatio)); p.y() / scale.y()) * _mapRatio));
} }
void RMap::load() void RMap::load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_file.open(QIODevice::ReadOnly); _file.open(QIODevice::ReadOnly);
} }
@ -455,13 +460,7 @@ void RMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
} }
} }
void RMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) Map *RMap::create(const QString &path, bool *isDir)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
}
Map *RMap::create(const QString &path, const Projection &, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -25,8 +25,8 @@ public:
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); void load(const Projection &in, const Projection &out, qreal deviceRatio,
void load(); bool hidpi);
void unload(); void unload();
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
@ -34,7 +34,7 @@ public:
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
struct Header { struct Header {

View File

@ -100,8 +100,13 @@ SqliteMap::SqliteMap(const QString &fileName, QObject *parent)
_valid = true; _valid = true;
} }
void SqliteMap::load() void SqliteMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
_db.open(); _db.open();
} }
@ -156,12 +161,6 @@ int SqliteMap::zoomOut()
return _zoom; return _zoom;
} }
void SqliteMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio)
{
Q_UNUSED(deviceRatio);
_mapRatio = mapRatio;
}
qreal SqliteMap::tileSize() const qreal SqliteMap::tileSize() const
{ {
return (_tileSize / _mapRatio); return (_tileSize / _mapRatio);
@ -257,7 +256,7 @@ Coordinates SqliteMap::xy2ll(const QPointF &p)
return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio); return OSM::m2ll(QPointF(p.x() * scale, -p.y() * scale) * _mapRatio);
} }
Map *SqliteMap::create(const QString &path, const Projection &, bool *isDir) Map *SqliteMap::create(const QString &path, bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;

View File

@ -11,7 +11,7 @@ public:
SqliteMap(const QString &fileName, QObject *parent = 0); SqliteMap(const QString &fileName, QObject *parent = 0);
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _bounds;} RectC llBounds(const Projection &) {return _bounds;}
qreal resolution(const QRectF &rect); qreal resolution(const QRectF &rect);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
@ -25,14 +25,14 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
int limitZoom(int zoom) const; int limitZoom(int zoom) const;

View File

@ -49,6 +49,9 @@ bool Tar::open()
if (!_file.open(QIODevice::ReadOnly)) if (!_file.open(QIODevice::ReadOnly))
return false; return false;
if (!_index.isEmpty())
return true;
QFileInfo fi(_file.fileName()); QFileInfo fi(_file.fileName());
QString tmiPath = fi.path() + "/" + fi.completeBaseName() + ".tmi"; QString tmiPath = fi.path() + "/" + fi.completeBaseName() + ".tmi";

View File

@ -11,6 +11,7 @@ public:
Tar(const QString &name) : _file(name) {} Tar(const QString &name) : _file(name) {}
bool open(); bool open();
void close() {_file.close();}
QStringList files() const {return _index.keys();} QStringList files() const {return _index.keys();}
QByteArray file(const QString &name); QByteArray file(const QString &name);

View File

@ -99,6 +99,15 @@ void WMSMap::wmsReady()
emit mapLoaded(); emit mapLoaded();
} }
void WMSMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
}
void WMSMap::clearCache() void WMSMap::clearCache()
{ {
_tileLoader->clearCache(); _tileLoader->clearCache();

View File

@ -20,7 +20,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds() {return _wms->bbox();} RectC llBounds(const Projection &) {return _wms->bbox();}
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -33,8 +33,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) void load(const Projection &in, const Projection &out, qreal deviceRatio,
{_mapRatio = mapRatio;} bool hidpi);
void clearCache(); void clearCache();
bool isReady() const {return _wms->isReady();} bool isReady() const {return _wms->isReady();}

View File

@ -44,6 +44,15 @@ void WMTSMap::wmtsReady()
emit mapLoaded(); emit mapLoaded();
} }
void WMTSMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{
Q_UNUSED(in);
Q_UNUSED(out);
_mapRatio = hidpi ? deviceRatio : 1.0;
}
void WMTSMap::clearCache() void WMTSMap::clearCache()
{ {
_tileLoader->clearCache(); _tileLoader->clearCache();
@ -97,7 +106,7 @@ QRectF WMTSMap::bounds()
return lb.isValid() ? lb & tb : tb; return lb.isValid() ? lb & tb : tb;
} }
RectC WMTSMap::llBounds() RectC WMTSMap::llBounds(const Projection &)
{ {
if (_wmts->bbox().isValid()) if (_wmts->bbox().isValid())
return _wmts->bbox(); return _wmts->bbox();

View File

@ -20,7 +20,7 @@ public:
QString name() const {return _name;} QString name() const {return _name;}
QRectF bounds(); QRectF bounds();
RectC llBounds(); RectC llBounds(const Projection &);
int zoom() const {return _zoom;} int zoom() const {return _zoom;}
void setZoom(int zoom); void setZoom(int zoom);
@ -33,8 +33,8 @@ public:
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) void load(const Projection &in, const Projection &out, qreal deviceRatio,
{_mapRatio = mapRatio;} bool hidpi);
void clearCache(); void clearCache();
bool isReady() const {return _wmts->isReady();} bool isReady() const {return _wmts->isReady();}

View File

@ -9,9 +9,8 @@
#include "worldfilemap.h" #include "worldfilemap.h"
WorldFileMap::WorldFileMap(const QString &fileName, const Projection &proj, WorldFileMap::WorldFileMap(const QString &fileName, QObject *parent)
QObject *parent) : Map(fileName, parent), _projection(proj), _img(0), : Map(fileName, parent), _img(0), _mapRatio(1.0), _hasPRJ(false), _valid(false)
_ratio(1.0), _hasPRJ(false), _valid(false)
{ {
QFileInfo fi(fileName); QFileInfo fi(fileName);
QDir dir(fi.absoluteDir()); QDir dir(fi.absoluteDir());
@ -74,17 +73,25 @@ WorldFileMap::~WorldFileMap()
QPointF WorldFileMap::ll2xy(const Coordinates &c) QPointF WorldFileMap::ll2xy(const Coordinates &c)
{ {
return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _ratio; return QPointF(_transform.proj2img(_projection.ll2xy(c))) / _mapRatio;
} }
Coordinates WorldFileMap::xy2ll(const QPointF &p) Coordinates WorldFileMap::xy2ll(const QPointF &p)
{ {
return _projection.xy2ll(_transform.img2proj(p * _ratio)); return _projection.xy2ll(_transform.img2proj(p * _mapRatio));
}
RectC WorldFileMap::llBounds(const Projection &proj)
{
if (_projection.isNull())
_projection = proj;
return Map::llBounds(proj);
} }
QRectF WorldFileMap::bounds() QRectF WorldFileMap::bounds()
{ {
return QRectF(QPointF(0, 0), _size / _ratio); return QRectF(QPointF(0, 0), _size / _mapRatio);
} }
void WorldFileMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void WorldFileMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
@ -93,19 +100,20 @@ void WorldFileMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
_img->draw(painter, rect, flags); _img->draw(painter, rect, flags);
} }
void WorldFileMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) void WorldFileMap::load(const Projection &in, const Projection &out,
qreal deviceRatio, bool hidpi)
{ {
Q_UNUSED(deviceRatio); Q_UNUSED(out);
_ratio = mapRatio; if (!_hasPRJ)
_projection = in;
_mapRatio = hidpi ? deviceRatio : 1.0;
Q_ASSERT(!_img);
_img = new Image(_imgFile);
if (_img) if (_img)
_img->setDevicePixelRatio(_ratio); _img->setDevicePixelRatio(_mapRatio);
}
void WorldFileMap::load()
{
if (!_img)
_img = new Image(_imgFile);
} }
void WorldFileMap::unload() void WorldFileMap::unload()
@ -114,19 +122,10 @@ void WorldFileMap::unload()
_img = 0; _img = 0;
} }
void WorldFileMap::setInputProjection(const Projection &projection) Map *WorldFileMap::create(const QString &path, bool *isDir)
{
if (_hasPRJ || !projection.isValid() || projection == _projection)
return;
_projection = projection;
}
Map *WorldFileMap::create(const QString &path, const Projection &proj,
bool *isDir)
{ {
if (isDir) if (isDir)
*isDir = false; *isDir = false;
return new WorldFileMap(path, proj); return new WorldFileMap(path);
} }

View File

@ -12,32 +12,31 @@ class WorldFileMap : public Map
Q_OBJECT Q_OBJECT
public: public:
WorldFileMap(const QString &fileName, const Projection &proj, WorldFileMap(const QString &fileName, QObject *parent = 0);
QObject *parent = 0);
~WorldFileMap(); ~WorldFileMap();
RectC llBounds(const Projection &proj);
QRectF bounds(); QRectF bounds();
QPointF ll2xy(const Coordinates &c); QPointF ll2xy(const Coordinates &c);
Coordinates xy2ll(const QPointF &p); Coordinates xy2ll(const QPointF &p);
void draw(QPainter *painter, const QRectF &rect, Flags flags); void draw(QPainter *painter, const QRectF &rect, Flags flags);
void load(); void load(const Projection &in, const Projection &out, qreal deviceRatio,
bool hidpi);
void unload(); void unload();
void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio);
void setInputProjection(const Projection &projection);
bool isValid() const {return _valid;} bool isValid() const {return _valid;}
QString errorString() const {return _errorString;} QString errorString() const {return _errorString;}
static Map *create(const QString &path, const Projection &proj, bool *isDir); static Map *create(const QString &path, bool *isDir);
private: private:
Projection _projection; Projection _projection;
Transform _transform; Transform _transform;
Image *_img; Image *_img;
QSize _size; QSize _size;
qreal _ratio; qreal _mapRatio;
QString _imgFile; QString _imgFile;
bool _hasPRJ; bool _hasPRJ;