mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-27 21:24:47 +01:00
Added support for GMAP maps
This commit is contained in:
parent
e2339c67cd
commit
911c63df0c
@ -91,8 +91,10 @@ HEADERS += src/common/config.h \
|
|||||||
src/map/IMG/bitmapline.h \
|
src/map/IMG/bitmapline.h \
|
||||||
src/map/IMG/bitstream.h \
|
src/map/IMG/bitstream.h \
|
||||||
src/map/IMG/deltastream.h \
|
src/map/IMG/deltastream.h \
|
||||||
|
src/map/IMG/gmap.h \
|
||||||
src/map/IMG/huffmanstream.h \
|
src/map/IMG/huffmanstream.h \
|
||||||
src/map/IMG/huffmantable.h \
|
src/map/IMG/huffmantable.h \
|
||||||
|
src/map/IMG/mapdata.h \
|
||||||
src/map/IMG/textpathitem.h \
|
src/map/IMG/textpathitem.h \
|
||||||
src/map/IMG/textpointitem.h \
|
src/map/IMG/textpointitem.h \
|
||||||
src/map/projection.h \
|
src/map/projection.h \
|
||||||
@ -249,8 +251,10 @@ SOURCES += src/main.cpp \
|
|||||||
src/map/IMG/bitmapline.cpp \
|
src/map/IMG/bitmapline.cpp \
|
||||||
src/map/IMG/bitstream.cpp \
|
src/map/IMG/bitstream.cpp \
|
||||||
src/map/IMG/deltastream.cpp \
|
src/map/IMG/deltastream.cpp \
|
||||||
|
src/map/IMG/gmap.cpp \
|
||||||
src/map/IMG/huffmanstream.cpp \
|
src/map/IMG/huffmanstream.cpp \
|
||||||
src/map/IMG/huffmantable.cpp \
|
src/map/IMG/huffmantable.cpp \
|
||||||
|
src/map/IMG/mapdata.cpp \
|
||||||
src/map/IMG/textpathitem.cpp \
|
src/map/IMG/textpathitem.cpp \
|
||||||
src/map/IMG/textpointitem.cpp \
|
src/map/IMG/textpointitem.cpp \
|
||||||
src/map/maplist.cpp \
|
src/map/maplist.cpp \
|
||||||
|
@ -32,7 +32,7 @@ bool BitStream1::read(int bits, quint32 &val)
|
|||||||
|
|
||||||
bool BitStream1::flush()
|
bool BitStream1::flush()
|
||||||
{
|
{
|
||||||
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
|
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_length = 0;
|
_length = 0;
|
||||||
@ -68,7 +68,7 @@ bool BitStream4::read(int bits, quint32 &val)
|
|||||||
|
|
||||||
bool BitStream4::flush()
|
bool BitStream4::flush()
|
||||||
{
|
{
|
||||||
if (_length && !_file.seek(_hdl, _hdl.pos + _length))
|
if (_length && !_file.seek(_hdl, _hdl.pos() + _length))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
_length = 0;
|
_length = 0;
|
||||||
|
151
src/map/IMG/gmap.cpp
Normal file
151
src/map/IMG/gmap.cpp
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
#include <QXmlStreamReader>
|
||||||
|
#include <QDir>
|
||||||
|
#include "vectortile.h"
|
||||||
|
#include "gmap.h"
|
||||||
|
|
||||||
|
|
||||||
|
static SubFile::Type tileType(const QString &suffix)
|
||||||
|
{
|
||||||
|
if (!suffix.compare("TRE"))
|
||||||
|
return SubFile::TRE;
|
||||||
|
else if (!suffix.compare("RGN"))
|
||||||
|
return SubFile::RGN;
|
||||||
|
else if (!suffix.compare("LBL"))
|
||||||
|
return SubFile::LBL;
|
||||||
|
else if (!suffix.compare("TYP"))
|
||||||
|
return SubFile::TYP;
|
||||||
|
else if (!suffix.compare("GMP"))
|
||||||
|
return SubFile::GMP;
|
||||||
|
else if (!suffix.compare("NET"))
|
||||||
|
return SubFile::NET;
|
||||||
|
else
|
||||||
|
return SubFile::Unknown;
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMAP::subProduct(QXmlStreamReader &reader, QString &dataDir,
|
||||||
|
QString &baseMap)
|
||||||
|
{
|
||||||
|
while (reader.readNextStartElement()) {
|
||||||
|
if (reader.name() == "Directory")
|
||||||
|
dataDir = reader.readElementText();
|
||||||
|
else if (reader.name() == "BaseMap")
|
||||||
|
baseMap = reader.readElementText();
|
||||||
|
else
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GMAP::mapProduct(QXmlStreamReader &reader, QString &dataDir,
|
||||||
|
QString &typFile, QString &baseMap)
|
||||||
|
{
|
||||||
|
while (reader.readNextStartElement()) {
|
||||||
|
if (reader.name() == "Name")
|
||||||
|
_name = reader.readElementText();
|
||||||
|
else if (reader.name() == "TYP")
|
||||||
|
typFile = reader.readElementText();
|
||||||
|
else if (reader.name() == "SubProduct")
|
||||||
|
subProduct(reader, dataDir, baseMap);
|
||||||
|
else
|
||||||
|
reader.skipCurrentElement();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GMAP::readXML(const QString &path, QString &dataDir, QString &typFile,
|
||||||
|
QString &baseMap)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
|
||||||
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QXmlStreamReader reader(&file);
|
||||||
|
if (reader.readNextStartElement()) {
|
||||||
|
if (reader.name() == "MapProduct")
|
||||||
|
mapProduct(reader, dataDir, typFile, baseMap);
|
||||||
|
else
|
||||||
|
reader.raiseError("Not a GMAP XML file");
|
||||||
|
}
|
||||||
|
if (reader.error()) {
|
||||||
|
_errorString = QString("%1: %2").arg(reader.lineNumber())
|
||||||
|
.arg(reader.errorString());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GMAP::loadTile(const QDir &dir, quint16 &id)
|
||||||
|
{
|
||||||
|
VectorTile *tile = new VectorTile();
|
||||||
|
|
||||||
|
QFileInfoList ml = dir.entryInfoList(QDir::Files);
|
||||||
|
for (int i = 0; i < ml.size(); i++) {
|
||||||
|
const QFileInfo &fi = ml.at(i);
|
||||||
|
SubFile::Type type = tileType(fi.suffix());
|
||||||
|
if (VectorTile::isTileFile(type)) {
|
||||||
|
SubFile *file = tile->addFile(fi.absoluteFilePath(), type);
|
||||||
|
file->setId(id++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!tile->init()) {
|
||||||
|
qWarning("%s: Invalid map tile", qPrintable(dir.path()));
|
||||||
|
delete tile;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
double min[2], max[2];
|
||||||
|
min[0] = tile->bounds().left();
|
||||||
|
min[1] = tile->bounds().bottom();
|
||||||
|
max[0] = tile->bounds().right();
|
||||||
|
max[1] = tile->bounds().top();
|
||||||
|
_tileTree.Insert(min, max, tile);
|
||||||
|
|
||||||
|
_bounds |= tile->bounds();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
GMAP::GMAP(const QString &fileName) : _fileName(fileName)
|
||||||
|
{
|
||||||
|
QString dataDirPath, typFile, baseMap;
|
||||||
|
if (!readXML(fileName, dataDirPath, typFile, baseMap))
|
||||||
|
return;
|
||||||
|
|
||||||
|
QDir baseDir(QFileInfo(fileName).absoluteDir());
|
||||||
|
if (!baseDir.exists(dataDirPath)) {
|
||||||
|
_errorString = "Missing/invalid map data directory";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
QDir dataDir(baseDir.filePath(dataDirPath));
|
||||||
|
QFileInfoList ml = dataDir.entryInfoList(QDir::Dirs | QDir::NoDotAndDotDot);
|
||||||
|
|
||||||
|
quint16 id = 0;
|
||||||
|
for (int i = 0; i < ml.size(); i++) {
|
||||||
|
const QFileInfo &fi = ml.at(i);
|
||||||
|
if (fi.isDir() && fi.baseName() != baseMap)
|
||||||
|
loadTile(QDir(fi.absoluteFilePath()), id);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (baseDir.exists(typFile))
|
||||||
|
_typ = new SubFile(baseDir.filePath(typFile));
|
||||||
|
|
||||||
|
if (!_tileTree.Count())
|
||||||
|
_errorString = "No usable map tile found";
|
||||||
|
else
|
||||||
|
_valid = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GMAP::isGMAP(const QString &path)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
|
||||||
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QXmlStreamReader reader(&file);
|
||||||
|
if (reader.readNextStartElement() && reader.name() == "MapProduct")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
30
src/map/IMG/gmap.h
Normal file
30
src/map/IMG/gmap.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#ifndef GMAP_H
|
||||||
|
#define GMAP_H
|
||||||
|
|
||||||
|
#include "mapdata.h"
|
||||||
|
|
||||||
|
class QXmlStreamReader;
|
||||||
|
class QDir;
|
||||||
|
|
||||||
|
class GMAP : public MapData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
GMAP(const QString &fileName);
|
||||||
|
|
||||||
|
QString fileName() const {return _fileName;}
|
||||||
|
|
||||||
|
static bool isGMAP(const QString &path);
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _fileName;
|
||||||
|
|
||||||
|
bool readXML(const QString &path, QString &dataDir, QString &typFile,
|
||||||
|
QString &baseMap);
|
||||||
|
void mapProduct(QXmlStreamReader &reader, QString &dataDir,
|
||||||
|
QString &typFile, QString &baseMap);
|
||||||
|
void subProduct(QXmlStreamReader &reader, QString &dataDir,
|
||||||
|
QString &baseMap);
|
||||||
|
bool loadTile(const QDir &dir, quint16 &id);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // GMAP_H
|
@ -55,7 +55,7 @@ bool HuffmanTable::getBuffer(const SubFile &file, SubFile::Handle &hdl,
|
|||||||
return false;
|
return false;
|
||||||
if (!file.readVUInt32(hdl, recordSize))
|
if (!file.readVUInt32(hdl, recordSize))
|
||||||
return false;
|
return false;
|
||||||
recordOffset = hdl.pos + recordSize;
|
recordOffset = hdl.pos() + recordSize;
|
||||||
if (recordOffset > offset + size)
|
if (recordOffset > offset + size)
|
||||||
return false;
|
return false;
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
#include <QMap>
|
#include <QMap>
|
||||||
#include <QtEndian>
|
#include <QtEndian>
|
||||||
#include "common/programpaths.h"
|
|
||||||
#include "vectortile.h"
|
#include "vectortile.h"
|
||||||
#include "img.h"
|
#include "img.h"
|
||||||
|
|
||||||
@ -8,32 +8,6 @@
|
|||||||
|
|
||||||
typedef QMap<QString, VectorTile*> TileMap;
|
typedef QMap<QString, VectorTile*> TileMap;
|
||||||
|
|
||||||
struct PolyCTX
|
|
||||||
{
|
|
||||||
PolyCTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
|
||||||
QList<IMG::Poly> *lines, QCache<const SubDiv*, IMG::Polys> *polyCache)
|
|
||||||
: rect(rect), bits(bits), polygons(polygons), lines(lines),
|
|
||||||
polyCache(polyCache) {}
|
|
||||||
|
|
||||||
const RectC ▭
|
|
||||||
int bits;
|
|
||||||
QList<IMG::Poly> *polygons;
|
|
||||||
QList<IMG::Poly> *lines;
|
|
||||||
QCache<const SubDiv*, IMG::Polys> *polyCache;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PointCTX
|
|
||||||
{
|
|
||||||
PointCTX(const RectC &rect, int bits, QList<IMG::Point> *points,
|
|
||||||
QCache<const SubDiv*, QList<IMG::Point> > *pointCache)
|
|
||||||
: rect(rect), bits(bits), points(points), pointCache(pointCache) {}
|
|
||||||
|
|
||||||
const RectC ▭
|
|
||||||
int bits;
|
|
||||||
QList<IMG::Point> *points;
|
|
||||||
QCache<const SubDiv*, QList<IMG::Point> > *pointCache;
|
|
||||||
};
|
|
||||||
|
|
||||||
static SubFile::Type tileType(const char str[3])
|
static SubFile::Type tileType(const char str[3])
|
||||||
{
|
{
|
||||||
if (!memcmp(str, "TRE", 3))
|
if (!memcmp(str, "TRE", 3))
|
||||||
@ -52,8 +26,7 @@ static SubFile::Type tileType(const char str[3])
|
|||||||
return SubFile::Unknown;
|
return SubFile::Unknown;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMG::IMG(const QString &fileName)
|
IMG::IMG(const QString &fileName) : _file(fileName)
|
||||||
: _file(fileName), _typ(0), _style(0), _valid(false)
|
|
||||||
{
|
{
|
||||||
#define CHECK(condition) \
|
#define CHECK(condition) \
|
||||||
if (!(condition)) { \
|
if (!(condition)) { \
|
||||||
@ -191,86 +164,6 @@ IMG::IMG(const QString &fileName)
|
|||||||
_valid = true;
|
_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
IMG::~IMG()
|
|
||||||
{
|
|
||||||
TileTree::Iterator it;
|
|
||||||
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
|
|
||||||
delete _tileTree.GetAt(it);
|
|
||||||
|
|
||||||
delete _typ;
|
|
||||||
delete _style;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMG::load()
|
|
||||||
{
|
|
||||||
Q_ASSERT(!_style);
|
|
||||||
|
|
||||||
if (_typ)
|
|
||||||
_style = new Style(_typ);
|
|
||||||
else {
|
|
||||||
QFile typFile(ProgramPaths::typFile());
|
|
||||||
if (typFile.open(QIODevice::ReadOnly)) {
|
|
||||||
SubFile typ(&typFile);
|
|
||||||
_style = new Style(&typ);
|
|
||||||
} else
|
|
||||||
_style = new Style();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMG::clear()
|
|
||||||
{
|
|
||||||
TileTree::Iterator it;
|
|
||||||
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
|
|
||||||
_tileTree.GetAt(it)->clear();
|
|
||||||
|
|
||||||
delete _style;
|
|
||||||
_style = 0;
|
|
||||||
|
|
||||||
_polyCache.clear();
|
|
||||||
_pointCache.clear();
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool polyCb(VectorTile *tile, void *context)
|
|
||||||
{
|
|
||||||
PolyCTX *ctx = (PolyCTX*)context;
|
|
||||||
tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool pointCb(VectorTile *tile, void *context)
|
|
||||||
{
|
|
||||||
PointCTX *ctx = (PointCTX*)context;
|
|
||||||
tile->points(ctx->rect, ctx->bits, ctx->points, ctx->pointCache);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMG::polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
|
||||||
QList<Poly> *lines)
|
|
||||||
{
|
|
||||||
PolyCTX ctx(rect, bits, polygons, lines, &_polyCache);
|
|
||||||
double min[2], max[2];
|
|
||||||
|
|
||||||
min[0] = rect.left();
|
|
||||||
min[1] = rect.bottom();
|
|
||||||
max[0] = rect.right();
|
|
||||||
max[1] = rect.top();
|
|
||||||
|
|
||||||
_tileTree.Search(min, max, polyCb, &ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IMG::points(const RectC &rect, int bits, QList<Point> *points)
|
|
||||||
{
|
|
||||||
PointCTX ctx(rect, bits, points, &_pointCache);
|
|
||||||
double min[2], max[2];
|
|
||||||
|
|
||||||
min[0] = rect.left();
|
|
||||||
min[1] = rect.bottom();
|
|
||||||
max[0] = rect.right();
|
|
||||||
max[1] = rect.top();
|
|
||||||
|
|
||||||
_tileTree.Search(min, max, pointCb, &ctx);
|
|
||||||
}
|
|
||||||
|
|
||||||
qint64 IMG::read(char *data, qint64 maxSize)
|
qint64 IMG::read(char *data, qint64 maxSize)
|
||||||
{
|
{
|
||||||
qint64 ret = _file.read(data, maxSize);
|
qint64 ret = _file.read(data, maxSize);
|
||||||
@ -292,28 +185,12 @@ template<class T> bool IMG::readValue(T &val)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IMG::readBlock(int blockNum, QByteArray &data)
|
bool IMG::readBlock(int blockNum, char *data)
|
||||||
{
|
{
|
||||||
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
||||||
return false;
|
return false;
|
||||||
data.resize(_blockSize);
|
if (read(data, _blockSize) < _blockSize)
|
||||||
if (read(data.data(), _blockSize) < _blockSize)
|
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Point &point)
|
|
||||||
{
|
|
||||||
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
|
|
||||||
<< ", " << point.poi << ")";
|
|
||||||
return dbg.space();
|
|
||||||
}
|
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Poly &poly)
|
|
||||||
{
|
|
||||||
dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")";
|
|
||||||
return dbg.space();
|
|
||||||
}
|
|
||||||
#endif // QT_NO_DEBUG
|
|
||||||
|
@ -2,105 +2,26 @@
|
|||||||
#define IMG_H
|
#define IMG_H
|
||||||
|
|
||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QByteArray>
|
#include "mapdata.h"
|
||||||
#include <QCache>
|
|
||||||
#include <QDebug>
|
|
||||||
#include "common/rtree.h"
|
|
||||||
#include "common/rectc.h"
|
|
||||||
#include "style.h"
|
|
||||||
#include "label.h"
|
|
||||||
|
|
||||||
class VectorTile;
|
class IMG : public MapData
|
||||||
class SubFile;
|
|
||||||
class SubDiv;
|
|
||||||
|
|
||||||
class IMG
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct Poly {
|
|
||||||
/* QPointF insted of Coordinates for performance reasons (no need to
|
|
||||||
duplicate all the vectors for drawing). Note, that we do not want to
|
|
||||||
ll2xy() the points in the IMG class as this can not be done in
|
|
||||||
parallel. */
|
|
||||||
QVector<QPointF> points;
|
|
||||||
Label label;
|
|
||||||
quint32 type;
|
|
||||||
RectC boundingRect;
|
|
||||||
|
|
||||||
bool operator<(const Poly &other) const
|
|
||||||
{return type > other.type;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Point {
|
|
||||||
Point() : id(0) {}
|
|
||||||
|
|
||||||
Coordinates coordinates;
|
|
||||||
Label label;
|
|
||||||
quint32 type;
|
|
||||||
bool poi;
|
|
||||||
quint64 id;
|
|
||||||
|
|
||||||
bool operator<(const Point &other) const
|
|
||||||
{return id < other.id;}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct Polys {
|
|
||||||
Polys() {}
|
|
||||||
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
|
|
||||||
: polygons(polygons), lines(lines) {}
|
|
||||||
|
|
||||||
QList<Poly> polygons;
|
|
||||||
QList<Poly> lines;
|
|
||||||
};
|
|
||||||
|
|
||||||
IMG(const QString &fileName);
|
IMG(const QString &fileName);
|
||||||
~IMG();
|
|
||||||
|
|
||||||
void load();
|
|
||||||
void clear();
|
|
||||||
|
|
||||||
QString fileName() const {return _file.fileName();}
|
QString fileName() const {return _file.fileName();}
|
||||||
const QString &name() const {return _name;}
|
|
||||||
const RectC &bounds() const {return _bounds;}
|
|
||||||
|
|
||||||
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
|
||||||
QList<Poly> *lines);
|
|
||||||
void points(const RectC &rect, int bits, QList<Point> *points);
|
|
||||||
const Style *style() const {return _style;}
|
|
||||||
|
|
||||||
bool isValid() const {return _valid;}
|
|
||||||
const QString &errorString() const {return _errorString;}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class SubFile;
|
friend class SubFile;
|
||||||
|
|
||||||
typedef RTree<VectorTile*, double, 2> TileTree;
|
|
||||||
|
|
||||||
int blockSize() const {return _blockSize;}
|
int blockSize() const {return _blockSize;}
|
||||||
bool readBlock(int blockNum, QByteArray &data);
|
bool readBlock(int blockNum, char *data);
|
||||||
qint64 read(char *data, qint64 maxSize);
|
qint64 read(char *data, qint64 maxSize);
|
||||||
template<class T> bool readValue(T &val);
|
template<class T> bool readValue(T &val);
|
||||||
|
|
||||||
QFile _file;
|
QFile _file;
|
||||||
quint8 _key;
|
quint8 _key;
|
||||||
int _blockSize;
|
int _blockSize;
|
||||||
|
|
||||||
QString _name;
|
|
||||||
RectC _bounds;
|
|
||||||
TileTree _tileTree;
|
|
||||||
SubFile *_typ;
|
|
||||||
Style *_style;
|
|
||||||
|
|
||||||
QCache<const SubDiv*, Polys> _polyCache;
|
|
||||||
QCache<const SubDiv*, QList<Point> > _pointCache;
|
|
||||||
|
|
||||||
bool _valid;
|
|
||||||
QString _errorString;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Point &point);
|
|
||||||
QDebug operator<<(QDebug dbg, const IMG::Poly &poly);
|
|
||||||
#endif // QT_NO_DEBUG
|
|
||||||
|
|
||||||
#endif // IMG_H
|
#endif // IMG_H
|
||||||
|
@ -12,6 +12,9 @@ public:
|
|||||||
LBLFile(IMG *img)
|
LBLFile(IMG *img)
|
||||||
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
|
: SubFile(img), _codec(0), _offset(0), _size(0), _poiOffset(0),
|
||||||
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
||||||
|
LBLFile(const QString &path)
|
||||||
|
: SubFile(path), _codec(0), _offset(0), _size(0), _poiOffset(0),
|
||||||
|
_poiSize(0), _poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
||||||
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
|
LBLFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
|
||||||
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
|
_codec(0), _offset(0), _size(0), _poiOffset(0), _poiSize(0),
|
||||||
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
_poiMultiplier(0), _multiplier(0), _encoding(0) {}
|
||||||
|
108
src/map/IMG/mapdata.cpp
Normal file
108
src/map/IMG/mapdata.cpp
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#include "common/programpaths.h"
|
||||||
|
#include "vectortile.h"
|
||||||
|
#include "style.h"
|
||||||
|
#include "mapdata.h"
|
||||||
|
|
||||||
|
|
||||||
|
struct PolyCTX
|
||||||
|
{
|
||||||
|
PolyCTX(const RectC &rect, int bits, QList<MapData::Poly> *polygons,
|
||||||
|
QList<MapData::Poly> *lines, QCache<const SubDiv*,
|
||||||
|
MapData::Polys> *polyCache) : rect(rect), bits(bits), polygons(polygons),
|
||||||
|
lines(lines), polyCache(polyCache) {}
|
||||||
|
|
||||||
|
const RectC ▭
|
||||||
|
int bits;
|
||||||
|
QList<MapData::Poly> *polygons;
|
||||||
|
QList<MapData::Poly> *lines;
|
||||||
|
QCache<const SubDiv*, MapData::Polys> *polyCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PointCTX
|
||||||
|
{
|
||||||
|
PointCTX(const RectC &rect, int bits, QList<MapData::Point> *points,
|
||||||
|
QCache<const SubDiv*, QList<MapData::Point> > *pointCache)
|
||||||
|
: rect(rect), bits(bits), points(points), pointCache(pointCache) {}
|
||||||
|
|
||||||
|
const RectC ▭
|
||||||
|
int bits;
|
||||||
|
QList<MapData::Point> *points;
|
||||||
|
QCache<const SubDiv*, QList<MapData::Point> > *pointCache;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline bool polyCb(VectorTile *tile, void *context)
|
||||||
|
{
|
||||||
|
PolyCTX *ctx = (PolyCTX*)context;
|
||||||
|
tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool pointCb(VectorTile *tile, void *context)
|
||||||
|
{
|
||||||
|
PointCTX *ctx = (PointCTX*)context;
|
||||||
|
tile->points(ctx->rect, ctx->bits, ctx->points, ctx->pointCache);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
MapData::~MapData()
|
||||||
|
{
|
||||||
|
TileTree::Iterator it;
|
||||||
|
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
|
||||||
|
delete _tileTree.GetAt(it);
|
||||||
|
|
||||||
|
delete _typ;
|
||||||
|
delete _style;
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapData::polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||||
|
QList<Poly> *lines)
|
||||||
|
{
|
||||||
|
PolyCTX ctx(rect, bits, polygons, lines, &_polyCache);
|
||||||
|
double min[2], max[2];
|
||||||
|
|
||||||
|
min[0] = rect.left();
|
||||||
|
min[1] = rect.bottom();
|
||||||
|
max[0] = rect.right();
|
||||||
|
max[1] = rect.top();
|
||||||
|
|
||||||
|
_tileTree.Search(min, max, polyCb, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapData::points(const RectC &rect, int bits, QList<Point> *points)
|
||||||
|
{
|
||||||
|
PointCTX ctx(rect, bits, points, &_pointCache);
|
||||||
|
double min[2], max[2];
|
||||||
|
|
||||||
|
min[0] = rect.left();
|
||||||
|
min[1] = rect.bottom();
|
||||||
|
max[0] = rect.right();
|
||||||
|
max[1] = rect.top();
|
||||||
|
|
||||||
|
_tileTree.Search(min, max, pointCb, &ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapData::load()
|
||||||
|
{
|
||||||
|
Q_ASSERT(!_style);
|
||||||
|
|
||||||
|
if (_typ)
|
||||||
|
_style = new Style(_typ);
|
||||||
|
else {
|
||||||
|
SubFile typ(ProgramPaths::typFile());
|
||||||
|
_style = new Style(&typ);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void MapData::clear()
|
||||||
|
{
|
||||||
|
TileTree::Iterator it;
|
||||||
|
for (_tileTree.GetFirst(it); !_tileTree.IsNull(it); _tileTree.GetNext(it))
|
||||||
|
_tileTree.GetAt(it)->clear();
|
||||||
|
|
||||||
|
delete _style;
|
||||||
|
_style = 0;
|
||||||
|
|
||||||
|
_polyCache.clear();
|
||||||
|
_pointCache.clear();
|
||||||
|
}
|
105
src/map/IMG/mapdata.h
Normal file
105
src/map/IMG/mapdata.h
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
#ifndef MAPDATA_H
|
||||||
|
#define MAPDATA_H
|
||||||
|
|
||||||
|
#include <QList>
|
||||||
|
#include <QPointF>
|
||||||
|
#include <QCache>
|
||||||
|
#include <QDebug>
|
||||||
|
#include "common/rectc.h"
|
||||||
|
#include "common/rtree.h"
|
||||||
|
#include "label.h"
|
||||||
|
|
||||||
|
class Style;
|
||||||
|
class SubDiv;
|
||||||
|
class SubFile;
|
||||||
|
class VectorTile;
|
||||||
|
|
||||||
|
class MapData
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
struct Poly {
|
||||||
|
/* QPointF insted of Coordinates for performance reasons (no need to
|
||||||
|
duplicate all the vectors for drawing). Note, that we do not want to
|
||||||
|
ll2xy() the points in the IMG class as this can not be done in
|
||||||
|
parallel. */
|
||||||
|
QVector<QPointF> points;
|
||||||
|
Label label;
|
||||||
|
quint32 type;
|
||||||
|
RectC boundingRect;
|
||||||
|
|
||||||
|
bool operator<(const Poly &other) const
|
||||||
|
{return type > other.type;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Point {
|
||||||
|
Point() : id(0) {}
|
||||||
|
|
||||||
|
Coordinates coordinates;
|
||||||
|
Label label;
|
||||||
|
quint32 type;
|
||||||
|
bool poi;
|
||||||
|
quint64 id;
|
||||||
|
|
||||||
|
bool operator<(const Point &other) const
|
||||||
|
{return id < other.id;}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Polys {
|
||||||
|
Polys() {}
|
||||||
|
Polys(const QList<Poly> &polygons, const QList<Poly> &lines)
|
||||||
|
: polygons(polygons), lines(lines) {}
|
||||||
|
|
||||||
|
QList<Poly> polygons;
|
||||||
|
QList<Poly> lines;
|
||||||
|
};
|
||||||
|
|
||||||
|
MapData() : _typ(0), _style(0), _valid(false) {}
|
||||||
|
virtual ~MapData();
|
||||||
|
|
||||||
|
const QString &name() const {return _name;}
|
||||||
|
const RectC &bounds() const {return _bounds;}
|
||||||
|
const Style *style() const {return _style;}
|
||||||
|
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||||
|
QList<Poly> *lines);
|
||||||
|
void points(const RectC &rect, int bits, QList<Point> *points);
|
||||||
|
|
||||||
|
void load();
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
virtual QString fileName() const = 0;
|
||||||
|
|
||||||
|
bool isValid() const {return _valid;}
|
||||||
|
QString errorString() const {return _errorString;}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
typedef RTree<VectorTile*, double, 2> TileTree;
|
||||||
|
|
||||||
|
QString _name;
|
||||||
|
RectC _bounds;
|
||||||
|
SubFile *_typ;
|
||||||
|
Style *_style;
|
||||||
|
|
||||||
|
TileTree _tileTree;
|
||||||
|
QCache<const SubDiv*, Polys> _polyCache;
|
||||||
|
QCache<const SubDiv*, QList<Point> > _pointCache;
|
||||||
|
|
||||||
|
bool _valid;
|
||||||
|
QString _errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifndef QT_NO_DEBUG
|
||||||
|
inline QDebug operator<<(QDebug dbg, const MapData::Point &point)
|
||||||
|
{
|
||||||
|
dbg.nospace() << "Point(" << hex << point.type << ", " << point.label
|
||||||
|
<< ", " << point.poi << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline QDebug operator<<(QDebug dbg, const MapData::Poly &poly)
|
||||||
|
{
|
||||||
|
dbg.nospace() << "Poly(" << hex << poly.type << ", " << poly.label << ")";
|
||||||
|
return dbg.space();
|
||||||
|
}
|
||||||
|
#endif // QT_NO_DEBUG
|
||||||
|
|
||||||
|
#endif // MAPDATA_H
|
@ -6,9 +6,12 @@
|
|||||||
class NETFile : public SubFile
|
class NETFile : public SubFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
NETFile(IMG *img) : SubFile(img), _offset(0), _size(0), _multiplier(0) {}
|
NETFile(IMG *img)
|
||||||
NETFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset),
|
: SubFile(img), _offset(0), _size(0), _multiplier(0) {}
|
||||||
_offset(0), _size(0), _multiplier(0) {}
|
NETFile(const QString &path)
|
||||||
|
: SubFile(path), _offset(0), _size(0), _multiplier(0) {}
|
||||||
|
NETFile(SubFile *gmp, quint32 offset)
|
||||||
|
: SubFile(gmp, offset), _offset(0), _size(0), _multiplier(0) {}
|
||||||
|
|
||||||
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);
|
bool lblOffset(Handle &hdl, quint32 netOffset, quint32 &lblOffset);
|
||||||
|
|
||||||
|
@ -35,7 +35,7 @@ bool RGNFile::skipClassFields(Handle &hdl) const
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
return seek(hdl, hdl.pos + rs);
|
return seek(hdl, hdl.pos() + rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||||
@ -133,7 +133,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
|||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
quint16 len;
|
quint16 len;
|
||||||
|
|
||||||
while (hdl.pos < (int)segment.end()) {
|
while (hdl.pos() < (int)segment.end()) {
|
||||||
IMG::Poly poly;
|
IMG::Poly poly;
|
||||||
|
|
||||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||||
@ -206,7 +206,7 @@ bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
|||||||
if (!seek(hdl, segment.offset()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos < (int)segment.end()) {
|
while (hdl.pos() < (int)segment.end()) {
|
||||||
IMG::Poly poly;
|
IMG::Poly poly;
|
||||||
QPoint pos;
|
QPoint pos;
|
||||||
|
|
||||||
@ -305,7 +305,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
|||||||
if (!seek(hdl, segment.offset()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos < (int)segment.end()) {
|
while (hdl.pos() < (int)segment.end()) {
|
||||||
IMG::Point point;
|
IMG::Point point;
|
||||||
|
|
||||||
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
if (!(readUInt8(hdl, type) && readUInt24(hdl, labelPtr)
|
||||||
@ -327,7 +327,7 @@ bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
|||||||
point.poi = labelPtr & 0x400000;
|
point.poi = labelPtr & 0x400000;
|
||||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||||
point.id = ((quint64)point.type)<<40 | ((quint64)lbl->offset())<<24
|
point.id = ((quint64)point.type)<<40 | ((quint64)lbl->id())<<24
|
||||||
| (labelPtr & 0x3FFFFF);
|
| (labelPtr & 0x3FFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -351,7 +351,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
|||||||
if (!seek(hdl, segment.offset()))
|
if (!seek(hdl, segment.offset()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos < (int)segment.end()) {
|
while (hdl.pos() < (int)segment.end()) {
|
||||||
IMG::Point point;
|
IMG::Point point;
|
||||||
|
|
||||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||||
@ -382,7 +382,7 @@ bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
|||||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
||||||
point.id = ((quint64)point.type)<<40
|
point.id = ((quint64)point.type)<<40
|
||||||
| ((quint64)lbl->offset())<<24 | (labelPtr & 0x3FFFFF);
|
| ((quint64)lbl->id())<<24 | (labelPtr & 0x3FFFFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
points->append(point);
|
points->append(point);
|
||||||
|
@ -24,6 +24,10 @@ public:
|
|||||||
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
||||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||||
_pointsSize(0), _init(false) {clearFlags();}
|
_pointsSize(0), _init(false) {clearFlags();}
|
||||||
|
RGNFile(const QString &path)
|
||||||
|
: SubFile(path), _offset(0), _size(0), _polygonsOffset(0),
|
||||||
|
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||||
|
_pointsSize(0), _init(false) {clearFlags();}
|
||||||
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
|
RGNFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset), _offset(0),
|
||||||
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
_size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0),
|
||||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
||||||
|
@ -341,7 +341,7 @@ static bool skipLocalization(SubFile *file, SubFile::Handle &hdl)
|
|||||||
len = len >> 2;
|
len = len >> 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file->seek(hdl, hdl.pos + len))
|
if (!file->seek(hdl, hdl.pos() + len))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
@ -890,7 +890,7 @@ bool Style::parseDrawOrder(SubFile *file, SubFile::Handle &hdl,
|
|||||||
|
|
||||||
bool Style::parseTYPFile(SubFile *file)
|
bool Style::parseTYPFile(SubFile *file)
|
||||||
{
|
{
|
||||||
SubFile::Handle hdl;
|
SubFile::Handle hdl(file);
|
||||||
Section points, lines, polygons, order;
|
Section points, lines, polygons, order;
|
||||||
quint16 tmp16, codepage;
|
quint16 tmp16, codepage;
|
||||||
|
|
||||||
|
@ -5,22 +5,35 @@
|
|||||||
|
|
||||||
bool SubFile::seek(Handle &handle, quint32 pos) const
|
bool SubFile::seek(Handle &handle, quint32 pos) const
|
||||||
{
|
{
|
||||||
if (_file)
|
if (handle._file) {
|
||||||
return _file->seek(pos);
|
int blockNum = pos / BLOCK_SIZE;
|
||||||
else {
|
|
||||||
|
if (handle._blockNum != blockNum) {
|
||||||
|
if (!handle._file->seek((qint64)blockNum * BLOCK_SIZE))
|
||||||
|
return false;
|
||||||
|
if (handle._file->read(handle._data.data(), BLOCK_SIZE) < 0)
|
||||||
|
return false;
|
||||||
|
handle._blockNum = blockNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
handle._blockPos = pos % BLOCK_SIZE;
|
||||||
|
handle._pos = pos;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
quint32 blockSize = _img->blockSize();
|
quint32 blockSize = _img->blockSize();
|
||||||
int blockNum = pos / blockSize;
|
int blockNum = pos / blockSize;
|
||||||
|
|
||||||
if (handle.blockNum != blockNum) {
|
if (handle._blockNum != blockNum) {
|
||||||
if (blockNum >= _blocks->size())
|
if (blockNum >= _blocks->size())
|
||||||
return false;
|
return false;
|
||||||
if (!_img->readBlock(_blocks->at(blockNum), handle.data))
|
if (!_img->readBlock(_blocks->at(blockNum), handle._data.data()))
|
||||||
return false;
|
return false;
|
||||||
handle.blockNum = blockNum;
|
handle._blockNum = blockNum;
|
||||||
}
|
}
|
||||||
|
|
||||||
handle.blockPos = pos % blockSize;
|
handle._blockPos = pos % blockSize;
|
||||||
handle.pos = pos;
|
handle._pos = pos;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -28,14 +41,10 @@ bool SubFile::seek(Handle &handle, quint32 pos) const
|
|||||||
|
|
||||||
bool SubFile::readByte(Handle &handle, quint8 &val) const
|
bool SubFile::readByte(Handle &handle, quint8 &val) const
|
||||||
{
|
{
|
||||||
if (_file)
|
int blockSize = handle._file ? BLOCK_SIZE : _img->blockSize();
|
||||||
return _file->getChar((char*)&val);
|
val = handle._data.at(handle._blockPos++);
|
||||||
else {
|
handle._pos++;
|
||||||
val = handle.data.at(handle.blockPos++);
|
return (handle._blockPos >= blockSize) ? seek(handle, handle._pos) : true;
|
||||||
handle.pos++;
|
|
||||||
return (handle.blockPos >= _img->blockSize())
|
|
||||||
? seek(handle, handle.pos) : true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
|
bool SubFile::readVUInt32(Handle &hdl, quint32 &val) const
|
||||||
@ -77,7 +86,7 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!(bits & 1)) {
|
if (!(bits & 1)) {
|
||||||
seek(hdl, hdl.pos - 1);
|
seek(hdl, hdl._pos - 1);
|
||||||
if (!((bits>>1) & 1)) {
|
if (!((bits>>1) & 1)) {
|
||||||
if (!((bits>>2) & 1)) {
|
if (!((bits>>2) & 1)) {
|
||||||
if (!readUInt32(hdl, bitfield))
|
if (!readUInt32(hdl, bitfield))
|
||||||
@ -97,8 +106,3 @@ bool SubFile::readVBitfield32(Handle &hdl, quint32 &bitfield) const
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString SubFile::fileName() const
|
|
||||||
{
|
|
||||||
return _file ? _file->fileName() : _img->fileName();
|
|
||||||
}
|
|
||||||
|
@ -3,38 +3,64 @@
|
|||||||
|
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
#include <QDebug>
|
#include <QDebug>
|
||||||
|
#include <QFile>
|
||||||
|
#include "img.h"
|
||||||
|
|
||||||
class QFile;
|
|
||||||
class IMG;
|
#define BLOCK_SIZE 8192
|
||||||
|
|
||||||
class SubFile
|
class SubFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP};
|
enum Type {Unknown, TRE, RGN, LBL, NET, TYP, GMP};
|
||||||
|
|
||||||
struct Handle
|
class Handle
|
||||||
{
|
{
|
||||||
Handle() : blockNum(-1), blockPos(-1), pos(-1) {}
|
public:
|
||||||
|
Handle(const SubFile *subFile)
|
||||||
|
: _file(0), _blockNum(-1), _blockPos(-1), _pos(-1)
|
||||||
|
{
|
||||||
|
if (subFile && subFile->_path) {
|
||||||
|
_file = new QFile(*(subFile->_path));
|
||||||
|
_file->open(QIODevice::ReadOnly);
|
||||||
|
_data.resize(BLOCK_SIZE);
|
||||||
|
} else if (subFile)
|
||||||
|
_data.resize(subFile->_img->blockSize());
|
||||||
|
_blockNum = -1;
|
||||||
|
_blockPos = -1;
|
||||||
|
_pos = -1;
|
||||||
|
}
|
||||||
|
~Handle() {delete _file;}
|
||||||
|
|
||||||
QByteArray data;
|
int pos() const {return _pos;}
|
||||||
int blockNum;
|
|
||||||
int blockPos;
|
private:
|
||||||
int pos;
|
friend class SubFile;
|
||||||
|
|
||||||
|
QFile *_file;
|
||||||
|
QByteArray _data;
|
||||||
|
int _blockNum;
|
||||||
|
int _blockPos;
|
||||||
|
int _pos;
|
||||||
};
|
};
|
||||||
|
|
||||||
SubFile(IMG *img)
|
SubFile(IMG *img)
|
||||||
: _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _file(0) {}
|
: _gmpOffset(0), _img(img), _blocks(new QVector<quint16>()), _path(0),
|
||||||
|
_id(0) {}
|
||||||
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
|
SubFile(SubFile *gmp, quint32 offset) : _gmpOffset(offset), _img(gmp->_img),
|
||||||
_blocks(gmp->_blocks), _file(gmp->_file) {}
|
_blocks(gmp->_blocks), _path(gmp->_path), _id(gmp->id()) {}
|
||||||
SubFile(QFile *file)
|
SubFile(const QString &path)
|
||||||
: _gmpOffset(0), _img(0), _blocks(0), _file(file) {}
|
: _gmpOffset(0), _img(0), _blocks(0), _path(new QString(path)), _id(0) {}
|
||||||
~SubFile()
|
~SubFile()
|
||||||
{
|
{
|
||||||
if (!_gmpOffset)
|
if (!_gmpOffset) {
|
||||||
delete _blocks;
|
delete _blocks;
|
||||||
|
delete _path;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void addBlock(quint16 block) {_blocks->append(block);}
|
void addBlock(quint16 block) {_blocks->append(block);}
|
||||||
|
void setId(quint16 id) {_id = id;}
|
||||||
|
|
||||||
bool seek(Handle &handle, quint32 pos) const;
|
bool seek(Handle &handle, quint32 pos) const;
|
||||||
|
|
||||||
@ -114,8 +140,8 @@ public:
|
|||||||
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
bool readVUInt32(Handle &hdl, quint32 &val) const;
|
||||||
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
bool readVBitfield32(Handle &hdl, quint32 &bitfield) const;
|
||||||
|
|
||||||
quint16 offset() const {return _blocks->first();}
|
quint16 id() const {return _blocks ? _blocks->first() : _id;}
|
||||||
QString fileName() const;
|
QString fileName() const {return _path ? *_path : _img->fileName();}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
quint32 _gmpOffset;
|
quint32 _gmpOffset;
|
||||||
@ -125,7 +151,8 @@ private:
|
|||||||
|
|
||||||
IMG *_img;
|
IMG *_img;
|
||||||
QVector<quint16> *_blocks;
|
QVector<quint16> *_blocks;
|
||||||
QFile *_file;
|
QString *_path;
|
||||||
|
quint16 _id;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // SUBFILE_H
|
#endif // SUBFILE_H
|
||||||
|
@ -39,7 +39,7 @@ TREFile::~TREFile()
|
|||||||
|
|
||||||
bool TREFile::init()
|
bool TREFile::init()
|
||||||
{
|
{
|
||||||
Handle hdl;
|
Handle hdl(this);
|
||||||
quint8 locked;
|
quint8 locked;
|
||||||
quint16 hdrLen;
|
quint16 hdrLen;
|
||||||
|
|
||||||
@ -113,7 +113,7 @@ bool TREFile::init()
|
|||||||
|
|
||||||
bool TREFile::load(int idx)
|
bool TREFile::load(int idx)
|
||||||
{
|
{
|
||||||
Handle hdl;
|
Handle hdl(this);
|
||||||
QList<SubDiv*> sl;
|
QList<SubDiv*> sl;
|
||||||
SubDiv *s = 0;
|
SubDiv *s = 0;
|
||||||
SubDivTree *tree = new SubDivTree();
|
SubDivTree *tree = new SubDivTree();
|
||||||
@ -199,7 +199,7 @@ bool TREFile::load(int idx)
|
|||||||
if (i)
|
if (i)
|
||||||
sl.at(i-1)->setExtEnds(polygons, lines, points);
|
sl.at(i-1)->setExtEnds(polygons, lines, points);
|
||||||
|
|
||||||
if (!seek(hdl, hdl.pos + _extended.itemSize - 12))
|
if (!seek(hdl, hdl.pos() + _extended.itemSize - 12))
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -14,6 +14,7 @@ class TREFile : public SubFile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TREFile(IMG *img) : SubFile(img) {}
|
TREFile(IMG *img) : SubFile(img) {}
|
||||||
|
TREFile(const QString &path) : SubFile(path) {}
|
||||||
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
|
TREFile(SubFile *gmp, quint32 offset) : SubFile(gmp, offset) {}
|
||||||
~TREFile();
|
~TREFile();
|
||||||
|
|
||||||
|
@ -59,6 +59,29 @@ SubFile *VectorTile::addFile(IMG *img, SubFile::Type type)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SubFile *VectorTile::addFile(const QString &path, SubFile::Type type)
|
||||||
|
{
|
||||||
|
switch (type) {
|
||||||
|
case SubFile::TRE:
|
||||||
|
_tre = new TREFile(path);
|
||||||
|
return _tre;
|
||||||
|
case SubFile::RGN:
|
||||||
|
_rgn = new RGNFile(path);
|
||||||
|
return _rgn;
|
||||||
|
case SubFile::LBL:
|
||||||
|
_lbl = new LBLFile(path);
|
||||||
|
return _lbl;
|
||||||
|
case SubFile::NET:
|
||||||
|
_net = new NETFile(path);
|
||||||
|
return _net;
|
||||||
|
case SubFile::GMP:
|
||||||
|
_gmp = new SubFile(path);
|
||||||
|
return _gmp;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool VectorTile::init()
|
bool VectorTile::init()
|
||||||
{
|
{
|
||||||
if (_gmp && !initGMP())
|
if (_gmp && !initGMP())
|
||||||
@ -72,7 +95,7 @@ bool VectorTile::init()
|
|||||||
|
|
||||||
bool VectorTile::initGMP()
|
bool VectorTile::initGMP()
|
||||||
{
|
{
|
||||||
SubFile::Handle hdl;
|
SubFile::Handle hdl(_gmp);
|
||||||
quint32 tre, rgn, lbl, net;
|
quint32 tre, rgn, lbl, net;
|
||||||
|
|
||||||
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
|
if (!(_gmp->seek(hdl, 0x19) && _gmp->readUInt32(hdl, tre)
|
||||||
@ -92,7 +115,7 @@ void VectorTile::polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
|||||||
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
|
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
|
||||||
const
|
const
|
||||||
{
|
{
|
||||||
SubFile::Handle rgnHdl, lblHdl, netHdl;
|
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl), netHdl(_net);
|
||||||
|
|
||||||
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
||||||
return;
|
return;
|
||||||
@ -131,7 +154,7 @@ void VectorTile::polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
|||||||
void VectorTile::points(const RectC &rect, int bits, QList<IMG::Point> *points,
|
void VectorTile::points(const RectC &rect, int bits, QList<IMG::Point> *points,
|
||||||
QCache<const SubDiv *, QList<IMG::Point> > *pointCache) const
|
QCache<const SubDiv *, QList<IMG::Point> > *pointCache) const
|
||||||
{
|
{
|
||||||
SubFile::Handle rgnHdl, lblHdl;
|
SubFile::Handle rgnHdl(_rgn), lblHdl(_lbl);
|
||||||
|
|
||||||
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
||||||
return;
|
return;
|
||||||
|
@ -23,6 +23,7 @@ public:
|
|||||||
|
|
||||||
SubFile *file(SubFile::Type type);
|
SubFile *file(SubFile::Type type);
|
||||||
SubFile *addFile(IMG *img, SubFile::Type type);
|
SubFile *addFile(IMG *img, SubFile::Type type);
|
||||||
|
SubFile *addFile(const QString &path, SubFile::Type type);
|
||||||
|
|
||||||
void polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
void polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
||||||
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
|
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
|
||||||
@ -37,8 +38,6 @@ public:
|
|||||||
|| type == SubFile::GMP);
|
|| type == SubFile::GMP);
|
||||||
}
|
}
|
||||||
|
|
||||||
friend QDebug operator<<(QDebug dbg, const VectorTile &tile);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool initGMP();
|
bool initGMP();
|
||||||
|
|
||||||
|
@ -13,6 +13,9 @@
|
|||||||
#include "IMG/textpathitem.h"
|
#include "IMG/textpathitem.h"
|
||||||
#include "IMG/textpointitem.h"
|
#include "IMG/textpointitem.h"
|
||||||
#include "IMG/bitmapline.h"
|
#include "IMG/bitmapline.h"
|
||||||
|
#include "IMG/style.h"
|
||||||
|
#include "IMG/img.h"
|
||||||
|
#include "IMG/gmap.h"
|
||||||
#include "pcs.h"
|
#include "pcs.h"
|
||||||
#include "rectd.h"
|
#include "rectd.h"
|
||||||
#include "imgmap.h"
|
#include "imgmap.h"
|
||||||
@ -35,9 +38,9 @@ public:
|
|||||||
const QString &key() const {return _key;}
|
const QString &key() const {return _key;}
|
||||||
const QPoint &xy() const {return _xy;}
|
const QPoint &xy() const {return _xy;}
|
||||||
QImage &img() {return _img;}
|
QImage &img() {return _img;}
|
||||||
QList<IMG::Poly> &polygons() {return _polygons;}
|
QList<MapData::Poly> &polygons() {return _polygons;}
|
||||||
QList<IMG::Poly> &lines() {return _lines;}
|
QList<MapData::Poly> &lines() {return _lines;}
|
||||||
QList<IMG::Point> &points() {return _points;}
|
QList<MapData::Point> &points() {return _points;}
|
||||||
|
|
||||||
void render()
|
void render()
|
||||||
{
|
{
|
||||||
@ -70,9 +73,9 @@ private:
|
|||||||
QPoint _xy;
|
QPoint _xy;
|
||||||
QString _key;
|
QString _key;
|
||||||
QImage _img;
|
QImage _img;
|
||||||
QList<IMG::Poly> _polygons;
|
QList<MapData::Poly> _polygons;
|
||||||
QList<IMG::Poly> _lines;
|
QList<MapData::Poly> _lines;
|
||||||
QList<IMG::Point> _points;
|
QList<MapData::Point> _points;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -226,11 +229,17 @@ static bool rectNearPolygon(const QPolygonF &polygon, const QRectF &rect)
|
|||||||
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
|
|| polygon.containsPoint(rect.bottomRight(), Qt::OddEvenFill)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
||||||
: Map(parent), _img(fileName), _projection(PCS::pcs(3857)), _valid(false)
|
: Map(parent), _projection(PCS::pcs(3857)), _valid(false)
|
||||||
{
|
{
|
||||||
if (!_img.isValid()) {
|
if (GMAP::isGMAP(fileName))
|
||||||
_errorString = _img.errorString();
|
_data = new GMAP(fileName);
|
||||||
|
else
|
||||||
|
_data = new IMG(fileName);
|
||||||
|
|
||||||
|
if (!_data->isValid()) {
|
||||||
|
_errorString = _data->errorString();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -242,17 +251,17 @@ IMGMap::IMGMap(const QString &fileName, QObject *parent)
|
|||||||
|
|
||||||
void IMGMap::load()
|
void IMGMap::load()
|
||||||
{
|
{
|
||||||
_img.load();
|
_data->load();
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::unload()
|
void IMGMap::unload()
|
||||||
{
|
{
|
||||||
_img.clear();
|
_data->clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
QRectF IMGMap::bounds()
|
QRectF IMGMap::bounds()
|
||||||
{
|
{
|
||||||
RectD prect(_img.bounds(), _projection);
|
RectD prect(_data->bounds(), _projection);
|
||||||
return QRectF(_transform.proj2img(prect.topLeft()),
|
return QRectF(_transform.proj2img(prect.topLeft()),
|
||||||
_transform.proj2img(prect.bottomRight()));
|
_transform.proj2img(prect.bottomRight()));
|
||||||
}
|
}
|
||||||
@ -302,7 +311,7 @@ Transform IMGMap::transform(int zoom) const
|
|||||||
{
|
{
|
||||||
double scale = _projection.isGeographic()
|
double scale = _projection.isGeographic()
|
||||||
? 360.0 / (1<<zoom) : (2.0 * M_PI * WGS84_RADIUS) / (1<<zoom);
|
? 360.0 / (1<<zoom) : (2.0 * M_PI * WGS84_RADIUS) / (1<<zoom);
|
||||||
PointD topLeft(_projection.ll2xy(_img.bounds().topLeft()));
|
PointD topLeft(_projection.ll2xy(_data->bounds().topLeft()));
|
||||||
return Transform(ReferencePoint(PointD(0, 0), topLeft),
|
return Transform(ReferencePoint(PointD(0, 0), topLeft),
|
||||||
PointD(scale, scale));
|
PointD(scale, scale));
|
||||||
}
|
}
|
||||||
@ -322,14 +331,14 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
|
|||||||
return _projection.xy2ll(_transform.img2proj(p));
|
return _projection.xy2ll(_transform.img2proj(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
|
void IMGMap::drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < _img.style()->drawOrder().size(); n++) {
|
for (int n = 0; n < _data->style()->drawOrder().size(); n++) {
|
||||||
for (int i = 0; i < polygons.size(); i++) {
|
for (int i = 0; i < polygons.size(); i++) {
|
||||||
const IMG::Poly &poly = polygons.at(i);
|
const MapData::Poly &poly = polygons.at(i);
|
||||||
if (poly.type != _img.style()->drawOrder().at(n))
|
if (poly.type != _data->style()->drawOrder().at(n))
|
||||||
continue;
|
continue;
|
||||||
const Style::Polygon &style = _img.style()->polygon(poly.type);
|
const Style::Polygon &style = _data->style()->polygon(poly.type);
|
||||||
|
|
||||||
painter->setPen(style.pen());
|
painter->setPen(style.pen());
|
||||||
painter->setBrush(style.brush());
|
painter->setBrush(style.brush());
|
||||||
@ -338,13 +347,13 @@ void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
|
void IMGMap::drawLines(QPainter *painter, const QList<MapData::Poly> &lines)
|
||||||
{
|
{
|
||||||
painter->setBrush(Qt::NoBrush);
|
painter->setBrush(Qt::NoBrush);
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
const IMG::Poly &poly = lines.at(i);
|
const MapData::Poly &poly = lines.at(i);
|
||||||
const Style::Line &style = _img.style()->line(poly.type);
|
const Style::Line &style = _data->style()->line(poly.type);
|
||||||
|
|
||||||
if (style.background() == Qt::NoPen)
|
if (style.background() == Qt::NoPen)
|
||||||
continue;
|
continue;
|
||||||
@ -354,8 +363,8 @@ void IMGMap::drawLines(QPainter *painter, const QList<IMG::Poly> &lines)
|
|||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
const IMG::Poly &poly = lines.at(i);
|
const MapData::Poly &poly = lines.at(i);
|
||||||
const Style::Line &style = _img.style()->line(poly.type);
|
const Style::Line &style = _data->style()->line(poly.type);
|
||||||
|
|
||||||
if (!style.img().isNull())
|
if (!style.img().isNull())
|
||||||
BitmapLine::draw(painter, poly.points, style.img());
|
BitmapLine::draw(painter, poly.points, style.img());
|
||||||
@ -372,12 +381,11 @@ void IMGMap::drawTextItems(QPainter *painter, const QList<TextItem*> &textItems)
|
|||||||
textItems.at(i)->paint(painter);
|
textItems.at(i)->paint(painter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IMGMap::processPolygons(QList<MapData::Poly> &polygons,
|
||||||
void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
|
|
||||||
QList<TextItem*> &textItems)
|
QList<TextItem*> &textItems)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < polygons.size(); i++) {
|
for (int i = 0; i < polygons.size(); i++) {
|
||||||
IMG::Poly &poly = polygons[i];
|
MapData::Poly &poly = polygons[i];
|
||||||
for (int j = 0; j < poly.points.size(); j++) {
|
for (int j = 0; j < poly.points.size(); j++) {
|
||||||
QPointF &p = poly.points[j];
|
QPointF &p = poly.points[j];
|
||||||
p = ll2xy(Coordinates(p.x(), p.y()));
|
p = ll2xy(Coordinates(p.x(), p.y()));
|
||||||
@ -389,7 +397,7 @@ void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
|
|||||||
if (_zoom <= 23 && (Style::isWaterArea(poly.type)
|
if (_zoom <= 23 && (Style::isWaterArea(poly.type)
|
||||||
|| Style::isMilitaryArea(poly.type)
|
|| Style::isMilitaryArea(poly.type)
|
||||||
|| Style::isNatureReserve(poly.type))) {
|
|| Style::isNatureReserve(poly.type))) {
|
||||||
const Style::Polygon &style = _img.style()->polygon(poly.type);
|
const Style::Polygon &style = _data->style()->polygon(poly.type);
|
||||||
TextPointItem *item = new TextPointItem(
|
TextPointItem *item = new TextPointItem(
|
||||||
centroid(poly.points).toPoint(), &poly.label.text(),
|
centroid(poly.points).toPoint(), &poly.label.text(),
|
||||||
poiFont(), 0, &style.brush().color());
|
poiFont(), 0, &style.brush().color());
|
||||||
@ -402,13 +410,13 @@ void IMGMap::processPolygons(QList<IMG::Poly> &polygons,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void IMGMap::processLines(QList<MapData::Poly> &lines, const QRect &tileRect,
|
||||||
QList<TextItem*> &textItems)
|
QList<TextItem*> &textItems)
|
||||||
{
|
{
|
||||||
qStableSort(lines);
|
qStableSort(lines);
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
IMG::Poly &poly = lines[i];
|
MapData::Poly &poly = lines[i];
|
||||||
for (int j = 0; j < poly.points.size(); j++) {
|
for (int j = 0; j < poly.points.size(); j++) {
|
||||||
QPointF &p = poly.points[j];
|
QPointF &p = poly.points[j];
|
||||||
p = ll2xy(Coordinates(p.x(), p.y()));
|
p = ll2xy(Coordinates(p.x(), p.y()));
|
||||||
@ -420,12 +428,12 @@ void IMGMap::processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
|
|||||||
processShields(lines, tileRect, textItems);
|
processShields(lines, tileRect, textItems);
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void IMGMap::processStreetNames(QList<MapData::Poly> &lines,
|
||||||
QList<TextItem*> &textItems)
|
const QRect &tileRect, QList<TextItem*> &textItems)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
IMG::Poly &poly = lines[i];
|
MapData::Poly &poly = lines[i];
|
||||||
const Style::Line &style = _img.style()->line(poly.type);
|
const Style::Line &style = _data->style()->line(poly.type);
|
||||||
|
|
||||||
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
if (style.img().isNull() && style.foreground() == Qt::NoPen)
|
||||||
continue;
|
continue;
|
||||||
@ -449,7 +457,7 @@ void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void IMGMap::processShields(QList<MapData::Poly> &lines, const QRect &tileRect,
|
||||||
QList<TextItem*> &textItems)
|
QList<TextItem*> &textItems)
|
||||||
{
|
{
|
||||||
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
|
for (int type = FIRST_SHIELD; type <= LAST_SHIELD; type++) {
|
||||||
@ -460,7 +468,7 @@ void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
|
|||||||
QHash<Label::Shield, const Label::Shield*> sp;
|
QHash<Label::Shield, const Label::Shield*> sp;
|
||||||
|
|
||||||
for (int i = 0; i < lines.size(); i++) {
|
for (int i = 0; i < lines.size(); i++) {
|
||||||
const IMG::Poly &poly = lines.at(i);
|
const MapData::Poly &poly = lines.at(i);
|
||||||
const Label::Shield &shield = poly.label.shield();
|
const Label::Shield &shield = poly.label.shield();
|
||||||
if (!shield.isValid() || shield.type() != type
|
if (!shield.isValid() || shield.type() != type
|
||||||
|| !Style::isMajorRoad(poly.type))
|
|| !Style::isMajorRoad(poly.type))
|
||||||
@ -513,14 +521,14 @@ void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMGMap::processPoints(QList<IMG::Point> &points,
|
void IMGMap::processPoints(QList<MapData::Point> &points,
|
||||||
QList<TextItem*> &textItems)
|
QList<TextItem*> &textItems)
|
||||||
{
|
{
|
||||||
qSort(points);
|
qSort(points);
|
||||||
|
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
IMG::Point &point = points[i];
|
MapData::Point &point = points[i];
|
||||||
const Style::Point &style = _img.style()->point(point.type);
|
const Style::Point &style = _data->style()->point(point.type);
|
||||||
|
|
||||||
if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
|
if (point.poi && _zoom < minPOIZoom(Style::poiClass(point.type)))
|
||||||
continue;
|
continue;
|
||||||
@ -574,7 +582,7 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
for (int j = 0; j < height; j++) {
|
for (int j = 0; j < height; j++) {
|
||||||
QPixmap pm;
|
QPixmap pm;
|
||||||
QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE);
|
QPoint ttl(tl.x() + i * TILE_SIZE, tl.y() + j * TILE_SIZE);
|
||||||
QString key = _img.fileName() + "-" + QString::number(_zoom) + "_"
|
QString key = _data->fileName() + "-" + QString::number(_zoom) + "_"
|
||||||
+ QString::number(ttl.x()) + "_" + QString::number(ttl.y());
|
+ QString::number(ttl.x()) + "_" + QString::number(ttl.y());
|
||||||
if (QPixmapCache::find(key, pm))
|
if (QPixmapCache::find(key, pm))
|
||||||
painter->drawPixmap(ttl, pm);
|
painter->drawPixmap(ttl, pm);
|
||||||
@ -584,13 +592,13 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
|
|
||||||
RectD polyRect(_transform.img2proj(ttl), _transform.img2proj(
|
RectD polyRect(_transform.img2proj(ttl), _transform.img2proj(
|
||||||
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
|
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
|
||||||
_img.polys(polyRect.toRectC(_projection, 4), _zoom,
|
_data->polys(polyRect.toRectC(_projection, 4), _zoom,
|
||||||
&(tile.polygons()), &(tile.lines()));
|
&(tile.polygons()), &(tile.lines()));
|
||||||
|
|
||||||
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
|
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
|
||||||
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
|
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
|
||||||
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
|
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
|
||||||
_img.points(pointRect.toRectC(_projection, 4), _zoom,
|
_data->points(pointRect.toRectC(_projection, 4), _zoom,
|
||||||
&(tile.points()));
|
&(tile.points()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,7 +4,7 @@
|
|||||||
#include "map.h"
|
#include "map.h"
|
||||||
#include "projection.h"
|
#include "projection.h"
|
||||||
#include "transform.h"
|
#include "transform.h"
|
||||||
#include "IMG/img.h"
|
#include "IMG/mapdata.h"
|
||||||
|
|
||||||
class TextItem;
|
class TextItem;
|
||||||
|
|
||||||
@ -14,8 +14,9 @@ class IMGMap : public Map
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
IMGMap(const QString &fileName, QObject *parent = 0);
|
IMGMap(const QString &fileName, QObject *parent = 0);
|
||||||
|
~IMGMap() {delete _data;}
|
||||||
|
|
||||||
QString name() const {return _img.name();}
|
QString name() const {return _data->name();}
|
||||||
|
|
||||||
QRectF bounds();
|
QRectF bounds();
|
||||||
|
|
||||||
@ -43,21 +44,21 @@ private:
|
|||||||
|
|
||||||
Transform transform(int zoom) const;
|
Transform transform(int zoom) const;
|
||||||
void updateTransform();
|
void updateTransform();
|
||||||
void drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons);
|
void drawPolygons(QPainter *painter, const QList<MapData::Poly> &polygons);
|
||||||
void drawLines(QPainter *painter, const QList<IMG::Poly> &lines);
|
void drawLines(QPainter *painter, const QList<MapData::Poly> &lines);
|
||||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||||
|
|
||||||
void processPolygons(QList<IMG::Poly> &polygons,
|
void processPolygons(QList<MapData::Poly> &polygons,
|
||||||
QList<TextItem *> &textItems);
|
QList<TextItem *> &textItems);
|
||||||
void processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void processLines(QList<MapData::Poly> &lines, const QRect &tileRect,
|
||||||
QList<TextItem*> &textItems);
|
QList<TextItem*> &textItems);
|
||||||
void processPoints(QList<IMG::Point> &points, QList<TextItem*> &textItems);
|
void processPoints(QList<MapData::Point> &points, QList<TextItem*> &textItems);
|
||||||
void processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void processShields(QList<MapData::Poly> &lines, const QRect &tileRect,
|
||||||
QList<TextItem*> &textItems);
|
QList<TextItem*> &textItems);
|
||||||
void processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
|
void processStreetNames(QList<MapData::Poly> &lines, const QRect &tileRect,
|
||||||
QList<TextItem*> &textItems);
|
QList<TextItem*> &textItems);
|
||||||
|
|
||||||
IMG _img;
|
MapData *_data;
|
||||||
int _zoom;
|
int _zoom;
|
||||||
Projection _projection;
|
Projection _projection;
|
||||||
Transform _transform;
|
Transform _transform;
|
||||||
|
@ -8,20 +8,27 @@
|
|||||||
#include "mbtilesmap.h"
|
#include "mbtilesmap.h"
|
||||||
#include "rmap.h"
|
#include "rmap.h"
|
||||||
#include "imgmap.h"
|
#include "imgmap.h"
|
||||||
|
#include "IMG/gmap.h"
|
||||||
#include "maplist.h"
|
#include "maplist.h"
|
||||||
|
|
||||||
|
|
||||||
bool MapList::loadMap(Map* map, const QString &path, bool dir)
|
bool MapList::loadMap(Map *map, const QString &path, bool dir)
|
||||||
{
|
{
|
||||||
if (map->isValid()) {
|
if (map && map->isValid()) {
|
||||||
_maps.append(map);
|
_maps.append(map);
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else if (map) {
|
||||||
if (dir)
|
if (dir)
|
||||||
_errorString += path + ": " + map->errorString() + "\n";
|
_errorString += path + ": " + map->errorString() + "\n";
|
||||||
else
|
else
|
||||||
_errorString = map->errorString();
|
_errorString = map->errorString();
|
||||||
return false;
|
return false;
|
||||||
|
} else {
|
||||||
|
if (dir)
|
||||||
|
_errorString += path + ": " + "Unknown map format\n";
|
||||||
|
else
|
||||||
|
_errorString = "Unknown map format";
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -41,18 +48,22 @@ Map *MapList::loadSource(const QString &path, bool dir)
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapList::loadFile(const QString &path, bool *atlas, bool dir)
|
bool MapList::loadFile(const QString &path, bool *terminate, bool dir)
|
||||||
{
|
{
|
||||||
QFileInfo fi(path);
|
QFileInfo fi(path);
|
||||||
QString suffix = fi.suffix().toLower();
|
QString suffix = fi.suffix().toLower();
|
||||||
Map *map;
|
Map *map = 0;
|
||||||
|
|
||||||
if (Atlas::isAtlas(path)) {
|
if (Atlas::isAtlas(path)) {
|
||||||
*atlas = true;
|
*terminate = true;
|
||||||
map = new Atlas(path, this);
|
map = new Atlas(path, this);
|
||||||
} else if (suffix == "xml") {
|
} else if (suffix == "xml") {
|
||||||
if (!(map = loadSource(path, dir)))
|
if (MapSource::isMap(path) && !(map = loadSource(path, dir)))
|
||||||
return false;
|
return false;
|
||||||
|
else if (GMAP::isGMAP(path)) {
|
||||||
|
*terminate = true;
|
||||||
|
map = new IMGMap(path);
|
||||||
|
}
|
||||||
} else if (suffix == "jnx")
|
} else if (suffix == "jnx")
|
||||||
map = new JNXMap(path, this);
|
map = new JNXMap(path, this);
|
||||||
else if (suffix == "tif" || suffix == "tiff")
|
else if (suffix == "tif" || suffix == "tiff")
|
||||||
@ -85,15 +96,15 @@ bool MapList::loadDirR(const QString &path)
|
|||||||
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;
|
bool terminate = false;
|
||||||
|
|
||||||
if (fi.isDir() && fi.fileName() != "set") {
|
if (fi.isDir() && fi.fileName() != "set") {
|
||||||
if (!loadDirR(fi.absoluteFilePath()))
|
if (!loadDirR(fi.absoluteFilePath()))
|
||||||
ret = false;
|
ret = false;
|
||||||
} else if (filter().contains("*." + suffix)) {
|
} else if (filter().contains("*." + suffix)) {
|
||||||
if (!loadFile(fi.absoluteFilePath(), &atlas, true))
|
if (!loadFile(fi.absoluteFilePath(), &terminate, true))
|
||||||
ret = false;
|
ret = false;
|
||||||
if (atlas)
|
if (terminate)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -120,7 +131,7 @@ QString MapList::formats()
|
|||||||
return
|
return
|
||||||
tr("Supported files")
|
tr("Supported files")
|
||||||
+ " (*.img *.jnx *.map *.mbtiles *.rmap *.rtmap *.tar *.tba *.tif *.tiff *.xml);;"
|
+ " (*.img *.jnx *.map *.mbtiles *.rmap *.rtmap *.tar *.tba *.tif *.tiff *.xml);;"
|
||||||
+ tr("Garmin IMG maps") + " (*.img);;"
|
+ tr("Garmin IMG maps") + " (*.img *.xml);;"
|
||||||
+ tr("Garmin JNX maps") + " (*.jnx);;"
|
+ tr("Garmin JNX maps") + " (*.jnx);;"
|
||||||
+ tr("OziExplorer maps") + " (*.map);;"
|
+ tr("OziExplorer maps") + " (*.map);;"
|
||||||
+ tr("MBTiles maps") + " (*.mbtiles);;"
|
+ tr("MBTiles maps") + " (*.mbtiles);;"
|
||||||
|
@ -23,7 +23,7 @@ public:
|
|||||||
static QStringList filter();
|
static QStringList filter();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool loadFile(const QString &path, bool *atlas, bool dir);
|
bool loadFile(const QString &path, bool *terminate, bool dir);
|
||||||
bool loadDirR(const QString &path);
|
bool loadDirR(const QString &path);
|
||||||
Map *loadSource(const QString &path, bool dir);
|
Map *loadSource(const QString &path, bool dir);
|
||||||
bool loadMap(Map *map, const QString &path, bool dir);
|
bool loadMap(Map *map, const QString &path, bool dir);
|
||||||
|
@ -222,6 +222,20 @@ void MapSource::map(QXmlStreamReader &reader, Config &config)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool MapSource::isMap(const QString &path)
|
||||||
|
{
|
||||||
|
QFile file(path);
|
||||||
|
|
||||||
|
if (!file.open(QFile::ReadOnly | QFile::Text))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
QXmlStreamReader reader(&file);
|
||||||
|
if (reader.readNextStartElement() && reader.name() == "map")
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Map *MapSource::loadMap(const QString &path, QString &errorString)
|
Map *MapSource::loadMap(const QString &path, QString &errorString)
|
||||||
{
|
{
|
||||||
Config config;
|
Config config;
|
||||||
|
@ -15,6 +15,7 @@ class MapSource
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
static Map *loadMap(const QString &path, QString &errorString);
|
static Map *loadMap(const QString &path, QString &errorString);
|
||||||
|
static bool isMap(const QString &path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum Type {
|
enum Type {
|
||||||
|
Loading…
Reference in New Issue
Block a user