mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Support all variants of TrekBuddy maps/atlases
Added support for gmi calibration files and arbitrary named tba/map/gmi files.
This commit is contained in:
parent
b38cf31920
commit
722f3acb1e
@ -134,6 +134,7 @@ HEADERS += src/common/config.h \
|
||||
src/map/encmap.h \
|
||||
src/map/ENC/iso8211.h \
|
||||
src/map/gemfmap.h \
|
||||
src/map/gmifile.h \
|
||||
src/map/oruxmap.h \
|
||||
src/map/osmdroidmap.h \
|
||||
src/map/proj/polyconic.h \
|
||||
@ -347,6 +348,7 @@ SOURCES += src/main.cpp \
|
||||
src/map/encmap.cpp \
|
||||
src/map/ENC/iso8211.cpp \
|
||||
src/map/gemfmap.cpp \
|
||||
src/map/gmifile.cpp \
|
||||
src/map/oruxmap.cpp \
|
||||
src/map/osmdroidmap.cpp \
|
||||
src/map/proj/polyconic.cpp \
|
||||
|
@ -27,6 +27,34 @@ static bool yCmp(OziMap *m1, OziMap *m2)
|
||||
return TL(m1).y() > TL(m2).y();
|
||||
}
|
||||
|
||||
static QString calibrationFile(const QString &path)
|
||||
{
|
||||
QDir dir(path);
|
||||
QFileInfoList files = dir.entryInfoList(QDir::Files);
|
||||
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
const QFileInfo &fi = files.at(i);
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (suffix == "map" || suffix == "gmi")
|
||||
return fi.absoluteFilePath();
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
static QString tbaFile(const QStringList &files)
|
||||
{
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
QFileInfo fi(files.at(i));
|
||||
|
||||
if (fi.path() == "." && fi.suffix().toLower() == "tba")
|
||||
return files.at(i);
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
void Atlas::computeZooms()
|
||||
{
|
||||
std::sort(_maps.begin(), _maps.end(), resCmp);
|
||||
@ -86,7 +114,11 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
QString tbaFileName = fi.completeBaseName() + ".tba";
|
||||
QString tbaFileName(tbaFile(tar.files()));
|
||||
if (tbaFileName.isNull()) {
|
||||
_errorString = "No tba file found";
|
||||
return;
|
||||
}
|
||||
ba = tar.file(tbaFileName);
|
||||
} else {
|
||||
QFile tbaFile(fileName);
|
||||
@ -97,7 +129,7 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
ba = tbaFile.readAll();
|
||||
}
|
||||
if (!ba.startsWith("Atlas 1.0")) {
|
||||
_errorString = "Missing or invalid tba file";
|
||||
_errorString = "Invalid tba file";
|
||||
return;
|
||||
}
|
||||
|
||||
@ -108,20 +140,23 @@ Atlas::Atlas(const QString &fileName, bool TAR, QObject *parent)
|
||||
QFileInfoList maps = zdir.entryInfoList(QDir::Dirs
|
||||
| QDir::NoDotAndDotDot);
|
||||
for (int i = 0; i < maps.count(); i++) {
|
||||
QString mapFile = maps.at(i).absoluteFilePath() + "/"
|
||||
+ maps.at(i).fileName() + ".map";
|
||||
|
||||
OziMap *map;
|
||||
if (tar.isOpen())
|
||||
map = new OziMap(mapFile, tar, this);
|
||||
else
|
||||
map = new OziMap(mapFile, TAR, this);
|
||||
if (TAR)
|
||||
map = new OziMap(maps.at(i).absoluteFilePath(), tar, this);
|
||||
else {
|
||||
QString cf(calibrationFile(maps.at(i).absoluteFilePath()));
|
||||
if (cf.isNull()) {
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
map = new OziMap(cf, this);
|
||||
}
|
||||
|
||||
if (map->isValid())
|
||||
_maps.append(map);
|
||||
else {
|
||||
_errorString = QString("Error loading map: %1: %2")
|
||||
.arg(mapFile, map->errorString());
|
||||
_errorString = QString("%1: %2")
|
||||
.arg(map->path(), map->errorString());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
97
src/map/gmifile.cpp
Normal file
97
src/map/gmifile.cpp
Normal file
@ -0,0 +1,97 @@
|
||||
#include "common/csv.h"
|
||||
#include "pcs.h"
|
||||
#include "gmifile.h"
|
||||
|
||||
static CalibrationPoint calibrationPoint(const QByteArray line)
|
||||
{
|
||||
bool xOk, yOk, lonOk, latOk;
|
||||
QList<QByteArray> list = line.split(';');
|
||||
if (list.size() != 4)
|
||||
return CalibrationPoint();
|
||||
|
||||
int x = list.at(0).toInt(&xOk);
|
||||
int y = list.at(1).toInt(&yOk);
|
||||
double lon = list.at(2).toDouble(&lonOk);
|
||||
double lat = list.at(3).toDouble(&latOk);
|
||||
|
||||
return (xOk && yOk && latOk && lonOk)
|
||||
? CalibrationPoint(PointD(x, y), Coordinates(lon, lat))
|
||||
: CalibrationPoint();
|
||||
}
|
||||
|
||||
bool GmiFile::parse(QIODevice &device, QList<CalibrationPoint> &points)
|
||||
{
|
||||
int ln = 1;
|
||||
int width, height;
|
||||
bool ok;
|
||||
|
||||
if (!device.open(QIODevice::ReadOnly)) {
|
||||
_errorString = device.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
while (!device.atEnd()) {
|
||||
QByteArray line = device.readLine(4096);
|
||||
|
||||
if (ln == 1) {
|
||||
if (!line.startsWith("Map Calibration data file")) {
|
||||
_errorString = "Not a GMI file";
|
||||
return false;
|
||||
}
|
||||
} else if (ln == 2)
|
||||
_image = line.trimmed();
|
||||
else if (ln == 3) {
|
||||
width = line.toInt(&ok);
|
||||
if (!ok || ok <= 0) {
|
||||
_errorString = "Invalid image width";
|
||||
return false;
|
||||
}
|
||||
} else if (ln == 4) {
|
||||
height = line.toInt(&ok);
|
||||
if (!ok || ok <= 0) {
|
||||
_errorString = "Invalid image height";
|
||||
return false;
|
||||
}
|
||||
_size = QSize(width, height);
|
||||
} else {
|
||||
CalibrationPoint cp(calibrationPoint(line));
|
||||
if (cp.isValid())
|
||||
points.append(cp);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
ln++;
|
||||
}
|
||||
|
||||
device.close();
|
||||
|
||||
return (points.size() >= 2);
|
||||
}
|
||||
|
||||
bool GmiFile::computeTransformation(const QList<CalibrationPoint> &points)
|
||||
{
|
||||
QList<ReferencePoint> rp;
|
||||
Projection proj(GCS::WGS84());
|
||||
|
||||
for (int i = 0; i < points.size(); i++)
|
||||
rp.append(points.at(i).rp(proj));
|
||||
|
||||
_transform = Transform(rp);
|
||||
if (!_transform.isValid()) {
|
||||
_errorString = _transform.errorString();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
GmiFile::GmiFile(QIODevice &file)
|
||||
{
|
||||
QList<CalibrationPoint> points;
|
||||
|
||||
if (!parse(file, points))
|
||||
return;
|
||||
if (!computeTransformation(points))
|
||||
return;
|
||||
}
|
33
src/map/gmifile.h
Normal file
33
src/map/gmifile.h
Normal file
@ -0,0 +1,33 @@
|
||||
#ifndef GMIFILE_H
|
||||
#define GMIFILE_H
|
||||
|
||||
#include "transform.h"
|
||||
#include "calibrationpoint.h"
|
||||
|
||||
class QIODevice;
|
||||
class GCS;
|
||||
|
||||
class GmiFile
|
||||
{
|
||||
public:
|
||||
GmiFile(QIODevice &file);
|
||||
|
||||
bool isValid() const {return !_image.isNull() && _transform.isValid();}
|
||||
const QString &errorString() const {return _errorString;}
|
||||
|
||||
const Transform &transform() const {return _transform;}
|
||||
const QString &image() const {return _image;}
|
||||
const QSize &size() const {return _size;}
|
||||
|
||||
private:
|
||||
bool parse(QIODevice &device, QList<CalibrationPoint> &points);
|
||||
bool computeTransformation(const QList<CalibrationPoint> &points);
|
||||
|
||||
QString _image;
|
||||
QSize _size;
|
||||
Transform _transform;
|
||||
|
||||
QString _errorString;
|
||||
};
|
||||
|
||||
#endif // GMIFILE_H
|
@ -43,6 +43,7 @@ MapList::ParserMap MapList::parsers()
|
||||
map.insert("rtmap", &RMap::create);
|
||||
map.insert("map", &MapsforgeMap::create);
|
||||
map.insert("map", &OziMap::createMAP);
|
||||
map.insert("gmi", &OziMap::createMAP);
|
||||
map.insert("kap", &BSBMap::create);
|
||||
map.insert("kmz", &KMZMap::create);
|
||||
map.insert("aqm", &AQMMap::create);
|
||||
@ -173,7 +174,8 @@ QString MapList::formats()
|
||||
+ qApp->translate("MapList", "Osmdroid SQLite maps") + " (*.sqlite);;"
|
||||
+ qApp->translate("MapList", "Locus/OsmAnd/RMaps SQLite maps")
|
||||
+ " (*.sqlitedb);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases") + " (*.tar *.tba);;"
|
||||
+ qApp->translate("MapList", "TrekBuddy maps/atlases")
|
||||
+ " (*.tar *.tba *.gmi *.map);;"
|
||||
+ qApp->translate("MapList", "GeoTIFF images") + " (*.tif *.tiff);;"
|
||||
+ qApp->translate("MapList", "World-file georeferenced images")
|
||||
+ " (*.wld *.jgw *.gfw *.pgw *.tfw);;"
|
||||
|
@ -12,42 +12,68 @@
|
||||
#include "ozf.h"
|
||||
#include "image.h"
|
||||
#include "mapfile.h"
|
||||
#include "gmifile.h"
|
||||
#include "rectd.h"
|
||||
#include "ozimap.h"
|
||||
|
||||
|
||||
static QString mapFile(const QStringList &files)
|
||||
QString OziMap::calibrationFile(const QStringList &files, const QString path,
|
||||
CalibrationType &type)
|
||||
{
|
||||
for (int i = 0; i < files.size(); i++) {
|
||||
QFileInfo fi(files.at(i));
|
||||
if (fi.path() == "." && fi.suffix() == "map")
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (path.endsWith(fi.path())) {
|
||||
if (suffix == "map") {
|
||||
type = MAP;
|
||||
return files.at(i);
|
||||
} else if (suffix == "gmi") {
|
||||
type = GMI;
|
||||
return files.at(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type = Unknown;
|
||||
return QString();
|
||||
}
|
||||
|
||||
OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
OziMap::OziMap(const QString &fileName, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
_hasProj(true), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QString suffix(fi.suffix().toLower());
|
||||
|
||||
if (suffix == "tar") {
|
||||
CalibrationType type;
|
||||
|
||||
if (TAR) {
|
||||
_tar = new Tar(fileName);
|
||||
if (!_tar->open()) {
|
||||
_errorString = "Error reading tar file";
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList files(_tar->files());
|
||||
QString mapFileName(mapFile(files));
|
||||
if (mapFileName.isNull()) {
|
||||
_errorString = "No map file found in tar file";
|
||||
return;
|
||||
}
|
||||
QString cf(calibrationFile(files, ".", type));
|
||||
|
||||
QByteArray ba(_tar->file(mapFileName));
|
||||
if (type == GMI) {
|
||||
QByteArray ba(_tar->file(cf));
|
||||
QBuffer buffer(&ba);
|
||||
GmiFile gmi(buffer);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = Util::file2name(fileName);
|
||||
_map.size = gmi.size();
|
||||
_map.path = gmi.image();
|
||||
_transform = gmi.transform();
|
||||
_projection = Projection(GCS::WGS84());
|
||||
_hasProj = false;
|
||||
}
|
||||
} else if (type == MAP) {
|
||||
QByteArray ba(_tar->file(cf));
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
@ -60,6 +86,10 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
} else {
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!setTileInfo(files))
|
||||
return;
|
||||
@ -67,6 +97,8 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
_tar->close();
|
||||
} else {
|
||||
QFile file(fileName);
|
||||
|
||||
if (suffix == "map") {
|
||||
MapFile mf(file);
|
||||
if (!mf.isValid()) {
|
||||
_errorString = mf.errorString();
|
||||
@ -78,6 +110,23 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
}
|
||||
} else if (suffix == "gmi") {
|
||||
GmiFile gmi(file);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
} else {
|
||||
_name = Util::file2name(fileName);
|
||||
_map.size = gmi.size();
|
||||
_map.path = gmi.image();
|
||||
_transform = gmi.transform();
|
||||
_projection = Projection(GCS::WGS84());
|
||||
_hasProj = false;
|
||||
}
|
||||
} else {
|
||||
_errorString = "Unknown file type";
|
||||
return;
|
||||
}
|
||||
|
||||
QDir set(fi.absolutePath() + "/" + "set");
|
||||
if (set.exists()) {
|
||||
@ -92,21 +141,15 @@ OziMap::OziMap(const QString &fileName, bool TAR, QObject *parent)
|
||||
_valid = true;
|
||||
}
|
||||
|
||||
OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
: Map(fileName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_valid(false)
|
||||
OziMap::OziMap(const QString &dirName, Tar &tar, QObject *parent)
|
||||
: Map(dirName, parent), _img(0), _tar(0), _ozf(0), _zoom(0), _mapRatio(1.0),
|
||||
_hasProj(true), _valid(false)
|
||||
{
|
||||
QFileInfo fi(fileName);
|
||||
QFileInfo map(fi.absolutePath());
|
||||
QFileInfo layer(map.absolutePath());
|
||||
QString mapFile = layer.fileName() + "/" + map.fileName() + "/"
|
||||
+ fi.fileName();
|
||||
CalibrationType type;
|
||||
QString cf(calibrationFile(tar.files(), dirName, type));
|
||||
|
||||
QByteArray ba = tar.file(mapFile);
|
||||
if (ba.isNull()) {
|
||||
_errorString = "Map file not found";
|
||||
return;
|
||||
}
|
||||
if (type == MAP) {
|
||||
QByteArray ba = tar.file(cf);
|
||||
QBuffer buffer(&ba);
|
||||
MapFile mf(buffer);
|
||||
if (!mf.isValid()) {
|
||||
@ -118,7 +161,28 @@ OziMap::OziMap(const QString &fileName, Tar &tar, QObject *parent)
|
||||
_map.size = mf.size();
|
||||
_projection = mf.projection();
|
||||
_transform = mf.transform();
|
||||
_tar = new Tar(fi.absolutePath() + "/" + fi.completeBaseName() + ".tar");
|
||||
} else if (type == GMI) {
|
||||
QByteArray ba = tar.file(cf);
|
||||
QBuffer buffer(&ba);
|
||||
GmiFile gmi(buffer);
|
||||
if (!gmi.isValid()) {
|
||||
_errorString = gmi.errorString();
|
||||
return;
|
||||
}
|
||||
|
||||
_name = Util::file2name(cf);
|
||||
_map.size = gmi.size();
|
||||
_transform = gmi.transform();
|
||||
_projection = Projection(GCS::WGS84());
|
||||
_hasProj = false;
|
||||
} else {
|
||||
_errorString = "No calibration file found";
|
||||
return;
|
||||
}
|
||||
|
||||
QFileInfo fi(cf);
|
||||
QDir dir(dirName);
|
||||
_tar = new Tar(dir.absoluteFilePath(fi.completeBaseName() + ".tar"));
|
||||
|
||||
if (!_tar->open()) {
|
||||
_errorString = _tar->fileName() + ": error reading tar file";
|
||||
@ -221,10 +285,11 @@ bool OziMap::setTileInfo(const QStringList &tiles, const QString &path)
|
||||
void OziMap::load(const Projection &in, const Projection &out,
|
||||
qreal deviceRatio, bool hidpi)
|
||||
{
|
||||
Q_UNUSED(in);
|
||||
Q_UNUSED(out);
|
||||
|
||||
_mapRatio = hidpi ? deviceRatio : 1.0;
|
||||
if (!_hasProj)
|
||||
_projection = in;
|
||||
|
||||
if (_tar) {
|
||||
Q_ASSERT(!_tar->isOpen());
|
||||
@ -413,7 +478,7 @@ Map *OziMap::createTAR(const QString &path, bool *isDir)
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new OziMap(path, true);
|
||||
return new OziMap(path);
|
||||
}
|
||||
|
||||
Map *OziMap::createMAP(const QString &path, bool *isDir)
|
||||
@ -421,5 +486,5 @@ Map *OziMap::createMAP(const QString &path, bool *isDir)
|
||||
if (isDir)
|
||||
*isDir = false;
|
||||
|
||||
return new OziMap(path, false);
|
||||
return new OziMap(path);
|
||||
}
|
||||
|
@ -14,8 +14,8 @@ class OziMap : public Map
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
OziMap(const QString &fileName, bool TAR, QObject *parent = 0);
|
||||
OziMap(const QString &fileName, Tar &tar, QObject *parent = 0);
|
||||
OziMap(const QString &fileName, QObject *parent = 0);
|
||||
OziMap(const QString &dirName, Tar &tar, QObject *parent = 0);
|
||||
~OziMap();
|
||||
|
||||
QString name() const {return _name;}
|
||||
@ -51,6 +51,10 @@ public:
|
||||
static Map *createMAP(const QString &path, bool *isDir);
|
||||
|
||||
private:
|
||||
enum CalibrationType {
|
||||
Unknown, MAP, GMI
|
||||
};
|
||||
|
||||
struct ImageInfo {
|
||||
QSize size;
|
||||
QString path;
|
||||
@ -67,6 +71,9 @@ private:
|
||||
|
||||
void rescale(int zoom);
|
||||
|
||||
static QString calibrationFile(const QStringList &files, const QString path,
|
||||
CalibrationType &type);
|
||||
|
||||
QString _name;
|
||||
Projection _projection;
|
||||
Transform _transform;
|
||||
@ -77,6 +84,7 @@ private:
|
||||
int _zoom;
|
||||
QPointF _scale;
|
||||
qreal _mapRatio;
|
||||
bool _hasProj;
|
||||
|
||||
bool _valid;
|
||||
QString _errorString;
|
||||
|
Loading…
Reference in New Issue
Block a user