diff --git a/src/GUI/areaitem.cpp b/src/GUI/areaitem.cpp index 2b7183ff..d35763d2 100644 --- a/src/GUI/areaitem.cpp +++ b/src/GUI/areaitem.cpp @@ -25,7 +25,6 @@ ToolTip AreaItem::info() const AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent) : PlaneItem(parent), _area(area) { - _map = map; _digitalZoom = 0; _width = 2; _opacity = 0.5; @@ -35,34 +34,34 @@ AreaItem::AreaItem(const Area &area, Map *map, GraphicsItem *parent) _pen = QPen(strokeColor(), width()); _brush = QBrush(fillColor()); - updatePainterPath(); + updatePainterPath(map); setCursor(Qt::ArrowCursor); setAcceptHoverEvents(true); } -QPainterPath AreaItem::painterPath(const Polygon &polygon) +QPainterPath AreaItem::painterPath(Map *map, const Polygon &polygon) { QPainterPath path; for (int i = 0; i < polygon.size(); i++) { const QVector &subpath = polygon.at(i); - path.moveTo(_map->ll2xy(subpath.first())); + path.moveTo(map->ll2xy(subpath.first())); for (int j = 1; j < subpath.size(); j++) - path.lineTo(_map->ll2xy(subpath.at(j))); + path.lineTo(map->ll2xy(subpath.at(j))); path.closeSubpath(); } return path; } -void AreaItem::updatePainterPath() +void AreaItem::updatePainterPath(Map *map) { _painterPath = QPainterPath(); 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, @@ -85,10 +84,7 @@ void AreaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void AreaItem::setMap(Map *map) { prepareGeometryChange(); - - _map = map; - - updatePainterPath(); + updatePainterPath(map); } const QColor &AreaItem::strokeColor() const diff --git a/src/GUI/areaitem.h b/src/GUI/areaitem.h index d989fb72..9aa5de61 100644 --- a/src/GUI/areaitem.h +++ b/src/GUI/areaitem.h @@ -33,8 +33,8 @@ protected: void hoverLeaveEvent(QGraphicsSceneHoverEvent *event); private: - QPainterPath painterPath(const Polygon &polygon); - void updatePainterPath(); + QPainterPath painterPath(Map *map, const Polygon &polygon); + void updatePainterPath(Map *map); void updateColor(); void updateWidth(); void updatePenStyle(); @@ -45,8 +45,6 @@ private: Area _area; - Map *_map; - qreal _width; QColor _color; qreal _opacity; diff --git a/src/GUI/gui.cpp b/src/GUI/gui.cpp index f8267b6c..3a797d3f 100644 --- a/src/GUI/gui.cpp +++ b/src/GUI/gui.cpp @@ -1721,8 +1721,7 @@ bool GUI::loadMapNode(const TreeNode &node, MapAction *&action, bool GUI::loadMap(const QString &fileName, MapAction *&action, bool silent) { - TreeNode maps(MapList::loadMaps(fileName, - CRS::projection(_options.inputProjection))); + TreeNode maps(MapList::loadMaps(fileName)); QList existingActions(_mapsActionGroup->actions()); return loadMapNode(maps, action, silent, existingActions); @@ -1812,8 +1811,7 @@ void GUI::loadMapDir() return; QFileInfo fi(dir); - TreeNode maps(MapList::loadMaps(dir, - CRS::projection(_options.inputProjection))); + TreeNode maps(MapList::loadMaps(dir)); QList existingActions(_mapsActionGroup->actions()); QList actions; QMenu *menu = new QMenu(maps.name()); @@ -2741,13 +2739,9 @@ void GUI::loadOptions() _mapView->setPOIColor(_options.poiColor); _mapView->setRenderHint(QPainter::Antialiasing, _options.pathAntiAliasing); _mapView->setMarkerColor(_options.sliderColor); - if (_options.useOpenGL) - _mapView->useOpenGL(true); - _mapView->setDevicePixelRatio(devicePixelRatioF(), - _options.hidpiMap ? devicePixelRatioF() : 1.0); - _mapView->setOutputProjection(CRS::projection(4326, - _options.outputProjection)); - _mapView->setInputProjection(CRS::projection(_options.inputProjection)); + _mapView->useOpenGL(_options.useOpenGL); + _mapView->setMapConfig(CRS::projection(_options.inputProjection), + CRS::projection(4326, _options.outputProjection), _options.hidpiMap); _mapView->setTimeZone(_options.timeZone.zone()); _mapView->setPositionSource(_positionSource); @@ -2856,14 +2850,12 @@ void GUI::updateOptions(const Options &options) _positionSource = source; } - if (options.hidpiMap != _options.hidpiMap) - _mapView->setDevicePixelRatio(devicePixelRatioF(), - options.hidpiMap ? devicePixelRatioF() : 1.0); - if (options.outputProjection != _options.outputProjection) - _mapView->setOutputProjection(CRS::projection(4326, - options.outputProjection)); - if (options.inputProjection != _options.inputProjection) - _mapView->setInputProjection(CRS::projection(options.inputProjection)); + if (options.hidpiMap != _options.hidpiMap + || options.outputProjection != _options.outputProjection + || options.inputProjection != _options.inputProjection) + _mapView->setMapConfig(CRS::projection(options.inputProjection), + CRS::projection(4326, options.outputProjection), options.hidpiMap); + if (options.timeZone != _options.timeZone) { _mapView->setTimeZone(options.timeZone.zone()); _dateRange.first = _dateRange.first.toTimeZone(options.timeZone.zone()); @@ -2941,8 +2933,7 @@ void GUI::loadInitialMaps(const QString &selected) if (mapDir.isNull()) return; - TreeNode maps(MapList::loadMaps(mapDir, - CRS::projection(_options.inputProjection))); + TreeNode maps(MapList::loadMaps(mapDir)); createMapNodeMenu(createMapActionsNode(maps), _mapMenu, _mapsEnd); // Select the active map according to the user settings @@ -3044,8 +3035,7 @@ void GUI::show() void GUI::screenChanged(QScreen *screen) { - _mapView->setDevicePixelRatio(devicePixelRatioF(), - _options.hidpiMap ? devicePixelRatioF() : 1.0); + _mapView->setDevicePixelRatio(devicePixelRatioF()); disconnect(SIGNAL(logicalDotsPerInchChanged(qreal)), this, SLOT(logicalDotsPerInchChanged(qreal))); @@ -3057,6 +3047,5 @@ void GUI::logicalDotsPerInchChanged(qreal dpi) { Q_UNUSED(dpi) - _mapView->setDevicePixelRatio(devicePixelRatioF(), - _options.hidpiMap ? devicePixelRatioF() : 1.0); + _mapView->setDevicePixelRatio(devicePixelRatioF()); } diff --git a/src/GUI/mapitem.cpp b/src/GUI/mapitem.cpp index e0005819..af275a19 100644 --- a/src/GUI/mapitem.cpp +++ b/src/GUI/mapitem.cpp @@ -81,19 +81,18 @@ ToolTip MapItem::info() const return tt; } -MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent) - : PlaneItem(parent) +MapItem::MapItem(MapAction *action, Map *map, const Projection &proj, + GraphicsItem *parent) : PlaneItem(parent) { Map *src = action->data().value(); Q_ASSERT(map->isReady()); _name = src->name(); _fileName = src->path(); - _bounds = src->llBounds(); + _bounds = src->llBounds(proj); connect(this, &MapItem::triggered, action, &MapAction::trigger); - _map = map; _digitalZoom = 0; _width = 2; @@ -101,23 +100,23 @@ MapItem::MapItem(MapAction *action, Map *map, GraphicsItem *parent) QBrush brush(Qt::SolidPattern); _pen = QPen(brush, _width); - updatePainterPath(); + updatePainterPath(map); setCursor(Qt::ArrowCursor); setAcceptHoverEvents(true); } -void MapItem::updatePainterPath() +void MapItem::updatePainterPath(Map *map) { _painterPath = QPainterPath(); - QRectF r(bbox(_bounds, _map)); + QRectF r(bbox(_bounds, map)); if (r.left() > r.right()) { 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()), - _bounds.bottomRight()), _map)); + _bounds.bottomRight()), map)); _painterPath.addRect(r1); _painterPath.addRect(r2); @@ -143,10 +142,7 @@ void MapItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, void MapItem::setMap(Map *map) { prepareGeometryChange(); - - _map = map; - - updatePainterPath(); + updatePainterPath(map); } void MapItem::setColor(const QColor &color) diff --git a/src/GUI/mapitem.h b/src/GUI/mapitem.h index 0ae93a45..72f8d63a 100644 --- a/src/GUI/mapitem.h +++ b/src/GUI/mapitem.h @@ -4,13 +4,15 @@ #include "planeitem.h" class MapAction; +class Projection; class MapItem : public QObject, public PlaneItem { Q_OBJECT 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;} QRectF boundingRect() const {return _painterPath.boundingRect();} @@ -37,13 +39,12 @@ protected: void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event); private: - void updatePainterPath(); + void updatePainterPath(Map *map); RectC _bounds; QString _name; QString _fileName; - Map *_map; int _digitalZoom; qreal _width; diff --git a/src/GUI/mapview.cpp b/src/GUI/mapview.cpp index be92a7ce..7b8c4472 100644 --- a/src/GUI/mapview.cpp +++ b/src/GUI/mapview.cpp @@ -60,12 +60,12 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent) _cursorCoordinates->setVisible(false); _scene->addItem(_cursorCoordinates); + _deviceRatio = devicePixelRatioF(); _outputProjection = PCS::pcs(3857); _inputProjection = GCS::gcs(4326); + _hidpi = true; _map = map; - _map->load(); - _map->setOutputProjection(_outputProjection); - _map->setInputProjection(_inputProjection); + _map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi); connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); _poi = poi; @@ -119,8 +119,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent) : QGraphicsView(parent) _showPositionCoordinates = false; _showMotionInfo = false; - _deviceRatio = 1.0; - _mapRatio = 1.0; _opengl = false; _plot = false; _digitalZoom = 0; @@ -247,7 +245,7 @@ void MapView::addWaypoints(const QVector &waypoints) MapItem *MapView::addMap(MapAction *map) { - MapItem *mi = new MapItem(map, _map); + MapItem *mi = new MapItem(map, _map, _inputProjection); mi->setColor(_palette.nextColor()); mi->setWidth(_areaWidth); mi->setPenStyle(_areaStyle); @@ -328,7 +326,7 @@ int MapView::fitMapZoom() const RectC br = _tr | _rr | _wr | _ar; 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 @@ -402,36 +400,18 @@ void MapView::setMap(Map *map) .intersected(_map->bounds())); RectC cr(_map->xy2ll(vr.topLeft()), _map->xy2ll(vr.bottomRight())); - _map->unload(); disconnect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); + _map->unload(); _map = map; - _map->load(); - _map->setOutputProjection(_outputProjection); - _map->setInputProjection(_inputProjection); - _map->setDevicePixelRatio(_deviceRatio, _mapRatio); + _map->load(_inputProjection, _outputProjection, _deviceRatio, _hidpi); connect(_map, &Map::tilesLoaded, this, &MapView::reloadMap); digitalZoom(0); _map->zoomFit(viewport()->rect().size(), cr); - _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); + rescale(); QPointF nc = QRectF(_map->ll2xy(cr.topLeft()), _map->ll2xy(cr.bottomRight())).center(); @@ -702,8 +682,9 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, PlotFlags flags) { QRect orig, adj; - qreal mapRatio, ratio, diff, q, p; + qreal ratio, diff, q, p; QPointF scenePos, scalePos, posPos, motionPos; + bool hidpi = _hidpi && _deviceRatio > 1.0; int zoom; @@ -728,8 +709,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, } // Expand the view if plotting into a bitmap - mapRatio = _mapRatio; - setDevicePixelRatio(_deviceRatio, 1.0); + if (hidpi) + setHidpi(false); if (flags & Expand) { qreal xdiff = (target.width() - adj.width()) / 2.0; @@ -784,7 +765,8 @@ void MapView::plot(QPainter *painter, const QRectF &target, qreal scale, centerOn(scenePos); } - setDevicePixelRatio(_deviceRatio, mapRatio); + if (hidpi) + setHidpi(true); _mapScale->setDigitalZoom(_digitalZoom); _mapScale->setPos(scalePos); @@ -1236,6 +1218,9 @@ bool MapView::gestureEvent(QGestureEvent *event) void MapView::useOpenGL(bool use) { + if (_opengl == use) + return; + _opengl = use; if (use) @@ -1286,60 +1271,21 @@ void MapView::reloadMap() _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) - return; + _inputProjection = in; + _outputProjection = out; + _hidpi = hidpi; - _deviceRatio = deviceRatio; - _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(); + setMap(_map); } -void MapView::setOutputProjection(const Projection &proj) +void MapView::setDevicePixelRatio(qreal ratio) { - _outputProjection = proj; - Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center())); - _map->setOutputProjection(_outputProjection); - rescale(); - centerOn(_map->ll2xy(center)); -} + _deviceRatio = ratio; -void MapView::setInputProjection(const Projection &proj) -{ - _inputProjection = proj; - Coordinates center = _map->xy2ll(mapToScene(viewport()->rect().center())); - _map->setInputProjection(_inputProjection); - rescale(); - centerOn(_map->ll2xy(center)); + setMap(_map); } void MapView::fitContentToSize() @@ -1436,3 +1382,20 @@ void MapView::drawInfoBackground(bool draw) _positionCoordinates->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(); +} diff --git a/src/GUI/mapview.h b/src/GUI/mapview.h index 9765aa08..dc74e95f 100644 --- a/src/GUI/mapview.h +++ b/src/GUI/mapview.h @@ -92,9 +92,8 @@ public: void useAntiAliasing(bool use); void setCoordinatesFormat(CoordinatesFormat format); void setTimeZone(const QTimeZone &zone); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - void setOutputProjection(const Projection &proj); - void setInputProjection(const Projection &proj); + void setMapConfig(const Projection &in, const Projection &out, bool hidpi); + void setDevicePixelRatio(qreal ratio); void clearMapCache(); void fitContentToSize(); @@ -156,6 +155,7 @@ private: bool gestureEvent(QGestureEvent *event); void pinchGesture(QPinchGesture *gesture); void skipColor() {_palette.nextColor();} + void setHidpi(bool hidpi); void mouseMoveEvent(QMouseEvent *event); void mousePressEvent(QMouseEvent *event); @@ -209,7 +209,7 @@ private: QCursor _cursor; qreal _deviceRatio; - qreal _mapRatio; + bool _hidpi; bool _opengl; int _pinchZoom; diff --git a/src/map/aqmmap.cpp b/src/map/aqmmap.cpp index dcd1b5e1..7226cde6 100644 --- a/src/map/aqmmap.cpp +++ b/src/map/aqmmap.cpp @@ -252,8 +252,13 @@ AQMMap::AQMMap(const QString &fileName, QObject *parent) _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); } @@ -305,12 +310,6 @@ int AQMMap::zoomOut() return _zoom; } -void AQMMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - Q_UNUSED(deviceRatio); - _mapRatio = mapRatio; -} - QPointF AQMMap::ll2xy(const Coordinates &c) { const Zoom &z = _zooms.at(_zoom); @@ -406,7 +405,7 @@ void AQMMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp) painter->drawPixmap(tp, pixmap); } -Map *AQMMap::create(const QString &path, const Projection &, bool *isDir) +Map *AQMMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; diff --git a/src/map/aqmmap.h b/src/map/aqmmap.h index 467abfe6..46cb4e43 100644 --- a/src/map/aqmmap.h +++ b/src/map/aqmmap.h @@ -17,7 +17,7 @@ public: QString name() const {return _name;} QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} qreal resolution(const QRectF &rect); int zoom() const {return _zoom;} @@ -26,9 +26,9 @@ public: int zoomIn(); int zoomOut(); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); QPointF ll2xy(const Coordinates &c); Coordinates xy2ll(const QPointF &p); @@ -38,7 +38,7 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: struct File { diff --git a/src/map/atlas.cpp b/src/map/atlas.cpp index 973259ac..e683a77a 100644 --- a/src/map/atlas.cpp +++ b/src/map/atlas.cpp @@ -14,12 +14,7 @@ static bool resCmp(OziMap *m1, OziMap *m2) { - qreal r1, r2; - - r1 = m1->resolution(m1->bounds()); - r2 = m2->resolution(m2->bounds()); - - return r1 > r2; + return m1->resolution(m1->bounds()) > m2->resolution(m2->bounds()); } static bool xCmp(OziMap *m1, OziMap *m2) @@ -38,7 +33,7 @@ void Atlas::computeZooms() _zooms.append(Zoom(0, _maps.count() - 1)); 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()); if (cur < last * ZOOM_THRESHOLD) { _zooms.last().last = i-1; @@ -136,18 +131,17 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent) return; } - computeZooms(); - computeBounds(); - _valid = true; } -void Atlas::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) +RectC Atlas::llBounds(const Projection &proj) { - for (int i = 0; i < _maps.size(); i++) - _maps[i]->setDevicePixelRatio(deviceRatio, mapRatio); + RectC bounds; - computeBounds(); + for (int i = 0; i < _maps.size(); i++) + bounds |= _maps.at(i)->llBounds(proj); + + return 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(); QRectF pr = QRectF(rect.topLeft() - offset, rect.size()); - map->load(); - painter->translate(offset); map->draw(painter, pr, flags); 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() { for (int i = 0; i < _maps.count(); i++) _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) *isDir = true; @@ -298,7 +303,7 @@ Map *Atlas::createTAR(const QString &path, const Projection &, bool *isDir) 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) *isDir = true; diff --git a/src/map/atlas.h b/src/map/atlas.h index b2f3428a..5a2306bc 100644 --- a/src/map/atlas.h +++ b/src/map/atlas.h @@ -3,6 +3,7 @@ #include "map.h" #include "rectd.h" +#include "projection.h" class OziMap; @@ -16,6 +17,7 @@ public: QString name() const {return _name;} QRectF bounds(); + RectC llBounds(const Projection &proj); int zoom() const {return _zoom;} void setZoom(int zoom); @@ -28,14 +30,15 @@ public: 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(); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *createTAR(const QString &path, const Projection &, bool *isDir); - static Map *createTBA(const QString &path, const Projection &, bool *isDir); + static Map *createTAR(const QString &path, bool *isDir); + static Map *createTBA(const QString &path, bool *isDir); private: struct Zoom { diff --git a/src/map/bsbmap.cpp b/src/map/bsbmap.cpp index 57a1340b..f7a4b18e 100644 --- a/src/map/bsbmap.cpp +++ b/src/map/bsbmap.cpp @@ -390,7 +390,7 @@ QImage BSBMap::readImage() } 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); @@ -414,19 +414,19 @@ BSBMap::~BSBMap() 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) { - return _projection.xy2ll(_transform.img2proj(p * _ratio)); + return _projection.xy2ll(_transform.img2proj(p * _mapRatio)); } QRectF BSBMap::bounds() { return _skewSize.isValid() - ? QRectF(QPointF(0, 0), _skewSize / _ratio) - : QRectF(QPointF(0, 0), _size / _ratio); + ? QRectF(QPointF(0, 0), _skewSize / _mapRatio) + : QRectF(QPointF(0, 0), _size / _mapRatio); } 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); } -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; - if (_img) - _img->setDevicePixelRatio(_ratio); -} + _mapRatio = hidpi ? deviceRatio : 1.0; -void BSBMap::load() -{ if (!_img) { if (_skew > 0.0 && _skew < 360.0) { QTransform matrix; @@ -454,6 +451,9 @@ void BSBMap::load() } else _img = new Image(readImage()); } + + if (_img) + _img->setDevicePixelRatio(_mapRatio); } void BSBMap::unload() @@ -462,7 +462,7 @@ void BSBMap::unload() _img = 0; } -Map *BSBMap::create(const QString &path, const Projection &, bool *isMap) +Map *BSBMap::create(const QString &path, bool *isMap) { if (isMap) *isMap = false; diff --git a/src/map/bsbmap.h b/src/map/bsbmap.h index c2c8a640..b2db5afa 100644 --- a/src/map/bsbmap.h +++ b/src/map/bsbmap.h @@ -25,14 +25,14 @@ public: 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isMap); + static Map *create(const QString &path, bool *isMap); private: bool parseBSB(const QByteArray &line); @@ -56,7 +56,7 @@ private: Image *_img; QSize _size; QSize _skewSize; - qreal _ratio; + qreal _mapRatio; qint64 _dataOffset; QVector _palette; diff --git a/src/map/emptymap.h b/src/map/emptymap.h index 1ba2d44f..ecfca06b 100644 --- a/src/map/emptymap.h +++ b/src/map/emptymap.h @@ -14,7 +14,7 @@ public: QString name() const {return QString();} QRectF bounds(); - RectC llBounds() {return OSM::BOUNDS;} + RectC llBounds(const Projection &) {return OSM::BOUNDS;} qreal resolution(const QRectF &rect); int zoom() const {return _zoom;} diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index 00bd805d..bd92e766 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -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(); + QPixmapCache::clear(); } void ENCMap::unload() @@ -218,24 +225,7 @@ void ENCMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } -void ENCMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - 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) +Map *ENCMap::create(const QString &path, bool *isMap) { if (isMap) *isMap = false; diff --git a/src/map/encmap.h b/src/map/encmap.h index ddea3d41..6a469112 100644 --- a/src/map/encmap.h +++ b/src/map/encmap.h @@ -53,7 +53,7 @@ public: QString name() const {return _data.name();} QRectF bounds() {return _bounds;} - RectC llBounds() {return _llBounds;} + RectC llBounds(const Projection &) {return _llBounds;} int zoom() const {return _zoom;} void setZoom(int zoom); @@ -61,10 +61,9 @@ public: int zoomIn(); int zoomOut(); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); - void setOutputProjection(const Projection &projection); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); QPointF ll2xy(const Coordinates &c) {return _transform.proj2img(_projection.ll2xy(c));} @@ -76,7 +75,7 @@ public: bool isValid() const {return _data.isValid();} 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: void jobFinished(ENCMapJob *job); diff --git a/src/map/gemfmap.cpp b/src/map/gemfmap.cpp index 7936c7bd..3af63c8b 100644 --- a/src/map/gemfmap.cpp +++ b/src/map/gemfmap.cpp @@ -182,8 +182,13 @@ Coordinates GEMFMap::xy2ll(const QPointF &p) 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); } @@ -296,7 +301,7 @@ void GEMFMap::drawTile(QPainter *painter, QPixmap &pixmap, QPointF &tp) painter->drawPixmap(tp, pixmap); } -Map *GEMFMap::create(const QString &path, const Projection &, bool *isDir) +Map *GEMFMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; diff --git a/src/map/gemfmap.h b/src/map/gemfmap.h index ca16231a..9b82fe5e 100644 --- a/src/map/gemfmap.h +++ b/src/map/gemfmap.h @@ -14,7 +14,7 @@ public: GEMFMap(const QString &fileName, QObject *parent = 0); QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} int zoom() const {return _zi;} void setZoom(int zoom) {_zi = zoom;} @@ -26,18 +26,16 @@ public: QPointF ll2xy(const Coordinates &c); Coordinates xy2ll(const QPointF &p); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) - {_mapRatio = mapRatio;} - bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: struct Region { diff --git a/src/map/geotiffmap.cpp b/src/map/geotiffmap.cpp index 59e4717f..6d139f0d 100644 --- a/src/map/geotiffmap.cpp +++ b/src/map/geotiffmap.cpp @@ -54,28 +54,26 @@ void GeoTIFFMap::draw(QPainter *painter, const QRectF &rect, Flags 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) _img->setDevicePixelRatio(_ratio); } -void GeoTIFFMap::load() -{ - if (!_img) - _img = new Image(path()); -} - void GeoTIFFMap::unload() { delete _img; _img = 0; } -Map *GeoTIFFMap::create(const QString &path, const Projection &, bool *isDir) +Map *GeoTIFFMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; diff --git a/src/map/geotiffmap.h b/src/map/geotiffmap.h index 44cef4e6..1bf0f33f 100644 --- a/src/map/geotiffmap.h +++ b/src/map/geotiffmap.h @@ -21,14 +21,15 @@ public: 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: Projection _projection; diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index 9733b3cf..28c18105 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -18,6 +18,21 @@ using namespace IMG; #define TILE_SIZE 384 #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 overlays(const QString &fileName) { QList list; @@ -56,17 +71,27 @@ IMGMap::IMGMap(const QString &fileName, bool GMAP, QObject *parent) return; } - _dataBounds = _data.first()->bounds() & OSM::BOUNDS; _zoom = _data.first()->zooms().min(); - updateTransform(); _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++) _data.at(i)->load(); + + updateTransform(); + + QPixmapCache::clear(); } void IMGMap::unload() @@ -261,37 +286,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } -void IMGMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - 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) +Map* IMGMap::createIMG(const QString &path, bool *isDir) { if (isDir) *isDir = false; @@ -299,7 +294,7 @@ Map* IMGMap::createIMG(const QString &path, const Projection &, bool *isDir) 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) *isDir = true; diff --git a/src/map/imgmap.h b/src/map/imgmap.h index e0357ac4..0a699669 100644 --- a/src/map/imgmap.h +++ b/src/map/imgmap.h @@ -55,7 +55,7 @@ public: QString name() const {return _data.first()->name();} QRectF bounds() {return _bounds;} - RectC llBounds() {return _dataBounds;} + RectC llBounds(const Projection &) {return _data.first()->bounds();} int zoom() const {return _zoom;} void setZoom(int zoom); @@ -70,17 +70,15 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setOutputProjection(const Projection &projection); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - - void load(); + void load(const Projection &in, const Projection &out, qreal devicelRatio, + bool hidpi); void unload(); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map* createIMG(const QString &path, const Projection &, bool *isDir); - static Map* createGMAP(const QString &path, const Projection &, bool *isDir); + static Map* createIMG(const QString &path, bool *isDir); + static Map* createGMAP(const QString &path, bool *isDir); private slots: void jobFinished(IMGMapJob *job); diff --git a/src/map/jnxmap.cpp b/src/map/jnxmap.cpp index de598f01..95f706c1 100644 --- a/src/map/jnxmap.cpp +++ b/src/map/jnxmap.cpp @@ -11,22 +11,6 @@ #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 bool JNXMap::readValue(T &val) { T data; @@ -53,7 +37,7 @@ bool JNXMap::readString(QByteArray& ba) } } -bool JNXMap::readTiles() +bool JNXMap::readHeader() { qint32 lat1, lon2, lat2, lon1; quint32 version, dummy, levels; @@ -88,16 +72,22 @@ bool JNXMap::readTiles() } _zooms.reserve(lh.size()); - for (int i = 0; i < lh.count(); i++) { - _zooms.append(new Zoom()); - Zoom *z = _zooms.last(); - const Level &l = lh.at(i); + for (int i = 0; i < lh.count(); i++) + _zooms.append(new Zoom(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; - z->tiles = QVector(l.count); - for (quint32 j = 0; j < l.count; j++) { + z->tiles = QVector(z->level.count); + for (quint32 j = 0; j < z->level.count; j++) { Tile &tile = z->tiles[j]; if (!(readValue(tile.top) && readValue(tile.right) @@ -134,16 +124,25 @@ bool JNXMap::readTiles() return true; } -JNXMap::JNXMap(const QString &fileName, const Projection &proj, QObject *parent) - : Map(fileName, parent), _file(fileName), _zoom(0), _projection(proj), - _mapRatio(1.0), _valid(false) +void JNXMap::clearTiles() +{ + 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)) { - _errorString = fileName + ": " + _file.errorString(); + _errorString = _file.errorString(); return; } - if (!readTiles()) { + if (!readHeader()) { _errorString = "JNX file format error"; return; } @@ -158,14 +157,22 @@ JNXMap::~JNXMap() 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() { _file.close(); + clearTiles(); } 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); } -void JNXMap::setInputProjection(const Projection &projection) -{ - 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) +Map *JNXMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; - return new JNXMap(path, proj); + return new JNXMap(path); } diff --git a/src/map/jnxmap.h b/src/map/jnxmap.h index 947c2584..46e20171 100644 --- a/src/map/jnxmap.h +++ b/src/map/jnxmap.h @@ -15,11 +15,11 @@ public: Q_OBJECT public: - JNXMap(const QString &fileName, const Projection &proj, QObject *parent = 0); + JNXMap(const QString &fileName, QObject *parent = 0); ~JNXMap(); QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} int zoom() const {return _zoom;} void setZoom(int zoom) {_zoom = zoom;} @@ -30,19 +30,16 @@ public: QPointF ll2xy(const Coordinates &c); Coordinates xy2ll(const QPointF &p); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); 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;} 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: struct Tile { @@ -54,15 +51,37 @@ private: QPointF pos; }; + struct Level { + quint32 count; + quint32 offset; + quint32 scale; + }; + struct Zoom { + Zoom() {} + Zoom(const Level &level) : level(level) {} + + Level level; Transform transform; QVector tiles; RTree tree; }; + struct Ctx { + QPainter *painter; + QFile *file; + qreal ratio; + + Ctx(QPainter *painter, QFile *file, qreal ratio) + : painter(painter), file(file), ratio(ratio) {} + }; + + template bool readValue(T &val); bool readString(QByteArray &ba); + bool readHeader(); bool readTiles(); + void clearTiles(); static bool cb(Tile *tile, void *context); static QPixmap pixmap(const Tile *tile, QFile *file); diff --git a/src/map/kmzmap.cpp b/src/map/kmzmap.cpp index e5d2455e..e4e91378 100644 --- a/src/map/kmzmap.cpp +++ b/src/map/kmzmap.cpp @@ -13,14 +13,12 @@ #include #include -#include -#include #include +#include #include +#include #include -#include"common/util.h" -#include "pcs.h" -#include "image.h" +#include "common/util.h" #include "kmzmap.h" @@ -29,162 +27,140 @@ #define TL(m) ((m).bbox().topLeft()) #define BR(m) ((m).bbox().bottomRight()) - -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) +bool KMZMap::resCmp(const Tile &m1, const Tile &m2) { - 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); + return m1.resolution() > m2.resolution(); } -qreal KMZMap::Overlay::resolution(const QRectF &rect) const -{ - 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) +bool KMZMap::xCmp(const Tile &m1, const Tile &m2) { 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(); } + +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 &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() { - std::sort(_maps.begin(), _maps.end(), resCmp); + std::sort(_tiles.begin(), _tiles.end(), resCmp); - _zooms.append(Zoom(0, _maps.count() - 1)); - for (int i = 1; i < _maps.count(); i++) { - qreal last = _maps.at(i-1).resolution(_maps.at(i).bounds()); - qreal cur = _maps.at(i).resolution(_maps.at(i).bounds()); + _zooms.append(Zoom(0, _tiles.count() - 1)); + for (int i = 1; i < _tiles.count(); i++) { + qreal last = _tiles.at(i-1).resolution(); + qreal cur = _tiles.at(i).resolution(); if (cur < last * ZOOM_THRESHOLD) { _zooms.last().last = i-1; - _zooms.append(Zoom(i, _maps.count() - 1)); + _zooms.append(Zoom(i, _tiles.count() - 1)); } } } void KMZMap::computeBounds() { - QVector offsets(_maps.count()); + QVector offsets(_tiles.count()); for (int z = 0; z < _zooms.count(); z++) { - QList m; + QList m; 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); - 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++) { - qreal w = m.first().ll2xy(TL(m.at(i))).x(); - offsets[_maps.indexOf(m.at(i))].setX(w + m.at(i).bounds().left()); + qreal w = ll2xy(TL(m.at(i)), m.first().transform()).x(); + offsets[_tiles.indexOf(m.at(i))].setX(w + m.at(i).bounds().left()); } 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++) { - qreal h = m.first().ll2xy(TL(m.at(i))).y(); - offsets[_maps.indexOf(m.at(i))].setY(h + m.at(i).bounds().top()); + qreal h = ll2xy(TL(m.at(i)), m.first().transform()).y(); + offsets[_tiles.indexOf(m.at(i))].setY(h + m.at(i).bounds().top()); } } _adjust = 0; - _bounds = QVector(_maps.count()); - for (int i = 0; i < _maps.count(); i++) { - QRectF xy(offsets.at(i), _maps.at(i).bounds().size()); - _bounds[i] = Bounds(_maps.at(i).bbox(), xy); - _adjust = qMin(qMin(_maps.at(i).bounds().left(), - _maps.at(i).bounds().top()), _adjust); + _bounds = QVector(_tiles.count()); + for (int i = 0; i < _tiles.count(); i++) { + QRectF xy(offsets.at(i), _tiles.at(i).bounds().size()); + _bounds[i] = Bounds(_tiles.at(i).bbox(), xy); + _adjust = qMin(qMin(_tiles.at(i).bounds().left(), + _tiles.at(i).bounds().top()), _adjust); } _adjust = -_adjust; } @@ -236,7 +212,7 @@ RectC KMZMap::latLonBox(QXmlStreamReader &reader, double *rotation) return RectC(Coordinates(left, top), Coordinates(right, bottom)); } -void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip) +void KMZMap::groundOverlay(QXmlStreamReader &reader, QList &overlays) { QString image; RectC rect; @@ -251,93 +227,87 @@ void KMZMap::groundOverlay(QXmlStreamReader &reader, QZipReader &zip) reader.skipCurrentElement(); } - if (rect.isValid()) { - QByteArray ba(zip.fileData(image)); - QBuffer img(&ba); - 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 + if (rect.isValid()) + overlays.append(Overlay(image, rect, rotation)); + else reader.raiseError("Invalid LatLonBox"); } -void KMZMap::document(QXmlStreamReader &reader, QZipReader &zip) +void KMZMap::document(QXmlStreamReader &reader, QList &overlays) { while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("Document")) - document(reader, zip); + document(reader, overlays); else if (reader.name() == QLatin1String("GroundOverlay")) - groundOverlay(reader, zip); + groundOverlay(reader, overlays); else if (reader.name() == QLatin1String("Folder")) - folder(reader, zip); + folder(reader, overlays); else reader.skipCurrentElement(); } } -void KMZMap::folder(QXmlStreamReader &reader, QZipReader &zip) +void KMZMap::folder(QXmlStreamReader &reader, QList &overlays) { while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("GroundOverlay")) - groundOverlay(reader, zip); + groundOverlay(reader, overlays); else if (reader.name() == QLatin1String("Folder")) - folder(reader, zip); + folder(reader, overlays); else reader.skipCurrentElement(); } } -void KMZMap::kml(QXmlStreamReader &reader, QZipReader &zip) +void KMZMap::kml(QXmlStreamReader &reader, QList &overlays) { while (reader.readNextStartElement()) { if (reader.name() == QLatin1String("Document")) - document(reader, zip); + document(reader, overlays); else if (reader.name() == QLatin1String("GroundOverlay")) - groundOverlay(reader, zip); + groundOverlay(reader, overlays); else if (reader.name() == QLatin1String("Folder")) - folder(reader, zip); + folder(reader, overlays); else reader.skipCurrentElement(); } } -KMZMap::KMZMap(const QString &fileName, const Projection &proj, QObject *parent) - : Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _projection(proj), - _ratio(1.0), _valid(false) +KMZMap::KMZMap(const QString &fileName, QObject *parent) + : Map(fileName, parent), _zoom(0), _mapIndex(-1), _zip(0), _mapRatio(1.0), + _valid(false) { QZipReader zip(fileName, QIODevice::ReadOnly); QByteArray xml(zip.fileData("doc.kml")); QXmlStreamReader reader(xml); + QList overlays; if (reader.readNextStartElement()) { if (reader.name() == QLatin1String("kml")) - kml(reader, zip); + kml(reader, overlays); else reader.raiseError("Not a KMZ file"); } - if (reader.error()) { _errorString = "doc.kml:" + QString::number(reader.lineNumber()) + ": " + reader.errorString(); return; } - if (_maps.isEmpty()) { - _errorString = "No usable GroundOverlay found"; - return; - } + if (!createTiles(overlays, zip)) + return; + computeLLBounds(); computeZooms(); - computeBounds(); _valid = true; } +KMZMap::~KMZMap() +{ + delete _zip; +} + QRectF KMZMap::bounds() { QRectF rect; @@ -364,8 +334,9 @@ int KMZMap::zoomFit(const QSize &size, const RectC &br) if (!_bounds.at(i).ll.contains(br.center())) continue; - QRect sbr = QRectF(_maps.at(i).ll2xy(br.topLeft()), - _maps.at(i).ll2xy(br.bottomRight())).toRect().normalized(); + QRect sbr = QRectF(ll2xy(br.topLeft(), _tiles.at(i).transform()), + ll2xy(br.bottomRight(), _tiles.at(i).transform())) + .toRect().normalized(); if (sbr.size().width() > size.width() || sbr.size().height() > size.height()) @@ -413,10 +384,10 @@ QPointF KMZMap::ll2xy(const Coordinates &c) } } - QPointF p = _maps.at(_mapIndex).ll2xy(c); - if (_maps.at(_mapIndex).rotation()) { + QPointF p = ll2xy(c, _tiles.at(_mapIndex).transform()); + if (_tiles.at(_mapIndex).rotation()) { QTransform matrix; - matrix.rotate(-_maps.at(_mapIndex).rotation()); + matrix.rotate(-_tiles.at(_mapIndex).rotation()); return matrix.map(p) + _bounds.at(_mapIndex).xy.topLeft(); } else return p + _bounds.at(_mapIndex).xy.topLeft(); @@ -434,90 +405,90 @@ Coordinates KMZMap::xy2ll(const QPointF &p) } QPointF p2 = p - _bounds.at(idx).xy.topLeft(); - if (_maps.at(idx).rotation()) { + if (_tiles.at(idx).rotation()) { QTransform matrix; - matrix.rotate(_maps.at(idx).rotation()); - return _maps.at(idx).xy2ll(matrix.map(p2)); + matrix.rotate(_tiles.at(idx).rotation()); + return xy2ll(matrix.map(p2), _tiles.at(idx).transform()); } else - return _maps.at(idx).xy2ll(p2); + return xy2ll(p2, _tiles.at(idx).transform()); } void KMZMap::draw(QPainter *painter, const QRectF &rect, Flags flags) { - QRectF er = rect.adjusted(-_adjust * _ratio, -_adjust * _ratio, - _adjust * _ratio, _adjust * _ratio); + Q_UNUSED(flags); + + 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++) { QRectF ir = er.intersected(_bounds.at(i).xy); 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); _zip = new QZipReader(path(), QIODevice::ReadOnly); } void KMZMap::unload() { - for (int i = 0; i < _maps.count(); i++) - _maps[i].unload(); + _bounds.clear(); delete _zip; _zip = 0; } -void KMZMap::setInputProjection(const Projection &projection) +void KMZMap::draw(QPainter *painter, const QRectF &rect, int mapIndex) { - if (!projection.isValid() || projection == _projection) - 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 Tile &map = _tiles.at(mapIndex); const QPointF offset = _bounds.at(mapIndex).xy.topLeft(); QRectF pr = QRectF(rect.topLeft() - offset, rect.size()); - - map.load(_zip); + QRectF sr(pr.topLeft() * _mapRatio, pr.size() * _mapRatio); + QString key(path() + "/" + map.path()); + QPixmap pm; painter->save(); 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); + qDebug() << key; + } + + //painter->setPen(Qt::red); + //painter->drawRect(map.bounds()); + painter->restore(); } -Map *KMZMap::create(const QString &path, const Projection &proj, bool *isDir) +Map *KMZMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; - return new KMZMap(path, proj); + return new KMZMap(path); } diff --git a/src/map/kmzmap.h b/src/map/kmzmap.h index 155c6b40..c6d76473 100644 --- a/src/map/kmzmap.h +++ b/src/map/kmzmap.h @@ -1,6 +1,7 @@ #ifndef KMZMAP_H #define KMZMAP_H +#include #include "projection.h" #include "transform.h" #include "rectd.h" @@ -8,15 +9,16 @@ class QXmlStreamReader; class QZipReader; -class Image; class KMZMap : public Map { Q_OBJECT 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(); int zoom() const {return _zoom;} @@ -30,54 +32,52 @@ public: 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 setInputProjection(const Projection &projection); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - bool isValid() const {return _valid;} 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: class Overlay { public: - Overlay(const QString &path, const QSize &size, const RectC &bbox, - double rotation, const Projection *proj, qreal ratio); - 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));} + Overlay(const QString &path, const RectC &bbox, double rotation) + : _path(path), _bbox(bbox), _rotation(rotation) {} const QString &path() const {return _path;} const RectC &bbox() const {return _bbox;} - const QRectF &bounds() const {return _bounds;} - qreal resolution(const QRectF &rect) const; 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: QString _path; - QSize _size; - QRectF _bounds; RectC _bbox; 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; - qreal _ratio; }; struct Zoom { @@ -96,23 +96,32 @@ private: Bounds(const RectC &ll, const QRectF &xy) : ll(ll), xy(xy) {} }; - void kml(QXmlStreamReader &reader, QZipReader &zip); - void document(QXmlStreamReader &reader, QZipReader &zip); - void folder(QXmlStreamReader &reader, QZipReader &zip); - void groundOverlay(QXmlStreamReader &reader, QZipReader &zip); + void kml(QXmlStreamReader &reader, QList &overlays); + void document(QXmlStreamReader &reader, QList &overlays); + void folder(QXmlStreamReader &reader, QList &overlays); + void groundOverlay(QXmlStreamReader &reader, QList &overlays); RectC latLonBox(QXmlStreamReader &reader, double *rotation); QString icon(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 &overlays, QZipReader &zip); void computeZooms(); void computeBounds(); + void computeLLBounds(); - static bool resCmp(const Overlay &m1, const Overlay &m2); - static bool xCmp(const Overlay &m1, const Overlay &m2); - static bool yCmp(const Overlay &m1, const Overlay &m2); + QPointF ll2xy(const Coordinates &c, const Transform &transform) const + {return QPointF(transform.proj2img(_projection.ll2xy(c))) / _mapRatio;} + Coordinates xy2ll(const QPointF &p, const Transform &transform) const + {return _projection.xy2ll(transform.img2proj(p * _mapRatio));} - QList _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 _tiles; QVector _zooms; QVector _bounds; int _zoom; @@ -120,7 +129,7 @@ private: QZipReader *_zip; qreal _adjust; Projection _projection; - qreal _ratio; + qreal _mapRatio; bool _valid; QString _errorString; diff --git a/src/map/map.cpp b/src/map/map.cpp index 841f78b5..405bed7d 100644 --- a/src/map/map.cpp +++ b/src/map/map.cpp @@ -37,8 +37,12 @@ void Map::growBottom(const QPointF &p, RectC &rect) 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()); double dx = b.width() / SAMPLES; double dy = b.height() / SAMPLES; diff --git a/src/map/map.h b/src/map/map.h index 5281808f..1d1d7067 100644 --- a/src/map/map.h +++ b/src/map/map.h @@ -28,10 +28,19 @@ public: : QObject(parent), _path(path) {} virtual ~Map() {} + /* Functions available since map creation */ const QString &path() const {return _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 qreal resolution(const QRectF &rect); @@ -47,15 +56,6 @@ public: virtual void draw(QPainter *painter, const QRectF &rect, Flags flags) = 0; 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: void tilesLoaded(); diff --git a/src/map/maplist.cpp b/src/map/maplist.cpp index bf759d7c..fd684937 100644 --- a/src/map/maplist.cpp +++ b/src/map/maplist.cpp @@ -62,7 +62,7 @@ MapList::ParserMap MapList::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; 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()) { while (it != _parsers.end() && it.key() == suffix) { delete map; - map = it.value()(path, proj, isDir); + map = it.value()(path, isDir); if (map->isValid()) return map; else @@ -82,7 +82,7 @@ Map *MapList::loadFile(const QString &path, const Projection &proj, bool *isDir) } } else { for (it = _parsers.begin(); it != _parsers.end(); it++) { - map = it.value()(path, proj, isDir); + map = it.value()(path, isDir); if (map->isValid()) return map; 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"); } -TreeNode MapList::loadDir(const QString &path, const Projection &proj, - TreeNode *parent) +TreeNode MapList::loadDir(const QString &path, TreeNode *parent) { QDir md(path); md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot); @@ -118,12 +117,12 @@ TreeNode MapList::loadDir(const QString &path, const Projection &proj, QString suffix = fi.suffix().toLower(); if (fi.isDir()) { - TreeNode child(loadDir(fi.absoluteFilePath(), proj, &tree)); + TreeNode child(loadDir(fi.absoluteFilePath(), &tree)); if (!child.isEmpty()) tree.addChild(child); } else if (filter().contains("*." + suffix)) { bool isDir = false; - Map *map = loadFile(fi.absoluteFilePath(), proj, &isDir); + Map *map = loadFile(fi.absoluteFilePath(), &isDir); if (isDir) { if (parent) parent->addItem(map); @@ -138,13 +137,13 @@ TreeNode MapList::loadDir(const QString &path, const Projection &proj, return tree; } -TreeNode MapList::loadMaps(const QString &path, const Projection &proj) +TreeNode MapList::loadMaps(const QString &path) { if (QFileInfo(path).isDir()) - return loadDir(path, proj); + return loadDir(path); else { TreeNode tree; - tree.addItem(loadFile(path, proj)); + tree.addItem(loadFile(path)); return tree; } } diff --git a/src/map/maplist.h b/src/map/maplist.h index 3bf8153c..8129b16a 100644 --- a/src/map/maplist.h +++ b/src/map/maplist.h @@ -10,18 +10,16 @@ class Projection; class MapList { public: - static TreeNode loadMaps(const QString &path, const Projection &proj); + static TreeNode loadMaps(const QString &path); static QString formats(); static QStringList filter(); private: - typedef Map*(*ParserCb)(const QString &, const Projection &, bool *isDir); + typedef Map*(*ParserCb)(const QString &, bool *isDir); typedef QMultiMap ParserMap; - static Map *loadFile(const QString &path, const Projection &proj, - bool *isDir = 0); - static TreeNode loadDir(const QString &path, const Projection &proj, - TreeNode *parent = 0); + static Map *loadFile(const QString &path, bool *isDir = 0); + static TreeNode loadDir(const QString &path, TreeNode *parent = 0); static ParserMap parsers(); static ParserMap _parsers; diff --git a/src/map/mapsforgemap.cpp b/src/map/mapsforgemap.cpp index a517184e..5849022a 100644 --- a/src/map/mapsforgemap.cpp +++ b/src/map/mapsforgemap.cpp @@ -15,16 +15,25 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent) : Map(fileName, parent), _data(fileName), _zoom(0), _projection(PCS::pcs(3857)), _tileRatio(1.0) { - if (_data.isValid()) { + if (_data.isValid()) _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(); _style.load(_data, _tileRatio); + + updateTransform(); + + QPixmapCache::clear(); } void MapsforgeMap::unload() @@ -225,24 +234,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } -void MapsforgeMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - 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) +Map *MapsforgeMap::create(const QString &path, bool *isMap) { if (isMap) *isMap = false; diff --git a/src/map/mapsforgemap.h b/src/map/mapsforgemap.h index ba29f6f7..72169aa0 100644 --- a/src/map/mapsforgemap.h +++ b/src/map/mapsforgemap.h @@ -52,7 +52,7 @@ public: MapsforgeMap(const QString &fileName, QObject *parent = 0); QRectF bounds() {return _bounds;} - RectC llBounds() {return _data.bounds();} + RectC llBounds(const Projection &) {return _data.bounds();} int zoom() const {return _zoom;} void setZoom(int zoom); @@ -60,10 +60,9 @@ public: int zoomIn(); int zoomOut(); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); - void setOutputProjection(const Projection &projection); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); QPointF ll2xy(const Coordinates &c) {return _transform.proj2img(_projection.ll2xy(c));} @@ -75,7 +74,7 @@ public: bool isValid() const {return _data.isValid();} 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: void jobFinished(MapsforgeMapJob *job); diff --git a/src/map/mapsource.cpp b/src/map/mapsource.cpp index dbf08db6..d5dd8dba 100644 --- a/src/map/mapsource.cpp +++ b/src/map/mapsource.cpp @@ -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; QFile file(path); diff --git a/src/map/mapsource.h b/src/map/mapsource.h index 7c9d045e..1be457ee 100644 --- a/src/map/mapsource.h +++ b/src/map/mapsource.h @@ -15,7 +15,7 @@ class Projection; class MapSource { public: - static Map *create(const QString &path, const Projection &proj, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: enum Type { diff --git a/src/map/mbtilesmap.cpp b/src/map/mbtilesmap.cpp index a9cee8e4..9b5224c5 100644 --- a/src/map/mbtilesmap.cpp +++ b/src/map/mbtilesmap.cpp @@ -165,8 +165,19 @@ MBTilesMap::MBTilesMap(const QString &fileName, QObject *parent) _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(); } @@ -218,16 +229,6 @@ int MBTilesMap::zoomOut() return _zi; } -void MBTilesMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - _mapRatio = mapRatio; - - if (_scalable) { - _scaledSize = _tileSize * deviceRatio; - _tileRatio = deviceRatio; - } -} - qreal MBTilesMap::coordinatesRatio() const { return _mapRatio > 1.0 ? _mapRatio / _tileRatio : 1.0; @@ -337,7 +338,7 @@ Coordinates MBTilesMap::xy2ll(const QPointF &p) * coordinatesRatio()); } -Map *MBTilesMap::create(const QString &path, const Projection &, bool *isDir) +Map *MBTilesMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; diff --git a/src/map/mbtilesmap.h b/src/map/mbtilesmap.h index d7cf56ff..0b3a8b41 100644 --- a/src/map/mbtilesmap.h +++ b/src/map/mbtilesmap.h @@ -13,7 +13,7 @@ public: QString name() const {return _name;} QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} qreal resolution(const QRectF &rect); int zoom() const {return _zi;} @@ -27,14 +27,14 @@ public: 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: qreal tileSize() const; diff --git a/src/map/onlinemap.cpp b/src/map/onlinemap.cpp index 0d0e96cd..2746a414 100644 --- a/src/map/onlinemap.cpp +++ b/src/map/onlinemap.cpp @@ -13,8 +13,8 @@ OnlineMap::OnlineMap(const QString &fileName, const QString &name, const Authorization &authorization, int tileSize, bool scalable, bool invertY, bool quadTiles, QObject *parent) : Map(fileName, parent), _name(name), _zooms(zooms), _bounds(bounds), - _zoom(_zooms.max()), _mapRatio(1.0), _tileRatio(tileRatio), - _tileSize(tileSize), _scalable(scalable), _invertY(invertY) + _zoom(_zooms.max()), _tileSize(tileSize), _mapRatio(1.0), + _tileRatio(tileRatio), _scalable(scalable), _invertY(invertY) { _tileLoader = new TileLoader(QDir(ProgramPaths::tilesDir()).filePath(_name), this); @@ -70,9 +70,13 @@ int OnlineMap::zoomOut() 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) { _tileLoader->setScaledSize(_tileSize * deviceRatio); diff --git a/src/map/onlinemap.h b/src/map/onlinemap.h index 83cd1b45..6ac36fd0 100644 --- a/src/map/onlinemap.h +++ b/src/map/onlinemap.h @@ -19,7 +19,7 @@ public: QString name() const {return _name;} QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} qreal resolution(const QRectF &rect); int zoom() const {return _zoom;} @@ -33,7 +33,8 @@ public: 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();} private: @@ -47,8 +48,8 @@ private: Range _zooms; RectC _bounds; int _zoom; - qreal _mapRatio, _tileRatio; int _tileSize; + qreal _mapRatio, _tileRatio; bool _scalable; bool _invertY; }; diff --git a/src/map/oruxmap.cpp b/src/map/oruxmap.cpp index 1ecd2071..03653dea 100644 --- a/src/map/oruxmap.cpp +++ b/src/map/oruxmap.cpp @@ -487,8 +487,14 @@ int OruxMap::zoomOut() 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()) _db.open(); } @@ -499,12 +505,6 @@ void OruxMap::unload() _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 { if (_db.isValid()) { @@ -590,7 +590,7 @@ Coordinates OruxMap::xy2ll(const QPointF &p) 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) *isDir = true; diff --git a/src/map/oruxmap.h b/src/map/oruxmap.h index 71589345..fc3f36f7 100644 --- a/src/map/oruxmap.h +++ b/src/map/oruxmap.h @@ -33,14 +33,14 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: struct Zoom { diff --git a/src/map/osmdroidmap.cpp b/src/map/osmdroidmap.cpp index 67e7df7e..47fb0559 100644 --- a/src/map/osmdroidmap.cpp +++ b/src/map/osmdroidmap.cpp @@ -152,8 +152,13 @@ OsmdroidMap::OsmdroidMap(const QString &fileName, QObject *parent) _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(); } @@ -208,12 +213,6 @@ int OsmdroidMap::zoomOut() return _zoom; } -void OsmdroidMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - Q_UNUSED(deviceRatio); - _mapRatio = mapRatio; -} - qreal OsmdroidMap::tileSize() const { return (_tileSize / _mapRatio); @@ -310,7 +309,7 @@ Coordinates OsmdroidMap::xy2ll(const QPointF &p) 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) *isDir = false; diff --git a/src/map/osmdroidmap.h b/src/map/osmdroidmap.h index 7b7b913c..6344b2a0 100644 --- a/src/map/osmdroidmap.h +++ b/src/map/osmdroidmap.h @@ -11,7 +11,7 @@ public: OsmdroidMap(const QString &fileName, QObject *parent = 0); QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} qreal resolution(const QRectF &rect); int zoom() const {return _zoom;} @@ -25,14 +25,14 @@ public: 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: int limitZoom(int zoom) const; diff --git a/src/map/ozf.cpp b/src/map/ozf.cpp index 7ff7499d..1cd68a44 100644 --- a/src/map/ozf.cpp +++ b/src/map/ozf.cpp @@ -182,6 +182,9 @@ bool OZF::open() if (!_file.open(QIODevice::ReadOnly)) return false; + if (!_zooms.isEmpty()) + return true; + if (!readHeaders()) { qWarning("%s: Invalid header", qPrintable(_file.fileName())); _file.close(); @@ -232,7 +235,6 @@ QPixmap OZF::tile(int zoom, int x, int y) QSize OZF::size(int zoom) const { - Q_ASSERT(_file.isOpen()); Q_ASSERT(0 <= zoom && zoom < _zooms.count()); return _zooms.at(zoom).size; diff --git a/src/map/ozf.h b/src/map/ozf.h index 9e46ee65..a7551dfd 100644 --- a/src/map/ozf.h +++ b/src/map/ozf.h @@ -16,6 +16,7 @@ public: _file(name) {} bool open(); + void close() {_file.close();} QString fileName() const {return _file.fileName();} bool isOpen() const {return _file.isOpen();} diff --git a/src/map/ozimap.cpp b/src/map/ozimap.cpp index dc6fea03..e72b40b2 100644 --- a/src/map/ozimap.cpp +++ b/src/map/ozimap.cpp @@ -50,6 +50,8 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent) if (!setTileInfo(_tar->files())) return; + + _tar->close(); } else { QFile file(fileName); MapFile mf(file); @@ -105,6 +107,16 @@ OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent) _transform = mf.transform(); _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; } @@ -144,6 +156,7 @@ bool OziMap::setImageInfo(const QString &path) return false; } _scale = _ozf->scale(_zoom); + _ozf->close(); } else { QImageReader ir(_map.path); if (!ir.canRead()) { @@ -192,28 +205,42 @@ bool OziMap::setTileInfo(const QStringList &tiles, const QString &path) return false; } -void OziMap::load() +void OziMap::load(const Projection &in, const Projection &out, + qreal deviceRatio, bool hidpi) { - if (_tar && !_tar->isOpen()) { - if (!_tar->open()) { - qWarning("%s: error loading tar file", - qPrintable(_tar->fileName())); - return; - } - if (!setTileInfo(_tar->files())) - qWarning("%s: %s", qPrintable(_tar->fileName()), - qPrintable(_errorString)); - return; - } + Q_UNUSED(in); + Q_UNUSED(out); - 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); + if (_img) + _img->setDevicePixelRatio(_mapRatio); + } } void OziMap::unload() { delete _img; _img = 0; + + if (_tar && _tar->isOpen()) + _tar->close(); + + if (_ozf && _ozf->isOpen()) + _ozf->close(); } void OziMap::drawTiled(QPainter *painter, const QRectF &rect) const @@ -368,16 +395,7 @@ void OziMap::rescale(int zoom) _scale = _ozf->scale(zoom); } -void OziMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - Q_UNUSED(deviceRatio); - - _mapRatio = mapRatio; - if (_img) - _img->setDevicePixelRatio(_mapRatio); -} - -Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir) +Map *OziMap::createTAR(const QString &path, bool *isDir) { if (isDir) *isDir = false; @@ -385,7 +403,7 @@ Map *OziMap::createTAR(const QString &path, const Projection &, bool *isDir) 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) *isDir = false; diff --git a/src/map/ozimap.h b/src/map/ozimap.h index 68b0a002..517ee97a 100644 --- a/src/map/ozimap.h +++ b/src/map/ozimap.h @@ -33,8 +33,8 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); bool isValid() const {return _valid;} @@ -47,8 +47,8 @@ public: QPointF pp2xy(const PointD &p) const {return _transform.proj2img(p) / _mapRatio;} - static Map *createTAR(const QString &path, const Projection &, bool *isDir); - static Map *createMAP(const QString &path, const Projection &, bool *isDir); + static Map *createTAR(const QString &path, bool *isDir); + static Map *createMAP(const QString &path, bool *isDir); private: struct ImageInfo { diff --git a/src/map/qctmap.cpp b/src/map/qctmap.cpp index cebb70d7..be195cf8 100644 --- a/src/map/qctmap.cpp +++ b/src/map/qctmap.cpp @@ -354,8 +354,13 @@ QCTMap::QCTMap(const QString &fileName, QObject *parent) _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); } @@ -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) *isDir = false; diff --git a/src/map/qctmap.h b/src/map/qctmap.h index a29bf728..f2e1b498 100644 --- a/src/map/qctmap.h +++ b/src/map/qctmap.h @@ -21,16 +21,14 @@ public: 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 setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) - {_mapRatio = mapRatio;} - bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: bool readName(QDataStream &stream); diff --git a/src/map/rmap.cpp b/src/map/rmap.cpp index ee3fcf0b..69bd2be8 100644 --- a/src/map/rmap.cpp +++ b/src/map/rmap.cpp @@ -355,8 +355,13 @@ Coordinates RMap::xy2ll(const QPointF &p) 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); } @@ -455,13 +460,7 @@ void RMap::draw(QPainter *painter, const QRectF &rect, Flags flags) } } -void RMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - Q_UNUSED(deviceRatio); - _mapRatio = mapRatio; -} - -Map *RMap::create(const QString &path, const Projection &, bool *isDir) +Map *RMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; diff --git a/src/map/rmap.h b/src/map/rmap.h index 7eed061f..fe02ac15 100644 --- a/src/map/rmap.h +++ b/src/map/rmap.h @@ -25,8 +25,8 @@ public: QPointF ll2xy(const Coordinates &c); Coordinates xy2ll(const QPointF &p); - void setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - void load(); + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void unload(); void draw(QPainter *painter, const QRectF &rect, Flags flags); @@ -34,7 +34,7 @@ public: bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: struct Header { diff --git a/src/map/sqlitemap.cpp b/src/map/sqlitemap.cpp index b35dc1d0..6f7f4878 100644 --- a/src/map/sqlitemap.cpp +++ b/src/map/sqlitemap.cpp @@ -100,8 +100,13 @@ SqliteMap::SqliteMap(const QString &fileName, QObject *parent) _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(); } @@ -156,12 +161,6 @@ int SqliteMap::zoomOut() return _zoom; } -void SqliteMap::setDevicePixelRatio(qreal deviceRatio, qreal mapRatio) -{ - Q_UNUSED(deviceRatio); - _mapRatio = mapRatio; -} - qreal SqliteMap::tileSize() const { return (_tileSize / _mapRatio); @@ -257,7 +256,7 @@ Coordinates SqliteMap::xy2ll(const QPointF &p) 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) *isDir = false; diff --git a/src/map/sqlitemap.h b/src/map/sqlitemap.h index 99285304..67328fbe 100644 --- a/src/map/sqlitemap.h +++ b/src/map/sqlitemap.h @@ -11,7 +11,7 @@ public: SqliteMap(const QString &fileName, QObject *parent = 0); QRectF bounds(); - RectC llBounds() {return _bounds;} + RectC llBounds(const Projection &) {return _bounds;} qreal resolution(const QRectF &rect); int zoom() const {return _zoom;} @@ -25,14 +25,14 @@ public: 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); bool isValid() const {return _valid;} QString errorString() const {return _errorString;} - static Map *create(const QString &path, const Projection &, bool *isDir); + static Map *create(const QString &path, bool *isDir); private: int limitZoom(int zoom) const; diff --git a/src/map/tar.cpp b/src/map/tar.cpp index 0ed8e1d9..d1a10508 100644 --- a/src/map/tar.cpp +++ b/src/map/tar.cpp @@ -49,6 +49,9 @@ bool Tar::open() if (!_file.open(QIODevice::ReadOnly)) return false; + if (!_index.isEmpty()) + return true; + QFileInfo fi(_file.fileName()); QString tmiPath = fi.path() + "/" + fi.completeBaseName() + ".tmi"; diff --git a/src/map/tar.h b/src/map/tar.h index 03800659..54982eb4 100644 --- a/src/map/tar.h +++ b/src/map/tar.h @@ -11,6 +11,7 @@ public: Tar(const QString &name) : _file(name) {} bool open(); + void close() {_file.close();} QStringList files() const {return _index.keys();} QByteArray file(const QString &name); diff --git a/src/map/wmsmap.cpp b/src/map/wmsmap.cpp index 053d9591..8147a73e 100644 --- a/src/map/wmsmap.cpp +++ b/src/map/wmsmap.cpp @@ -99,6 +99,15 @@ void WMSMap::wmsReady() 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() { _tileLoader->clearCache(); diff --git a/src/map/wmsmap.h b/src/map/wmsmap.h index 909eafde..eb21a31e 100644 --- a/src/map/wmsmap.h +++ b/src/map/wmsmap.h @@ -20,7 +20,7 @@ public: QString name() const {return _name;} QRectF bounds(); - RectC llBounds() {return _wms->bbox();} + RectC llBounds(const Projection &) {return _wms->bbox();} int zoom() const {return _zoom;} void setZoom(int zoom); @@ -33,8 +33,8 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) - {_mapRatio = mapRatio;} + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void clearCache(); bool isReady() const {return _wms->isReady();} diff --git a/src/map/wmtsmap.cpp b/src/map/wmtsmap.cpp index 7896fbb3..1da2dd29 100644 --- a/src/map/wmtsmap.cpp +++ b/src/map/wmtsmap.cpp @@ -44,6 +44,15 @@ void WMTSMap::wmtsReady() 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() { _tileLoader->clearCache(); @@ -97,7 +106,7 @@ QRectF WMTSMap::bounds() return lb.isValid() ? lb & tb : tb; } -RectC WMTSMap::llBounds() +RectC WMTSMap::llBounds(const Projection &) { if (_wmts->bbox().isValid()) return _wmts->bbox(); diff --git a/src/map/wmtsmap.h b/src/map/wmtsmap.h index 4b23c7e2..68af58c0 100644 --- a/src/map/wmtsmap.h +++ b/src/map/wmtsmap.h @@ -20,7 +20,7 @@ public: QString name() const {return _name;} QRectF bounds(); - RectC llBounds(); + RectC llBounds(const Projection &); int zoom() const {return _zoom;} void setZoom(int zoom); @@ -33,8 +33,8 @@ public: void draw(QPainter *painter, const QRectF &rect, Flags flags); - void setDevicePixelRatio(qreal /*deviceRatio*/, qreal mapRatio) - {_mapRatio = mapRatio;} + void load(const Projection &in, const Projection &out, qreal deviceRatio, + bool hidpi); void clearCache(); bool isReady() const {return _wmts->isReady();} diff --git a/src/map/worldfilemap.cpp b/src/map/worldfilemap.cpp index 61b15d45..e5dcd572 100644 --- a/src/map/worldfilemap.cpp +++ b/src/map/worldfilemap.cpp @@ -9,9 +9,8 @@ #include "worldfilemap.h" -WorldFileMap::WorldFileMap(const QString &fileName, const Projection &proj, - QObject *parent) : Map(fileName, parent), _projection(proj), _img(0), - _ratio(1.0), _hasPRJ(false), _valid(false) +WorldFileMap::WorldFileMap(const QString &fileName, QObject *parent) + : Map(fileName, parent), _img(0), _mapRatio(1.0), _hasPRJ(false), _valid(false) { QFileInfo fi(fileName); QDir dir(fi.absoluteDir()); @@ -74,17 +73,25 @@ WorldFileMap::~WorldFileMap() 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) { - 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() { - return QRectF(QPointF(0, 0), _size / _ratio); + return QRectF(QPointF(0, 0), _size / _mapRatio); } 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); } -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) - _img->setDevicePixelRatio(_ratio); -} - -void WorldFileMap::load() -{ - if (!_img) - _img = new Image(_imgFile); + _img->setDevicePixelRatio(_mapRatio); } void WorldFileMap::unload() @@ -114,19 +122,10 @@ void WorldFileMap::unload() _img = 0; } -void WorldFileMap::setInputProjection(const Projection &projection) -{ - if (_hasPRJ || !projection.isValid() || projection == _projection) - return; - - _projection = projection; -} - -Map *WorldFileMap::create(const QString &path, const Projection &proj, - bool *isDir) +Map *WorldFileMap::create(const QString &path, bool *isDir) { if (isDir) *isDir = false; - return new WorldFileMap(path, proj); + return new WorldFileMap(path); } diff --git a/src/map/worldfilemap.h b/src/map/worldfilemap.h index 59ec3518..4de84397 100644 --- a/src/map/worldfilemap.h +++ b/src/map/worldfilemap.h @@ -12,32 +12,31 @@ class WorldFileMap : public Map Q_OBJECT public: - WorldFileMap(const QString &fileName, const Projection &proj, - QObject *parent = 0); + WorldFileMap(const QString &fileName, QObject *parent = 0); ~WorldFileMap(); + RectC llBounds(const Projection &proj); QRectF bounds(); QPointF ll2xy(const Coordinates &c); Coordinates xy2ll(const QPointF &p); 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 setDevicePixelRatio(qreal deviceRatio, qreal mapRatio); - void setInputProjection(const Projection &projection); bool isValid() const {return _valid;} 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: Projection _projection; Transform _transform; Image *_img; QSize _size; - qreal _ratio; + qreal _mapRatio; QString _imgFile; bool _hasPRJ;