mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-01-19 04:02:09 +01:00
Use integers as tag keys in Mapsforge maps
This commit is contained in:
parent
dacaeca71a
commit
ce4f0472c0
@ -15,6 +15,11 @@ using namespace Mapsforge;
|
||||
#define MD(val) ((val) / 1e6)
|
||||
#define OFFSET_MASK 0x7FFFFFFFFFL
|
||||
|
||||
#define KEY_NAME "name"
|
||||
#define KEY_HOUSE "addr:housenumber"
|
||||
#define KEY_REF "ref"
|
||||
#define KEY_ELE "ele"
|
||||
|
||||
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
||||
QList<MapData::Path> *dst)
|
||||
{
|
||||
@ -43,65 +48,6 @@ static bool isClosed(const Polygon &poly)
|
||||
return (distance(poly.first().first(), poly.first().last()) < 0.000000001);
|
||||
}
|
||||
|
||||
static bool readTags(SubFile &subfile, int count,
|
||||
const QVector<MapData::Tag> &tags, QVector<MapData::Tag> &list)
|
||||
{
|
||||
QVector<quint32> ids(count);
|
||||
|
||||
list.resize(count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!subfile.readVUInt32(ids[i]))
|
||||
return false;
|
||||
if (ids[i] >= (quint32)tags.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const MapData::Tag &tag = tags.at(ids.at(i));
|
||||
|
||||
if (tag.value.length() == 2 && tag.value.at(0) == '%') {
|
||||
QByteArray value;
|
||||
|
||||
if (tag.value.at(1) == 'b') {
|
||||
quint8 b;
|
||||
if (!subfile.readByte(b))
|
||||
return false;
|
||||
value.setNum(b);
|
||||
} else if (tag.value.at(1) == 'i') {
|
||||
qint32 u;
|
||||
if (!subfile.readInt32(u))
|
||||
return false;
|
||||
|
||||
if (tag.key.contains(":colour"))
|
||||
value = QColor((quint32)u).name().toLatin1();
|
||||
else
|
||||
value.setNum(u);
|
||||
} else if (tag.value.at(1) == 'f') {
|
||||
quint32 u;
|
||||
if (!subfile.readUInt32(u))
|
||||
return false;
|
||||
float *f = (float *)&u;
|
||||
value.setNum(*f);
|
||||
} else if (tag.value.at(1) == 'h') {
|
||||
quint16 s;
|
||||
if (!subfile.readUInt16(s))
|
||||
return false;
|
||||
value.setNum(s);
|
||||
} else if (tag.value.at(1) == 's') {
|
||||
if (!subfile.readString(value))
|
||||
return false;
|
||||
} else
|
||||
value = tag.value;
|
||||
|
||||
list[i] = MapData::Tag(tag.key, value);
|
||||
} else
|
||||
list[i] = tag;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool readSingleDelta(SubFile &subfile, const Coordinates &c,
|
||||
int count, QVector<Coordinates> &nodes)
|
||||
{
|
||||
@ -204,6 +150,64 @@ static bool readOffset(QDataStream &stream, quint64 &offset)
|
||||
return (stream.status() == QDataStream::Ok);
|
||||
}
|
||||
|
||||
bool MapData::readTags(SubFile &subfile, int count,
|
||||
const QVector<TagSource> &tags, QVector<Tag> &list)
|
||||
{
|
||||
QVector<quint32> ids(count);
|
||||
|
||||
list.resize(count);
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
if (!subfile.readVUInt32(ids[i]))
|
||||
return false;
|
||||
if (ids[i] >= (quint32)tags.size())
|
||||
return false;
|
||||
}
|
||||
|
||||
for (int i = 0; i < count; i++) {
|
||||
const TagSource &tag = tags.at(ids.at(i));
|
||||
|
||||
if (tag.value.length() == 2 && tag.value.at(0) == '%') {
|
||||
QByteArray value;
|
||||
|
||||
if (tag.value.at(1) == 'b') {
|
||||
quint8 b;
|
||||
if (!subfile.readByte(b))
|
||||
return false;
|
||||
value.setNum(b);
|
||||
} else if (tag.value.at(1) == 'i') {
|
||||
qint32 u;
|
||||
if (!subfile.readInt32(u))
|
||||
return false;
|
||||
if (tag.key.contains(":colour"))
|
||||
value = QColor((quint32)u).name().toLatin1();
|
||||
else
|
||||
value.setNum(u);
|
||||
} else if (tag.value.at(1) == 'f') {
|
||||
quint32 u;
|
||||
if (!subfile.readUInt32(u))
|
||||
return false;
|
||||
float *f = (float *)&u;
|
||||
value.setNum(*f);
|
||||
} else if (tag.value.at(1) == 'h') {
|
||||
quint16 s;
|
||||
if (!subfile.readUInt16(s))
|
||||
return false;
|
||||
value.setNum(s);
|
||||
} else if (tag.value.at(1) == 's') {
|
||||
if (!subfile.readString(value))
|
||||
return false;
|
||||
} else
|
||||
value = tag.value;
|
||||
|
||||
list[i] = MapData::Tag(tag.id, value);
|
||||
} else
|
||||
list[i] = MapData::Tag(tag.id, tag.value);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapData::readSubFiles()
|
||||
{
|
||||
QDataStream stream(&_file);
|
||||
@ -273,34 +277,43 @@ bool MapData::readZoomInfo(SubFile &hdr)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapData::readTagInfo(SubFile &hdr)
|
||||
bool MapData::readTagInfo(SubFile &hdr, QVector<TagSource> &tags)
|
||||
{
|
||||
quint16 tags;
|
||||
QByteArray tag;
|
||||
quint16 size;
|
||||
QByteArray str;
|
||||
|
||||
if (!hdr.readUInt16(tags))
|
||||
if (!hdr.readUInt16(size))
|
||||
return false;
|
||||
_pointTags.resize(tags);
|
||||
for (quint16 i = 0; i < tags; i++) {
|
||||
if (!hdr.readString(tag))
|
||||
return false;
|
||||
_pointTags[i] = tag;
|
||||
}
|
||||
tags.resize(size);
|
||||
|
||||
if (!hdr.readUInt16(tags))
|
||||
return false;
|
||||
_pathTags.resize(tags);
|
||||
for (quint16 i = 0; i < tags; i++) {
|
||||
if (!hdr.readString(tag))
|
||||
for (quint16 i = 0; i < size; i++) {
|
||||
TagSource &tag = tags[i];
|
||||
if (!hdr.readString(str))
|
||||
return false;
|
||||
_pathTags[i] = tag;
|
||||
tag = str;
|
||||
unsigned key = _keys.value(tag.key);
|
||||
if (key)
|
||||
tag.id = key;
|
||||
else {
|
||||
tag.id = _keys.size() + 1;
|
||||
_keys.insert(tag.key, tag.id);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection,
|
||||
bool &debugMap)
|
||||
bool MapData::readTagInfo(SubFile &hdr)
|
||||
{
|
||||
_keys.insert(KEY_NAME, ID_NAME);
|
||||
_keys.insert(KEY_HOUSE, ID_HOUSE);
|
||||
_keys.insert(KEY_REF, ID_REF);
|
||||
_keys.insert(KEY_ELE, ID_ELE);
|
||||
|
||||
return (readTagInfo(hdr, _pointTags) && readTagInfo(hdr, _pathTags));
|
||||
}
|
||||
|
||||
bool MapData::readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap)
|
||||
{
|
||||
quint64 fileSize, date;
|
||||
quint32 version;
|
||||
@ -592,17 +605,17 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||
if (!subfile.readString(name))
|
||||
return false;
|
||||
name = name.split('\r').first();
|
||||
p.tags.append(Tag("name", name));
|
||||
p.tags.append(Tag(ID_NAME, name));
|
||||
}
|
||||
if (flags & 0x40) {
|
||||
if (!subfile.readString(houseNumber))
|
||||
return false;
|
||||
p.tags.append(Tag("addr:housenumber", houseNumber));
|
||||
p.tags.append(Tag(ID_HOUSE, houseNumber));
|
||||
}
|
||||
if (flags & 0x20) {
|
||||
if (!subfile.readString(reference))
|
||||
return false;
|
||||
p.tags.append(Tag("ref", reference));
|
||||
p.tags.append(Tag(ID_REF, reference));
|
||||
}
|
||||
if (flags & 0x10) {
|
||||
if (!(subfile.readVInt32(lat) && subfile.readVInt32(lon)))
|
||||
@ -675,18 +688,18 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
||||
if (!subfile.readString(name))
|
||||
return false;
|
||||
name = name.split('\r').first();
|
||||
p.tags.append(Tag("name", name));
|
||||
p.tags.append(Tag(ID_NAME, name));
|
||||
}
|
||||
if (flags & 0x40) {
|
||||
if (!subfile.readString(houseNumber))
|
||||
return false;
|
||||
p.tags.append(Tag("addr:housenumber", houseNumber));
|
||||
p.tags.append(Tag(ID_HOUSE, houseNumber));
|
||||
}
|
||||
if (flags & 0x20) {
|
||||
qint32 elevation;
|
||||
if (!subfile.readVInt32(elevation))
|
||||
return false;
|
||||
p.tags.append(Tag("ele", QByteArray::number(elevation)));
|
||||
p.tags.append(Tag(ID_ELE, QByteArray::number(elevation)));
|
||||
}
|
||||
|
||||
list->append(p);
|
||||
|
@ -9,6 +9,10 @@
|
||||
#include "common/range.h"
|
||||
#include "common/polygon.h"
|
||||
|
||||
#define ID_NAME 1
|
||||
#define ID_HOUSE 2
|
||||
#define ID_REF 3
|
||||
#define ID_ELE 4
|
||||
|
||||
namespace Mapsforge {
|
||||
|
||||
@ -22,21 +26,12 @@ public:
|
||||
|
||||
struct Tag {
|
||||
Tag() {}
|
||||
Tag(const QByteArray &key, const QByteArray &value)
|
||||
: key(key), value(value) {}
|
||||
Tag(const QByteArray &str)
|
||||
{
|
||||
QList<QByteArray> l(str.split('='));
|
||||
if (l.size() == 2) {
|
||||
key = l.at(0);
|
||||
value = l.at(1);
|
||||
}
|
||||
}
|
||||
Tag(unsigned key, const QByteArray &value) : key(key), value(value) {}
|
||||
|
||||
bool operator==(const Tag &other) const
|
||||
{return (key == other.key && value == other.value);}
|
||||
|
||||
QByteArray key;
|
||||
unsigned key;
|
||||
QByteArray value;
|
||||
};
|
||||
|
||||
@ -75,6 +70,7 @@ public:
|
||||
|
||||
void points(const RectC &rect, int zoom, QList<Point> *list);
|
||||
void paths(const RectC &rect, int zoom, QList<Path> *set);
|
||||
unsigned tagId(const QByteArray &name) const {return _keys.value(name);}
|
||||
|
||||
void load();
|
||||
void clear();
|
||||
@ -128,10 +124,27 @@ private:
|
||||
int zoom;
|
||||
};
|
||||
|
||||
struct TagSource {
|
||||
TagSource() {}
|
||||
TagSource(const QByteArray &str)
|
||||
{
|
||||
QList<QByteArray> l(str.split('='));
|
||||
if (l.size() == 2) {
|
||||
key = l.at(0);
|
||||
value = l.at(1);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray key;
|
||||
QByteArray value;
|
||||
unsigned id;
|
||||
};
|
||||
|
||||
typedef RTree<VectorTile *, double, 2> TileTree;
|
||||
|
||||
bool readZoomInfo(SubFile &hdr);
|
||||
bool readTagInfo(SubFile &hdr);
|
||||
bool readTagInfo(SubFile &hdr, QVector<TagSource> &tags);
|
||||
bool readMapInfo(SubFile &hdr, QByteArray &projection, bool &debugMap);
|
||||
bool readHeader();
|
||||
bool readSubFiles();
|
||||
@ -145,6 +158,8 @@ private:
|
||||
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
|
||||
bool readPoints(const VectorTile *tile, int zoom, QList<Point> *list);
|
||||
|
||||
static bool readTags(SubFile &subfile, int count,
|
||||
const QVector<TagSource> &tags, QVector<Tag> &list);
|
||||
static bool pathCb(VectorTile *tile, void *context);
|
||||
static bool pointCb(VectorTile *tile, void *context);
|
||||
|
||||
@ -153,9 +168,10 @@ private:
|
||||
QFile _file;
|
||||
RectC _bounds;
|
||||
quint16 _tileSize;
|
||||
QVector<Tag> _pointTags, _pathTags;
|
||||
QVector<SubFileInfo> _subFiles;
|
||||
QVector<TagSource> _pointTags, _pathTags;
|
||||
QList<TileTree*> _tiles;
|
||||
QHash<QByteArray, unsigned> _keys;
|
||||
|
||||
QCache<Key, QList<Path> > _pathCache;
|
||||
QCache<Key, QList<Point> > _pointCache;
|
||||
|
@ -5,12 +5,6 @@
|
||||
|
||||
using namespace Mapsforge;
|
||||
|
||||
static const Style& style(qreal ratio)
|
||||
{
|
||||
static Style s(ProgramPaths::renderthemeFile(), ratio);
|
||||
return s;
|
||||
}
|
||||
|
||||
static qreal area(const QPainterPath &polygon)
|
||||
{
|
||||
qreal area = 0;
|
||||
@ -41,8 +35,7 @@ static QPointF centroid(const QPainterPath &polygon)
|
||||
return QPointF(cx * factor, cy * factor);
|
||||
}
|
||||
|
||||
static const QByteArray *label(const QByteArray &key,
|
||||
const QVector<MapData::Tag> &tags)
|
||||
static const QByteArray *label(unsigned key, const QVector<MapData::Tag> &tags)
|
||||
{
|
||||
for (int i = 0; i < tags.size(); i++) {
|
||||
const MapData::Tag &tag = tags.at(i);
|
||||
@ -61,9 +54,8 @@ static const QColor *haloColor(const Style::TextRender *ti)
|
||||
|
||||
void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.pointLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.pointSymbols(_zoom));
|
||||
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
|
||||
QList<PainterPoint> points;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
@ -115,9 +107,8 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
|
||||
QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
|
||||
QList<const Style::Symbol*> symbols(_style->areaSymbols(_zoom));
|
||||
|
||||
for (int i = 0; i < paths.size(); i++) {
|
||||
PainterPath &path = paths[i];
|
||||
@ -168,8 +159,7 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
QVector<PainterPath> &paths)
|
||||
{
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
|
||||
QList<const Style::TextRender*> instructions(_style->pathLabels(_zoom));
|
||||
QSet<QByteArray> set;
|
||||
|
||||
for (int i = 0; i < instructions.size(); i++) {
|
||||
@ -183,9 +173,7 @@ void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||
continue;
|
||||
if (!ri->rule().match(path.path->closed, path.path->tags))
|
||||
continue;
|
||||
bool limit = (ri->key() == "ref" || ri->key() == "ele"
|
||||
|| ri->key() == "ref_hike" || ri->key() == "ref_cycle"
|
||||
|| ri->key() == "ref_mtb");
|
||||
bool limit = (ri->key() == ID_ELE || ri->key() == ID_REF);
|
||||
if (limit && set.contains(*lbl))
|
||||
continue;
|
||||
|
||||
@ -242,7 +230,6 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QCache<PathKey, QList<const Style::PathRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::PathRender*> *ri;
|
||||
|
||||
for (int i = 0; i < _paths.size(); i++) {
|
||||
@ -253,8 +240,8 @@ void RasterTile::pathInstructions(QVector<PainterPath> &paths,
|
||||
rp.path = &path;
|
||||
|
||||
if (!(ri = cache.object(key))) {
|
||||
ri = new QList<const Style::PathRender*>(s.paths(_zoom, path.closed,
|
||||
path.tags));
|
||||
ri = new QList<const Style::PathRender*>(_style->paths(_zoom,
|
||||
path.closed, path.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &rp));
|
||||
cache.insert(key, ri);
|
||||
@ -269,7 +256,6 @@ void RasterTile::circleInstructions(
|
||||
QVector<RasterTile::RenderInstruction> &instructions)
|
||||
{
|
||||
QCache<PointKey, QList<const Style::CircleRender *> > cache(8192);
|
||||
const Style &s = style(_ratio);
|
||||
QList<const Style::CircleRender*> *ri;
|
||||
|
||||
for (int i = 0; i < _points.size(); i++) {
|
||||
@ -277,7 +263,8 @@ void RasterTile::circleInstructions(
|
||||
PointKey key(_zoom, point.tags);
|
||||
|
||||
if (!(ri = cache.object(key))) {
|
||||
ri = new QList<const Style::CircleRender*>(s.circles(_zoom, point.tags));
|
||||
ri = new QList<const Style::CircleRender*>(_style->circles(_zoom,
|
||||
point.tags));
|
||||
for (int j = 0; j < ri->size(); j++)
|
||||
instructions.append(RenderInstruction(ri->at(j), &point));
|
||||
cache.insert(key, ri);
|
||||
|
@ -14,12 +14,12 @@ namespace Mapsforge {
|
||||
class RasterTile
|
||||
{
|
||||
public:
|
||||
RasterTile(const Projection &proj, const Transform &transform, int zoom,
|
||||
const QRect &rect, qreal ratio, const QList<MapData::Path> &paths,
|
||||
const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
|
||||
_zoom(zoom), _rect(rect), _ratio(ratio),
|
||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
|
||||
_points(points), _valid(false) {}
|
||||
RasterTile(const Projection &proj, const Transform &transform,
|
||||
const Style *style, int zoom, const QRect &rect, qreal ratio,
|
||||
const QList<MapData::Path> &paths, const QList<MapData::Point> &points)
|
||||
: _proj(proj), _transform(transform), _style(style),
|
||||
_zoom(zoom), _rect(rect), _ratio(ratio), _pixmap(rect.width() * ratio,
|
||||
rect.height() * ratio), _paths(paths), _points(points), _valid(false) {}
|
||||
|
||||
int zoom() const {return _zoom;}
|
||||
QPoint xy() const {return _rect.topLeft();}
|
||||
@ -159,8 +159,10 @@ private:
|
||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||
void drawPaths(QPainter *painter, QVector<PainterPath> &paths);
|
||||
|
||||
|
||||
Projection _proj;
|
||||
Transform _transform;
|
||||
const Style *_style;
|
||||
int _zoom;
|
||||
QRect _rect;
|
||||
qreal _ratio;
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <QUrl>
|
||||
#include <QFileInfo>
|
||||
#include <QImageReader>
|
||||
#include "common/programpaths.h"
|
||||
#include "style.h"
|
||||
|
||||
using namespace Mapsforge;
|
||||
@ -37,6 +38,48 @@ static QImage image(const QString &path, int width, int height, qreal ratio)
|
||||
return QImage(path);
|
||||
}
|
||||
|
||||
static QList<unsigned> keyList(const MapData &data, const QList<QByteArray> &in)
|
||||
{
|
||||
QList<unsigned> out;
|
||||
|
||||
for (int i = 0; i < in.size(); i++) {
|
||||
if (in.at(i) == "*")
|
||||
out.append(0);
|
||||
else {
|
||||
unsigned key = data.tagId(in.at(i));
|
||||
if (key)
|
||||
out.append(key);
|
||||
}
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static QList<QByteArray> valList(const QList<QByteArray> &in)
|
||||
{
|
||||
QList<QByteArray> out;
|
||||
|
||||
for (int i = 0; i < in.size(); i++) {
|
||||
if (in.at(i) == "*")
|
||||
out.append(QByteArray());
|
||||
else
|
||||
out.append(in.at(i));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
Style::Rule::Filter::Filter(const MapData &data, const QList<QByteArray> &keys,
|
||||
const QList<QByteArray> &vals) : _neg(false)
|
||||
{
|
||||
_keys = keyList(data, keys);
|
||||
|
||||
QList<QByteArray> vc(vals);
|
||||
if (vc.removeAll("~"))
|
||||
_neg = true;
|
||||
_vals = valList(vc);
|
||||
}
|
||||
|
||||
bool Style::Rule::match(const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
for (int i = 0; i < _filters.size(); i++)
|
||||
@ -237,7 +280,7 @@ void Style::circle(QXmlStreamReader &reader, const Rule &rule)
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule,
|
||||
QList<QList<TextRender>*> &lists)
|
||||
{
|
||||
TextRender ri(rule);
|
||||
@ -249,7 +292,7 @@ void Style::text(QXmlStreamReader &reader, const Rule &rule,
|
||||
bool ok;
|
||||
|
||||
if (attr.hasAttribute("k"))
|
||||
ri._key = attr.value("k").toLatin1();
|
||||
ri._key = data.tagId(attr.value("k").toLatin1());
|
||||
if (attr.hasAttribute("fill"))
|
||||
ri._fillColor = QColor(attr.value("fill").toString());
|
||||
if (attr.hasAttribute("stroke"))
|
||||
@ -357,8 +400,9 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
reader.skipCurrentElement();
|
||||
}
|
||||
|
||||
void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const QSet<QString> &cats, const Rule &parent)
|
||||
void Style::rule(QXmlStreamReader &reader, const QString &dir,
|
||||
const MapData &data, qreal ratio, const QSet<QString> &cats,
|
||||
const Rule &parent)
|
||||
{
|
||||
Rule r(parent);
|
||||
const QXmlStreamAttributes &attr = reader.attributes();
|
||||
@ -399,11 +443,11 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
|
||||
QList<QByteArray> keys(attr.value("k").toLatin1().split('|'));
|
||||
QList<QByteArray> vals(attr.value("v").toLatin1().split('|'));
|
||||
r.addFilter(Rule::Filter(keys, vals));
|
||||
r.addFilter(Rule::Filter(data, keys, vals));
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("rule"))
|
||||
rule(reader, dir, ratio, cats, r);
|
||||
rule(reader, dir, data, ratio, cats, r);
|
||||
else if (reader.name() == QLatin1String("area"))
|
||||
area(reader, dir, ratio, r);
|
||||
else if (reader.name() == QLatin1String("line"))
|
||||
@ -413,14 +457,14 @@ void Style::rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
else if (reader.name() == QLatin1String("pathText")) {
|
||||
QList<QList<TextRender>*> list;
|
||||
list.append(&_pathLabels);
|
||||
text(reader, r, list);
|
||||
text(reader, data, r, list);
|
||||
} else if (reader.name() == QLatin1String("caption")) {
|
||||
QList<QList<TextRender>*> list;
|
||||
if (r._type == Rule::WayType || r._type == Rule::AnyType)
|
||||
list.append(&_areaLabels);
|
||||
if (r._type == Rule::NodeType || r._type == Rule::AnyType)
|
||||
list.append(&_pointLabels);
|
||||
text(reader, r, list);
|
||||
text(reader, data, r, list);
|
||||
}
|
||||
else if (reader.name() == QLatin1String("symbol"))
|
||||
symbol(reader, dir, ratio, r);
|
||||
@ -462,14 +506,14 @@ void Style::stylemenu(QXmlStreamReader &reader, QSet<QString> &cats)
|
||||
}
|
||||
|
||||
void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
qreal ratio)
|
||||
const MapData &data, qreal ratio)
|
||||
{
|
||||
Rule r;
|
||||
QSet<QString> cats;
|
||||
|
||||
while (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("rule"))
|
||||
rule(reader, dir, ratio, cats, r);
|
||||
rule(reader, dir, data, ratio, cats, r);
|
||||
else if (reader.name() == QLatin1String("stylemenu"))
|
||||
stylemenu(reader, cats);
|
||||
else
|
||||
@ -477,7 +521,7 @@ void Style::rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
}
|
||||
}
|
||||
|
||||
bool Style::loadXml(const QString &path, qreal ratio)
|
||||
bool Style::loadXml(const QString &path, const MapData &data, qreal ratio)
|
||||
{
|
||||
QFile file(path);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
@ -487,7 +531,7 @@ bool Style::loadXml(const QString &path, qreal ratio)
|
||||
|
||||
if (reader.readNextStartElement()) {
|
||||
if (reader.name() == QLatin1String("rendertheme"))
|
||||
rendertheme(reader, fi.absolutePath(), ratio);
|
||||
rendertheme(reader, fi.absolutePath(), data, ratio);
|
||||
else
|
||||
reader.raiseError("Not a Mapsforge style file");
|
||||
}
|
||||
@ -499,10 +543,22 @@ bool Style::loadXml(const QString &path, qreal ratio)
|
||||
return !reader.error();
|
||||
}
|
||||
|
||||
Style::Style(const QString &path, qreal ratio)
|
||||
void Style::load(const MapData &data, qreal ratio)
|
||||
{
|
||||
if (!QFileInfo::exists(path) || !loadXml(path, ratio))
|
||||
loadXml(":/mapsforge/default.xml", ratio);
|
||||
QString path(ProgramPaths::renderthemeFile());
|
||||
|
||||
if (!QFileInfo::exists(path) || !loadXml(path, data, ratio))
|
||||
loadXml(":/mapsforge/default.xml", data, ratio);
|
||||
}
|
||||
|
||||
void Style::clear()
|
||||
{
|
||||
_paths.clear();
|
||||
_circles.clear();
|
||||
_pathLabels.clear();
|
||||
_pointLabels.clear();
|
||||
_areaLabels.clear();
|
||||
_symbols.clear();
|
||||
}
|
||||
|
||||
QList<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||
|
@ -53,16 +53,8 @@ public:
|
||||
class Filter {
|
||||
public:
|
||||
Filter() : _neg(false) {}
|
||||
Filter(const QList<QByteArray> &keys, const QList<QByteArray> &vals)
|
||||
: _neg(false)
|
||||
{
|
||||
_keys = list(keys);
|
||||
|
||||
QList<QByteArray> vc(vals);
|
||||
if (vc.removeAll("~"))
|
||||
_neg = true;
|
||||
_vals = list(vc);
|
||||
}
|
||||
Filter(const MapData &data, const QList<QByteArray> &keys,
|
||||
const QList<QByteArray> &vals);
|
||||
|
||||
bool match(const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
@ -76,30 +68,15 @@ public:
|
||||
|
||||
bool isTautology() const
|
||||
{
|
||||
return (!_neg && _keys.contains(QByteArray())
|
||||
&& _vals.contains(QByteArray()));
|
||||
return (!_neg && _keys.contains(0u) && _vals.contains(QByteArray()));
|
||||
}
|
||||
|
||||
private:
|
||||
static QList<QByteArray> list(const QList<QByteArray> &in)
|
||||
{
|
||||
QList<QByteArray> out;
|
||||
|
||||
for (int i = 0; i < in.size(); i++) {
|
||||
if (in.at(i) == "*")
|
||||
out.append(QByteArray());
|
||||
else
|
||||
out.append(in.at(i));
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
bool keyMatches(const QVector<MapData::Tag> &tags) const
|
||||
{
|
||||
for (int i = 0; i < _keys.size(); i++)
|
||||
for (int j = 0; j < tags.size(); j++)
|
||||
if (wcmp(_keys.at(i), tags.at(j).key))
|
||||
if (!_keys.at(i) || _keys.at(i) == tags.at(j).key)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -115,7 +92,7 @@ public:
|
||||
return false;
|
||||
}
|
||||
|
||||
QList<QByteArray> _keys;
|
||||
QList<unsigned> _keys;
|
||||
QList<QByteArray> _vals;
|
||||
bool _neg;
|
||||
};
|
||||
@ -218,7 +195,7 @@ public:
|
||||
const QColor &fillColor() const {return _fillColor;}
|
||||
const QColor &strokeColor() const {return _strokeColor;}
|
||||
qreal strokeWidth() const {return _strokeWidth;}
|
||||
const QByteArray &key() const {return _key;}
|
||||
unsigned key() const {return _key;}
|
||||
int priority() const {return _priority;}
|
||||
|
||||
private:
|
||||
@ -228,7 +205,7 @@ public:
|
||||
QColor _fillColor, _strokeColor;
|
||||
qreal _strokeWidth;
|
||||
QFont _font;
|
||||
QByteArray _key;
|
||||
unsigned _key;
|
||||
};
|
||||
|
||||
class Symbol : public Render
|
||||
@ -246,7 +223,8 @@ public:
|
||||
QImage _img;
|
||||
};
|
||||
|
||||
Style(const QString &path, qreal ratio);
|
||||
void load(const MapData &data, qreal ratio);
|
||||
void clear();
|
||||
|
||||
QList<const PathRender *> paths(int zoom, bool closed,
|
||||
const QVector<MapData::Tag> &tags) const;
|
||||
@ -264,18 +242,19 @@ private:
|
||||
QList<TextRender> _pathLabels, _pointLabels, _areaLabels;
|
||||
QList<Symbol> _symbols;
|
||||
|
||||
bool loadXml(const QString &path, qreal ratio);
|
||||
void rendertheme(QXmlStreamReader &reader, const QString &dir, qreal ratio);
|
||||
bool loadXml(const QString &path, const MapData &data, qreal ratio);
|
||||
void rendertheme(QXmlStreamReader &reader, const QString &dir,
|
||||
const MapData &data, qreal ratio);
|
||||
void layer(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
void stylemenu(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
void cat(QXmlStreamReader &reader, QSet<QString> &cats);
|
||||
void rule(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const QSet<QString> &cats, const Rule &parent);
|
||||
void rule(QXmlStreamReader &reader, const QString &dir, const MapData &data,
|
||||
qreal ratio, const QSet<QString> &cats, const Rule &parent);
|
||||
void area(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule);
|
||||
void line(QXmlStreamReader &reader, const Rule &rule);
|
||||
void circle(QXmlStreamReader &reader, const Rule &rule);
|
||||
void text(QXmlStreamReader &reader, const Rule &rule,
|
||||
void text(QXmlStreamReader &reader, const MapData &data, const Rule &rule,
|
||||
QList<QList<TextRender> *> &lists);
|
||||
void symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
|
||||
const Rule &rule);
|
||||
|
@ -24,11 +24,15 @@ MapsforgeMap::MapsforgeMap(const QString &fileName, QObject *parent)
|
||||
void MapsforgeMap::load()
|
||||
{
|
||||
_data.load();
|
||||
_style.load(_data, _tileRatio);
|
||||
}
|
||||
|
||||
void MapsforgeMap::unload()
|
||||
{
|
||||
cancelJobs(true);
|
||||
|
||||
_data.clear();
|
||||
_style.clear();
|
||||
}
|
||||
|
||||
int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
@ -54,7 +58,7 @@ int MapsforgeMap::zoomFit(const QSize &size, const RectC &rect)
|
||||
|
||||
int MapsforgeMap::zoomIn()
|
||||
{
|
||||
cancelJobs();
|
||||
cancelJobs(false);
|
||||
|
||||
_zoom = qMin(_zoom + 1, _data.zooms().max());
|
||||
updateTransform();
|
||||
@ -63,7 +67,7 @@ int MapsforgeMap::zoomIn()
|
||||
|
||||
int MapsforgeMap::zoomOut()
|
||||
{
|
||||
cancelJobs();
|
||||
cancelJobs(false);
|
||||
|
||||
_zoom = qMax(_zoom - 1, _data.zooms().min());
|
||||
updateTransform();
|
||||
@ -148,10 +152,10 @@ void MapsforgeMap::jobFinished(MapsforgeMapJob *job)
|
||||
emit tilesLoaded();
|
||||
}
|
||||
|
||||
void MapsforgeMap::cancelJobs()
|
||||
void MapsforgeMap::cancelJobs(bool wait)
|
||||
{
|
||||
for (int i = 0; i < _jobs.size(); i++)
|
||||
_jobs.at(i)->cancel();
|
||||
_jobs.at(i)->cancel(wait);
|
||||
}
|
||||
|
||||
void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
@ -198,7 +202,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
||||
_data.points(pointRectD.toRectC(_projection, 20), _zoom,
|
||||
&points);
|
||||
|
||||
tiles.append(RasterTile(_projection, _transform, _zoom,
|
||||
tiles.append(RasterTile(_projection, _transform, &_style, _zoom,
|
||||
QRect(ttl, QSize(_data.tileSize(), _data.tileSize())),
|
||||
_tileRatio, paths, points));
|
||||
}
|
||||
|
@ -24,7 +24,12 @@ public:
|
||||
_future = QtConcurrent::map(_tiles, &Mapsforge::RasterTile::render);
|
||||
_watcher.setFuture(_future);
|
||||
}
|
||||
void cancel() {_future.cancel();}
|
||||
void cancel(bool wait)
|
||||
{
|
||||
_future.cancel();
|
||||
if (wait)
|
||||
_future.waitForFinished();
|
||||
}
|
||||
const QList<Mapsforge::RasterTile> &tiles() const {return _tiles;}
|
||||
|
||||
signals:
|
||||
@ -82,9 +87,10 @@ private:
|
||||
bool isRunning(int zoom, const QPoint &xy) const;
|
||||
void runJob(MapsforgeMapJob *job);
|
||||
void removeJob(MapsforgeMapJob *job);
|
||||
void cancelJobs();
|
||||
void cancelJobs(bool wait);
|
||||
|
||||
Mapsforge::MapData _data;
|
||||
Mapsforge::Style _style;
|
||||
int _zoom;
|
||||
|
||||
Projection _projection;
|
||||
|
Loading…
x
Reference in New Issue
Block a user