mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-28 05:34:47 +01:00
Added support for Garmin JNX maps
This commit is contained in:
parent
ba7074f902
commit
0d879e61a9
@ -15,6 +15,7 @@ HEADERS += src/config.h \
|
|||||||
src/common/rectc.h \
|
src/common/rectc.h \
|
||||||
src/common/wgs84.h \
|
src/common/wgs84.h \
|
||||||
src/common/str2int.h \
|
src/common/str2int.h \
|
||||||
|
src/common/rtree.h \
|
||||||
src/GUI/app.h \
|
src/GUI/app.h \
|
||||||
src/GUI/icons.h \
|
src/GUI/icons.h \
|
||||||
src/GUI/gui.h \
|
src/GUI/gui.h \
|
||||||
@ -117,7 +118,6 @@ HEADERS += src/config.h \
|
|||||||
src/data/trackdata.h \
|
src/data/trackdata.h \
|
||||||
src/data/routedata.h \
|
src/data/routedata.h \
|
||||||
src/data/path.h \
|
src/data/path.h \
|
||||||
src/data/rtree.h \
|
|
||||||
src/data/gpxparser.h \
|
src/data/gpxparser.h \
|
||||||
src/data/tcxparser.h \
|
src/data/tcxparser.h \
|
||||||
src/data/csvparser.h \
|
src/data/csvparser.h \
|
||||||
@ -128,7 +128,8 @@ HEADERS += src/config.h \
|
|||||||
src/data/oziparsers.h \
|
src/data/oziparsers.h \
|
||||||
src/map/rectd.h \
|
src/map/rectd.h \
|
||||||
src/map/geocentric.h \
|
src/map/geocentric.h \
|
||||||
src/map/mercator.h
|
src/map/mercator.h \
|
||||||
|
src/map/jnxmap.h
|
||||||
SOURCES += src/main.cpp \
|
SOURCES += src/main.cpp \
|
||||||
src/common/coordinates.cpp \
|
src/common/coordinates.cpp \
|
||||||
src/common/rectc.cpp \
|
src/common/rectc.cpp \
|
||||||
@ -224,7 +225,8 @@ SOURCES += src/main.cpp \
|
|||||||
src/data/nmeaparser.cpp \
|
src/data/nmeaparser.cpp \
|
||||||
src/data/oziparsers.cpp \
|
src/data/oziparsers.cpp \
|
||||||
src/map/geocentric.cpp \
|
src/map/geocentric.cpp \
|
||||||
src/map/mercator.cpp
|
src/map/mercator.cpp \
|
||||||
|
src/map/jnxmap.cpp
|
||||||
RESOURCES += gpxsee.qrc
|
RESOURCES += gpxsee.qrc
|
||||||
TRANSLATIONS = lang/gpxsee_cs.ts \
|
TRANSLATIONS = lang/gpxsee_cs.ts \
|
||||||
lang/gpxsee_sv.ts \
|
lang/gpxsee_sv.ts \
|
||||||
|
@ -75,7 +75,6 @@ MapView::MapView(Map *map, POI *poi, QWidget *parent)
|
|||||||
_plot = false;
|
_plot = false;
|
||||||
_digitalZoom = 0;
|
_digitalZoom = 0;
|
||||||
|
|
||||||
_map->setBackgroundColor(_backgroundColor);
|
|
||||||
_res = _map->resolution(_map->bounds());
|
_res = _map->resolution(_map->bounds());
|
||||||
_scene->setSceneRect(_map->bounds());
|
_scene->setSceneRect(_map->bounds());
|
||||||
|
|
||||||
@ -267,7 +266,6 @@ void MapView::setMap(Map *map)
|
|||||||
|
|
||||||
_map = map;
|
_map = map;
|
||||||
_map->load();
|
_map->load();
|
||||||
_map->setBackgroundColor(_backgroundColor);
|
|
||||||
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
connect(_map, SIGNAL(loaded()), this, SLOT(reloadMap()));
|
||||||
|
|
||||||
digitalZoom(0);
|
digitalZoom(0);
|
||||||
@ -746,7 +744,6 @@ void MapView::setMapOpacity(int opacity)
|
|||||||
void MapView::setBackgroundColor(const QColor &color)
|
void MapView::setBackgroundColor(const QColor &color)
|
||||||
{
|
{
|
||||||
_backgroundColor = color;
|
_backgroundColor = color;
|
||||||
_map->setBackgroundColor(color);
|
|
||||||
resetCachedContent();
|
resetCachedContent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
#include <QPointF>
|
#include <QPointF>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include "rtree.h"
|
#include "common/rtree.h"
|
||||||
#include "waypoint.h"
|
#include "waypoint.h"
|
||||||
#include "path.h"
|
#include "path.h"
|
||||||
|
|
||||||
|
@ -276,7 +276,6 @@ void Atlas::draw(QPainter *painter, const QRectF &rect, bool block)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Multiple maps
|
// Multiple maps
|
||||||
painter->fillRect(rect, _backgroundColor);
|
|
||||||
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
for (int i = _zooms.at(_zoom).first; i <= _zooms.at(_zoom).last; i++) {
|
||||||
QRectF ir = rect.intersected(_bounds.at(i).xy);
|
QRectF ir = rect.intersected(_bounds.at(i).xy);
|
||||||
if (!ir.isNull())
|
if (!ir.isNull())
|
||||||
|
@ -87,8 +87,9 @@ int EmptyMap::zoomOut()
|
|||||||
|
|
||||||
void EmptyMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
void EmptyMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
||||||
{
|
{
|
||||||
|
Q_UNUSED(painter);
|
||||||
|
Q_UNUSED(rect);
|
||||||
Q_UNUSED(block);
|
Q_UNUSED(block);
|
||||||
painter->fillRect(rect, _backgroundColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF EmptyMap::ll2xy(const Coordinates &c) const
|
QPointF EmptyMap::ll2xy(const Coordinates &c) const
|
||||||
|
244
src/map/jnxmap.cpp
Normal file
244
src/map/jnxmap.cpp
Normal file
@ -0,0 +1,244 @@
|
|||||||
|
#include <QtEndian>
|
||||||
|
#include <QPainter>
|
||||||
|
#include <QFileInfo>
|
||||||
|
#include "transform.h"
|
||||||
|
#include "rectd.h"
|
||||||
|
#include "jnxmap.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct Level {
|
||||||
|
quint32 count;
|
||||||
|
quint32 offset;
|
||||||
|
quint32 scale;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Ctx {
|
||||||
|
QPainter *painter;
|
||||||
|
QFile *file;
|
||||||
|
|
||||||
|
Ctx(QPainter *painter, QFile *file) : painter(painter), file(file) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template<class T> bool JNXMap::readValue(T &val)
|
||||||
|
{
|
||||||
|
T data;
|
||||||
|
|
||||||
|
if (_file.read((char*)&data, sizeof(T)) < (qint64)sizeof(T))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (sizeof(T) > 1)
|
||||||
|
val = qFromLittleEndian(data);
|
||||||
|
else
|
||||||
|
val = data;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::readString(QByteArray& ba)
|
||||||
|
{
|
||||||
|
char byte;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
if (!_file.getChar(&byte))
|
||||||
|
return false;
|
||||||
|
else if (!byte)
|
||||||
|
return true;
|
||||||
|
else
|
||||||
|
ba += byte;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::readTiles()
|
||||||
|
{
|
||||||
|
qint32 lat1, lon2, lat2, lon1;
|
||||||
|
quint32 version, dummy, levels;
|
||||||
|
|
||||||
|
if (!(readValue(version) && readValue(dummy) && readValue(lat1)
|
||||||
|
&& readValue(lon2) && readValue(lat2) && readValue(lon1)
|
||||||
|
&& readValue(levels)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_bounds = RectC(Coordinates(lon1 * 180.0 / 0x7FFFFFFF, lat1 * 180.0
|
||||||
|
/ 0x7FFFFFFF), Coordinates(lon2 * 180.0 / 0x7FFFFFFF, lat2 * 180.0
|
||||||
|
/ 0x7FFFFFFF));
|
||||||
|
|
||||||
|
if (!_file.seek(version > 3 ? 0x34 : 0x30))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QVector<Level> lh(levels);
|
||||||
|
for (int i = 0; i < lh.count(); i++) {
|
||||||
|
if (!(readValue(lh[i].count) && readValue(lh[i].offset)
|
||||||
|
&& readValue(lh[i].scale)))
|
||||||
|
return false;
|
||||||
|
if (version > 3) {
|
||||||
|
QByteArray ba;
|
||||||
|
if (!(readValue(dummy) && readString(ba)))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
_zooms = QVector<Zoom>(lh.size());
|
||||||
|
for (int i = 0; i < lh.count(); i++) {
|
||||||
|
if (!_file.seek(lh.at(i).offset))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
_zooms[i].tiles = QVector<Tile>(lh.at(i).count);
|
||||||
|
for (quint32 j = 0; j < lh.at(i).count; j++) {
|
||||||
|
Tile &tile = _zooms[i].tiles[j];
|
||||||
|
qint32 top, right, bottom, left;
|
||||||
|
quint16 width, height;
|
||||||
|
|
||||||
|
if (!(readValue(top) && readValue(right) && readValue(bottom)
|
||||||
|
&& readValue(left) && readValue(width)
|
||||||
|
&& readValue(height) && readValue(tile.size)
|
||||||
|
&& readValue(tile.offset)))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
RectD rect(PointD(left * 180.0 / 0x7FFFFFFF, top * 180.0
|
||||||
|
/ 0x7FFFFFFF), PointD(right * 180.0 / 0x7FFFFFFF, bottom * 180.0
|
||||||
|
/ 0x7FFFFFFF));
|
||||||
|
|
||||||
|
if (j == 0) {
|
||||||
|
ReferencePoint tl(PointD(0, 0), rect.topLeft());
|
||||||
|
ReferencePoint br(PointD(width, height), rect.bottomRight());
|
||||||
|
_zooms[i].transform = Transform(tl, br);
|
||||||
|
}
|
||||||
|
|
||||||
|
const Transform &t = _zooms.at(i).transform;
|
||||||
|
QRectF trect(t.proj2img(rect.topLeft()),
|
||||||
|
t.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();
|
||||||
|
_zooms[i].tree.Insert(min, max, &tile);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
JNXMap::JNXMap(const QString &fileName, QObject *parent)
|
||||||
|
: Map(parent), _file(fileName), _zoom(0), _valid(false)
|
||||||
|
{
|
||||||
|
_name = QFileInfo(fileName).fileName();
|
||||||
|
|
||||||
|
if (!_file.open(QIODevice::ReadOnly)) {
|
||||||
|
_errorString = QString("%1: Error opening file").arg(fileName);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!readTiles()) {
|
||||||
|
_errorString = "JNX file format error";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPointF JNXMap::ll2xy(const Coordinates &c) const
|
||||||
|
{
|
||||||
|
const Transform &t = _zooms.at(_zoom).transform;
|
||||||
|
return t.proj2img(PointD(c.lon(), c.lat()));
|
||||||
|
}
|
||||||
|
|
||||||
|
Coordinates JNXMap::xy2ll(const QPointF &p) const
|
||||||
|
{
|
||||||
|
const Transform &t = _zooms.at(_zoom).transform;
|
||||||
|
PointD pp(t.img2proj(p));
|
||||||
|
return Coordinates(pp.x(), pp.y());
|
||||||
|
}
|
||||||
|
|
||||||
|
QRectF JNXMap::bounds() const
|
||||||
|
{
|
||||||
|
const Transform &t = _zooms.at(_zoom).transform;
|
||||||
|
|
||||||
|
return QRectF(t.proj2img(PointD(_bounds.topLeft().lon(),
|
||||||
|
_bounds.topLeft().lat())), t.proj2img(PointD(_bounds.bottomRight().lon(),
|
||||||
|
_bounds.bottomRight().lat())));
|
||||||
|
}
|
||||||
|
|
||||||
|
qreal JNXMap::resolution(const QRectF &rect) const
|
||||||
|
{
|
||||||
|
Coordinates tl = xy2ll((rect.topLeft()));
|
||||||
|
Coordinates br = xy2ll(rect.bottomRight());
|
||||||
|
|
||||||
|
qreal ds = tl.distanceTo(br);
|
||||||
|
qreal ps = QLineF(rect.topLeft(), rect.bottomRight()).length();
|
||||||
|
|
||||||
|
return ds/ps;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomFit(const QSize &size, const RectC &rect)
|
||||||
|
{
|
||||||
|
if (!rect.isValid())
|
||||||
|
_zoom = _zooms.size() - 1;
|
||||||
|
else {
|
||||||
|
for (int i = 1; i < _zooms.count(); i++) {
|
||||||
|
_zoom = i;
|
||||||
|
QRect sbr(QPoint(ll2xy(rect.topLeft()).toPoint()),
|
||||||
|
QPoint(ll2xy(rect.bottomRight()).toPoint()));
|
||||||
|
if (sbr.size().width() >= size.width() || sbr.size().height()
|
||||||
|
>= size.height()) {
|
||||||
|
_zoom--;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomIn()
|
||||||
|
{
|
||||||
|
_zoom = qMin(_zoom + 1, _zooms.size() - 1);
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
int JNXMap::zoomOut()
|
||||||
|
{
|
||||||
|
_zoom = qMax(_zoom - 1, 0);
|
||||||
|
return _zoom;
|
||||||
|
}
|
||||||
|
|
||||||
|
QPixmap JNXMap::pixmap(const Tile *tile, QFile *file)
|
||||||
|
{
|
||||||
|
QByteArray ba;
|
||||||
|
ba.resize(tile->size + 2);
|
||||||
|
ba[0] = (char)0xFF;
|
||||||
|
ba[1] = (char)0xD8;
|
||||||
|
char *data = ba.data() + 2;
|
||||||
|
|
||||||
|
if (!file->seek(tile->offset))
|
||||||
|
return QPixmap();
|
||||||
|
if (!file->read(data, tile->size))
|
||||||
|
return QPixmap();
|
||||||
|
|
||||||
|
return QPixmap::fromImage(QImage::fromData(ba));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool JNXMap::cb(Tile *tile, void *context)
|
||||||
|
{
|
||||||
|
Ctx *ctx = static_cast<Ctx*>(context);
|
||||||
|
ctx->painter->drawPixmap(tile->pos, pixmap(tile, ctx->file));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void JNXMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
||||||
|
{
|
||||||
|
Q_UNUSED(block);
|
||||||
|
const RTree<Tile*, qreal, 2> &tree = _zooms.at(_zoom).tree;
|
||||||
|
Ctx ctx(painter, &_file);
|
||||||
|
|
||||||
|
qreal min[2], max[2];
|
||||||
|
min[0] = rect.left();
|
||||||
|
min[1] = rect.top();
|
||||||
|
max[0] = rect.right();
|
||||||
|
max[1] = rect.bottom();
|
||||||
|
tree.Search(min, max, cb, &ctx);
|
||||||
|
}
|
73
src/map/jnxmap.h
Normal file
73
src/map/jnxmap.h
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
#ifndef JNXMAP_H
|
||||||
|
#define JNXMAP_H
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QVector>
|
||||||
|
#include "common/rtree.h"
|
||||||
|
#include "common/rectc.h"
|
||||||
|
#include "transform.h"
|
||||||
|
#include "map.h"
|
||||||
|
|
||||||
|
class JNXMap : public Map
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
JNXMap(const QString &fileName, QObject *parent = 0);
|
||||||
|
|
||||||
|
const QString &name() const {return _name;}
|
||||||
|
|
||||||
|
QRectF bounds() const;
|
||||||
|
qreal resolution(const QRectF &rect) const;
|
||||||
|
|
||||||
|
int zoom() const {return _zoom;}
|
||||||
|
void setZoom(int zoom) {_zoom = zoom;}
|
||||||
|
int zoomFit(const QSize &size, const RectC &rect);
|
||||||
|
int zoomIn();
|
||||||
|
int zoomOut();
|
||||||
|
|
||||||
|
QPointF ll2xy(const Coordinates &c)
|
||||||
|
{return static_cast<const JNXMap &>(*this).ll2xy(c);}
|
||||||
|
Coordinates xy2ll(const QPointF &p)
|
||||||
|
{return static_cast<const JNXMap &>(*this).xy2ll(p);}
|
||||||
|
|
||||||
|
void draw(QPainter *painter, const QRectF &rect, bool block);
|
||||||
|
|
||||||
|
bool isValid() const {return _valid;}
|
||||||
|
QString errorString() const {return _errorString;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct Tile {
|
||||||
|
QPointF pos;
|
||||||
|
quint32 size;
|
||||||
|
quint32 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Zoom {
|
||||||
|
Transform transform;
|
||||||
|
QVector<Tile> tiles;
|
||||||
|
RTree<Tile*, qreal, 2> tree;
|
||||||
|
};
|
||||||
|
|
||||||
|
QPointF ll2xy(const Coordinates &c) const;
|
||||||
|
Coordinates xy2ll(const QPointF &p) const;
|
||||||
|
|
||||||
|
template<class T> bool readValue(T &val);
|
||||||
|
bool readString(QByteArray &ba);
|
||||||
|
bool readTiles();
|
||||||
|
|
||||||
|
static bool cb(Tile *tile, void *context);
|
||||||
|
static QPixmap pixmap(const Tile *tile, QFile *file);
|
||||||
|
|
||||||
|
QString _name;
|
||||||
|
QFile _file;
|
||||||
|
QVector<Zoom> _zooms;
|
||||||
|
int _zoom;
|
||||||
|
RectC _bounds;
|
||||||
|
|
||||||
|
bool _valid;
|
||||||
|
QString _errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // JNXMAP_H
|
@ -15,7 +15,7 @@ class Map : public QObject
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Map(QObject *parent = 0) : QObject(parent), _backgroundColor(Qt::white) {}
|
Map(QObject *parent = 0) : QObject(parent) {}
|
||||||
virtual ~Map() {}
|
virtual ~Map() {}
|
||||||
|
|
||||||
virtual const QString &name() const = 0;
|
virtual const QString &name() const = 0;
|
||||||
@ -41,13 +41,8 @@ public:
|
|||||||
virtual bool isValid() const {return true;}
|
virtual bool isValid() const {return true;}
|
||||||
virtual QString errorString() const {return QString();}
|
virtual QString errorString() const {return QString();}
|
||||||
|
|
||||||
void setBackgroundColor(const QColor &color) {_backgroundColor = color;}
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void loaded();
|
void loaded();
|
||||||
|
|
||||||
protected:
|
|
||||||
QColor _backgroundColor;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAP_H
|
#endif // MAP_H
|
||||||
|
@ -3,33 +3,13 @@
|
|||||||
#include "atlas.h"
|
#include "atlas.h"
|
||||||
#include "offlinemap.h"
|
#include "offlinemap.h"
|
||||||
#include "onlinemap.h"
|
#include "onlinemap.h"
|
||||||
|
#include "jnxmap.h"
|
||||||
#include "mapsource.h"
|
#include "mapsource.h"
|
||||||
#include "maplist.h"
|
#include "maplist.h"
|
||||||
|
|
||||||
|
|
||||||
bool MapList::loadSource(const QString &path, bool dir)
|
bool MapList::loadMap(Map* map, const QString &path, bool dir)
|
||||||
{
|
{
|
||||||
MapSource ms;
|
|
||||||
Map *map;
|
|
||||||
|
|
||||||
if (!(map = ms.loadFile(path))) {
|
|
||||||
if (dir)
|
|
||||||
_errorString += path + ": " + ms.errorString() + "\n";
|
|
||||||
else
|
|
||||||
_errorString = ms.errorString();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
map->setParent(this);
|
|
||||||
_maps.append(map);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool MapList::loadMap(const QString &path, bool dir)
|
|
||||||
{
|
|
||||||
OfflineMap *map = new OfflineMap(path, this);
|
|
||||||
|
|
||||||
if (map->isValid()) {
|
if (map->isValid()) {
|
||||||
_maps.append(map);
|
_maps.append(map);
|
||||||
return true;
|
return true;
|
||||||
@ -38,26 +18,27 @@ bool MapList::loadMap(const QString &path, bool dir)
|
|||||||
_errorString += path + ": " + map->errorString() + "\n";
|
_errorString += path + ": " + map->errorString() + "\n";
|
||||||
else
|
else
|
||||||
_errorString = map->errorString();
|
_errorString = map->errorString();
|
||||||
|
|
||||||
delete map;
|
delete map;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapList::loadAtlas(const QString &path, bool dir)
|
bool MapList::loadSource(const QString &path, bool dir)
|
||||||
{
|
{
|
||||||
Atlas *atlas = new Atlas(path, this);
|
QString err;
|
||||||
|
Map *map = MapSource::loadMap(path, err);
|
||||||
|
|
||||||
if (atlas->isValid()) {
|
if (!map) {
|
||||||
_maps.append(atlas);
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
if (dir)
|
if (dir)
|
||||||
_errorString += path + ": " + atlas->errorString() + "\n";
|
_errorString += path + ": " + err + "\n";
|
||||||
else
|
else
|
||||||
_errorString = atlas->errorString();
|
_errorString = err;
|
||||||
delete atlas;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
map->setParent(this);
|
||||||
|
|
||||||
|
return loadMap(map, path, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
|
bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
|
||||||
@ -67,14 +48,13 @@ bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
|
|||||||
|
|
||||||
if (Atlas::isAtlas(path)) {
|
if (Atlas::isAtlas(path)) {
|
||||||
*atlas = true;
|
*atlas = true;
|
||||||
return loadAtlas(path, dir);
|
return loadMap(new Atlas(path, this), path, dir);
|
||||||
} else if (suffix == "xml") {
|
} else if (suffix == "xml")
|
||||||
*atlas = false;
|
|
||||||
return loadSource(path, dir);
|
return loadSource(path, dir);
|
||||||
} else {
|
else if (suffix == "jnx")
|
||||||
*atlas = false;
|
return loadMap(new JNXMap(path, this), path, dir);
|
||||||
return loadMap(path, dir);
|
else
|
||||||
}
|
return loadMap(new OfflineMap(path, this), path, dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapList::loadDirR(const QString &path)
|
bool MapList::loadDirR(const QString &path)
|
||||||
@ -83,11 +63,12 @@ bool MapList::loadDirR(const QString &path)
|
|||||||
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
md.setFilter(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
md.setSorting(QDir::DirsLast);
|
md.setSorting(QDir::DirsLast);
|
||||||
QFileInfoList ml = md.entryInfoList();
|
QFileInfoList ml = md.entryInfoList();
|
||||||
bool atlas, ret = true;
|
bool ret = true;
|
||||||
|
|
||||||
for (int i = 0; i < ml.size(); i++) {
|
for (int i = 0; i < ml.size(); i++) {
|
||||||
const QFileInfo &fi = ml.at(i);
|
const QFileInfo &fi = ml.at(i);
|
||||||
QString suffix = fi.suffix().toLower();
|
QString suffix = fi.suffix().toLower();
|
||||||
|
bool atlas = false;
|
||||||
|
|
||||||
if (fi.isDir() && fi.fileName() != "set") {
|
if (fi.isDir() && fi.fileName() != "set") {
|
||||||
if (!loadDirR(fi.absoluteFilePath()))
|
if (!loadDirR(fi.absoluteFilePath()))
|
||||||
@ -127,7 +108,8 @@ void MapList::clear()
|
|||||||
QString MapList::formats()
|
QString MapList::formats()
|
||||||
{
|
{
|
||||||
return
|
return
|
||||||
tr("Supported files") + " (*.map *.tar *.tba *.tif *.tiff *.xml);;"
|
tr("Supported files") + " (*.jnx *.map *.tar *.tba *.tif *.tiff *.xml);;"
|
||||||
|
+ tr("Garmin JNX maps") + " (*.jnx);;"
|
||||||
+ tr("OziExplorer maps") + " (*.map);;"
|
+ tr("OziExplorer maps") + " (*.map);;"
|
||||||
+ tr("TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
+ tr("TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||||
+ tr("GeoTIFF images") + " (*.tif *.tiff);;"
|
+ tr("GeoTIFF images") + " (*.tif *.tiff);;"
|
||||||
@ -137,6 +119,7 @@ QString MapList::formats()
|
|||||||
QStringList MapList::filter()
|
QStringList MapList::filter()
|
||||||
{
|
{
|
||||||
QStringList filter;
|
QStringList filter;
|
||||||
filter << "*.map" << "*.tba" << "*.tar" << "*.xml" << "*.tif" << "*.tiff";
|
filter << "*.jnx *.map" << "*.tba" << "*.tar" << "*.xml" << "*.tif"
|
||||||
|
<< "*.tiff";
|
||||||
return filter;
|
return filter;
|
||||||
}
|
}
|
||||||
|
@ -26,12 +26,8 @@ public:
|
|||||||
private:
|
private:
|
||||||
bool loadFile(const QString &path, bool *atlas, bool dir);
|
bool loadFile(const QString &path, bool *atlas, bool dir);
|
||||||
bool loadDirR(const QString &path);
|
bool loadDirR(const QString &path);
|
||||||
|
|
||||||
Map *loadListEntry(const QByteArray &line);
|
|
||||||
|
|
||||||
bool loadSource(const QString &path, bool dir);
|
bool loadSource(const QString &path, bool dir);
|
||||||
bool loadMap(const QString &path, bool dir);
|
bool loadMap(Map *map, const QString &path, bool dir);
|
||||||
bool loadAtlas(const QString &path, bool dir);
|
|
||||||
|
|
||||||
QList<Map*> _maps;
|
QList<Map*> _maps;
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
|
@ -164,20 +164,18 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Map *MapSource::loadFile(const QString &path)
|
Map *MapSource::loadMap(const QString &path, QString &errorString)
|
||||||
{
|
{
|
||||||
QFile file(path);
|
|
||||||
QXmlStreamReader reader;
|
|
||||||
Config config;
|
Config config;
|
||||||
Map *m;
|
QFile file(path);
|
||||||
|
|
||||||
|
|
||||||
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
if (!file.open(QFile::ReadOnly | QFile::Text)) {
|
||||||
_errorString = file.errorString();
|
errorString = file.errorString();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
reader.setDevice(&file);
|
QXmlStreamReader reader(&file);
|
||||||
if (reader.readNextStartElement()) {
|
if (reader.readNextStartElement()) {
|
||||||
if (reader.name() == "map")
|
if (reader.name() == "map")
|
||||||
map(reader, config);
|
map(reader, config);
|
||||||
@ -185,59 +183,51 @@ Map *MapSource::loadFile(const QString &path)
|
|||||||
reader.raiseError("Not an online map source file");
|
reader.raiseError("Not an online map source file");
|
||||||
}
|
}
|
||||||
if (reader.error()) {
|
if (reader.error()) {
|
||||||
_errorString = QString("%1: %2").arg(reader.lineNumber())
|
errorString = QString("%1: %2").arg(reader.lineNumber())
|
||||||
.arg(reader.errorString());
|
.arg(reader.errorString());
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.name.isEmpty()) {
|
if (config.name.isEmpty()) {
|
||||||
_errorString = "Missing name definition";
|
errorString = "Missing name definition";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (config.url.isEmpty()) {
|
if (config.url.isEmpty()) {
|
||||||
_errorString = "Missing URL definition";
|
errorString = "Missing URL definition";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (config.type == WMTS || config.type == WMS) {
|
if (config.type == WMTS || config.type == WMS) {
|
||||||
if (config.layer.isEmpty()) {
|
if (config.layer.isEmpty()) {
|
||||||
_errorString = "Missing layer definition";
|
errorString = "Missing layer definition";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (config.format.isEmpty()) {
|
if (config.format.isEmpty()) {
|
||||||
_errorString = "Missing format definition";
|
errorString = "Missing format definition";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config.type == WMTS) {
|
if (config.type == WMTS) {
|
||||||
if (config.set.isEmpty()) {
|
if (config.set.isEmpty()) {
|
||||||
_errorString = "Missing set definiton";
|
errorString = "Missing set definiton";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (config.type == WMS) {
|
if (config.type == WMS) {
|
||||||
if (config.crs.isEmpty()) {
|
if (config.crs.isEmpty()) {
|
||||||
_errorString = "Missing CRS definiton";
|
errorString = "Missing CRS definiton";
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (config.type == WMTS)
|
if (config.type == WMTS)
|
||||||
m = new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
|
return new WMTSMap(config.name, WMTS::Setup(config.url, config.layer,
|
||||||
config.set, config.style, config.format, config.rest,
|
config.set, config.style, config.format, config.rest,
|
||||||
config.coordinateSystem, config.dimensions, config.authorization));
|
config.coordinateSystem, config.dimensions, config.authorization));
|
||||||
else if (config.type == WMS)
|
else if (config.type == WMS)
|
||||||
m = new WMSMap(config.name, WMS::Setup(config.url, config.layer,
|
return new WMSMap(config.name, WMS::Setup(config.url, config.layer,
|
||||||
config.style, config.format, config.crs, config.coordinateSystem,
|
config.style, config.format, config.crs, config.coordinateSystem,
|
||||||
config.dimensions, config.authorization));
|
config.dimensions, config.authorization));
|
||||||
else
|
else
|
||||||
m = new OnlineMap(config.name, config.url, config.zooms, config.bounds,
|
return new OnlineMap(config.name, config.url, config.zooms,
|
||||||
config.authorization);
|
config.bounds, config.authorization);
|
||||||
|
|
||||||
if (!m->isValid()) {
|
|
||||||
_errorString = m->errorString();
|
|
||||||
delete m;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
|
@ -13,8 +13,7 @@ class QXmlStreamReader;
|
|||||||
class MapSource
|
class MapSource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Map *loadFile(const QString &path);
|
static Map *loadMap(const QString &path, QString &errorString);
|
||||||
const QString &errorString() const {return _errorString;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Type {
|
enum Type {
|
||||||
@ -42,11 +41,9 @@ private:
|
|||||||
Config();
|
Config();
|
||||||
};
|
};
|
||||||
|
|
||||||
RectC bounds(QXmlStreamReader &reader);
|
static RectC bounds(QXmlStreamReader &reader);
|
||||||
Range zooms(QXmlStreamReader &reader);
|
static Range zooms(QXmlStreamReader &reader);
|
||||||
void map(QXmlStreamReader &reader, Config &config);
|
static void map(QXmlStreamReader &reader, Config &config);
|
||||||
|
|
||||||
QString _errorString;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // MAPSOURCE_H
|
#endif // MAPSOURCE_H
|
||||||
|
@ -262,12 +262,10 @@ void OfflineMap::drawTiled(QPainter *painter, const QRectF &rect) const
|
|||||||
} else
|
} else
|
||||||
pixmap = QPixmap(tileName);
|
pixmap = QPixmap(tileName);
|
||||||
|
|
||||||
if (pixmap.isNull()) {
|
if (pixmap.isNull())
|
||||||
qWarning("%s: error loading tile image", qPrintable(
|
qWarning("%s: error loading tile image", qPrintable(
|
||||||
_tile.path.arg(QString::number(x), QString::number(y))));
|
_tile.path.arg(QString::number(x), QString::number(y))));
|
||||||
painter->fillRect(QRectF(QPoint(x, y), _tile.size),
|
else
|
||||||
_backgroundColor);
|
|
||||||
} else
|
|
||||||
painter->drawPixmap(QPoint(x, y), pixmap);
|
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -294,11 +292,9 @@ void OfflineMap::drawOZF(QPainter *painter, const QRectF &rect) const
|
|||||||
QPixmapCache::insert(key, pixmap);
|
QPixmapCache::insert(key, pixmap);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pixmap.isNull()) {
|
if (pixmap.isNull())
|
||||||
qWarning("%s: error loading tile image", qPrintable(key));
|
qWarning("%s: error loading tile image", qPrintable(key));
|
||||||
painter->fillRect(QRectF(QPoint(x, y), _ozf->tileSize()),
|
else
|
||||||
_backgroundColor);
|
|
||||||
} else
|
|
||||||
painter->drawPixmap(QPoint(x, y), pixmap);
|
painter->drawPixmap(QPoint(x, y), pixmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -321,8 +317,6 @@ void OfflineMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
|||||||
drawTiled(painter, rect);
|
drawTiled(painter, rect);
|
||||||
else if (_img && !_img->isNull())
|
else if (_img && !_img->isNull())
|
||||||
drawImage(painter, rect);
|
drawImage(painter, rect);
|
||||||
else
|
|
||||||
painter->fillRect(rect, _backgroundColor);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
QPointF OfflineMap::ll2xy(const Coordinates &c) const
|
QPointF OfflineMap::ll2xy(const Coordinates &c) const
|
||||||
|
@ -136,10 +136,7 @@ void OnlineMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
|||||||
Tile &t = tiles[i];
|
Tile &t = tiles[i];
|
||||||
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE,
|
QPoint tp(tl.x() + (t.xy().x() - tile.x()) * TILE_SIZE,
|
||||||
tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE);
|
tl.y() + (t.xy().y() - tile.y()) * TILE_SIZE);
|
||||||
if (t.pixmap().isNull())
|
if (!t.pixmap().isNull())
|
||||||
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
|
|
||||||
_backgroundColor);
|
|
||||||
else
|
|
||||||
painter->drawPixmap(tp, t.pixmap());
|
painter->drawPixmap(tp, t.pixmap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -227,10 +227,7 @@ void WMSMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
|||||||
for (int i = 0; i < tiles.count(); i++) {
|
for (int i = 0; i < tiles.count(); i++) {
|
||||||
Tile &t = tiles[i];
|
Tile &t = tiles[i];
|
||||||
QPoint tp(t.xy().x() * TILE_SIZE, t.xy().y() * TILE_SIZE);
|
QPoint tp(t.xy().x() * TILE_SIZE, t.xy().y() * TILE_SIZE);
|
||||||
if (t.pixmap().isNull())
|
if (!t.pixmap().isNull())
|
||||||
painter->fillRect(QRect(tp, QSize(TILE_SIZE, TILE_SIZE)),
|
|
||||||
_backgroundColor);
|
|
||||||
else
|
|
||||||
painter->drawPixmap(tp, t.pixmap());
|
painter->drawPixmap(tp, t.pixmap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -184,9 +184,7 @@ void WMTSMap::draw(QPainter *painter, const QRectF &rect, bool block)
|
|||||||
for (int i = 0; i < tiles.count(); i++) {
|
for (int i = 0; i < tiles.count(); i++) {
|
||||||
Tile &t = tiles[i];
|
Tile &t = tiles[i];
|
||||||
QPoint tp(t.xy().x() * z.tile().width(), t.xy().y() * z.tile().height());
|
QPoint tp(t.xy().x() * z.tile().width(), t.xy().y() * z.tile().height());
|
||||||
if (t.pixmap().isNull())
|
if (!t.pixmap().isNull())
|
||||||
painter->fillRect(QRect(tp, z.tile()), _backgroundColor);
|
|
||||||
else
|
|
||||||
painter->drawPixmap(tp, t.pixmap());
|
painter->drawPixmap(tp, t.pixmap());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user