mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-01-31 17:15:14 +01:00
Fix/improve Mapsforge tiles rendering
This commit is contained in:
parent
981bd33680
commit
6cd122f59b
@ -3,6 +3,7 @@
|
|||||||
#include <QFile>
|
#include <QFile>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QColor>
|
#include <QColor>
|
||||||
|
#include "common/hash.h"
|
||||||
#include "map/osm.h"
|
#include "map/osm.h"
|
||||||
#include "subfile.h"
|
#include "subfile.h"
|
||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
@ -14,7 +15,7 @@ using namespace Mapsforge;
|
|||||||
#define MD(val) ((val) / 1e6)
|
#define MD(val) ((val) / 1e6)
|
||||||
#define OFFSET_MASK 0x7FFFFFFFFFL
|
#define OFFSET_MASK 0x7FFFFFFFFFL
|
||||||
|
|
||||||
static uint pointType(const QVector<MapData::Tag> &tags)
|
static quint8 pointType(const QVector<MapData::Tag> &tags)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < tags.size(); i++) {
|
for (int i = 0; i < tags.size(); i++) {
|
||||||
const MapData::Tag &tag = tags.at(i);
|
const MapData::Tag &tag = tags.at(i);
|
||||||
@ -37,20 +38,19 @@ static uint pointType(const QVector<MapData::Tag> &tags)
|
|||||||
|
|
||||||
static void setPointId(MapData::Point &p)
|
static void setPointId(MapData::Point &p)
|
||||||
{
|
{
|
||||||
uint hash = (uint)qHash(QPair<double,double>((uint)qHash(
|
HASH_T hash = qHash(QPair<double, double>(p.coordinates.lon(),
|
||||||
QPair<double, double>(p.coordinates.lon(), p.coordinates.lat())),
|
p.coordinates.lat()));
|
||||||
(uint)qHash(p.label)));
|
quint8 type = pointType(p.tags);
|
||||||
uint type = pointType(p.tags);
|
|
||||||
|
|
||||||
p.id = ((quint64)type)<<32 | hash;
|
p.id = ((quint64)type)<<56 | (quint64)hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
static void copyPaths(const RectC &rect, const QList<MapData::Path> *src,
|
||||||
QList<MapData::Path> *dst)
|
QSet<MapData::Path> *dst)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < src->size(); i++)
|
for (int i = 0; i < src->size(); i++)
|
||||||
if (rect.intersects(src->at(i).poly.boundingRect()))
|
if (rect.intersects(src->at(i).poly.boundingRect()))
|
||||||
dst->append(src->at(i));
|
dst->insert(src->at(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void copyPoints(const RectC &rect, const QList<MapData::Point> *src,
|
static void copyPoints(const RectC &rect, const QList<MapData::Point> *src,
|
||||||
@ -194,7 +194,7 @@ static bool readDoubleDelta(SubFile &subfile, const Coordinates &c,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool readPolygon(SubFile &subfile, const Coordinates &c,
|
static bool readPolygonPath(SubFile &subfile, const Coordinates &c,
|
||||||
bool doubleDelta, Polygon &polygon)
|
bool doubleDelta, Polygon &polygon)
|
||||||
{
|
{
|
||||||
quint32 blocks, nodes;
|
quint32 blocks, nodes;
|
||||||
@ -202,7 +202,7 @@ static bool readPolygon(SubFile &subfile, const Coordinates &c,
|
|||||||
if (!subfile.readVUInt32(blocks))
|
if (!subfile.readVUInt32(blocks))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
polygon.reserve(blocks);
|
polygon.reserve(polygon.size() + blocks);
|
||||||
for (quint32 i = 0; i < blocks; i++) {
|
for (quint32 i = 0; i < blocks; i++) {
|
||||||
if (!subfile.readVUInt32(nodes) || !nodes)
|
if (!subfile.readVUInt32(nodes) || !nodes)
|
||||||
return false;
|
return false;
|
||||||
@ -494,7 +494,7 @@ void MapData::clearTiles()
|
|||||||
bool MapData::pathCb(VectorTile *tile, void *context)
|
bool MapData::pathCb(VectorTile *tile, void *context)
|
||||||
{
|
{
|
||||||
PathCTX *ctx = (PathCTX*)context;
|
PathCTX *ctx = (PathCTX*)context;
|
||||||
ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->list);
|
ctx->data->paths(tile, ctx->rect, ctx->zoom, ctx->set);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -545,10 +545,10 @@ void MapData::points(const VectorTile *tile, const RectC &rect, int zoom,
|
|||||||
copyPoints(rect, cached, list);
|
copyPoints(rect, cached, list);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MapData::paths(const RectC &rect, int zoom, QList<Path> *list)
|
void MapData::paths(const RectC &rect, int zoom, QSet<Path> *set)
|
||||||
{
|
{
|
||||||
int l(level(zoom));
|
int l(level(zoom));
|
||||||
PathCTX ctx(this, rect, zoom, list);
|
PathCTX ctx(this, rect, zoom, set);
|
||||||
double min[2], max[2];
|
double min[2], max[2];
|
||||||
|
|
||||||
min[0] = rect.left();
|
min[0] = rect.left();
|
||||||
@ -560,7 +560,7 @@ void MapData::paths(const RectC &rect, int zoom, QList<Path> *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||||
QList<Path> *list)
|
QSet<Path> *set)
|
||||||
{
|
{
|
||||||
Key key(tile, zoom);
|
Key key(tile, zoom);
|
||||||
QList<Path> *cached = _pathCache.object(key);
|
QList<Path> *cached = _pathCache.object(key);
|
||||||
@ -568,12 +568,12 @@ void MapData::paths(const VectorTile *tile, const RectC &rect, int zoom,
|
|||||||
if (!cached) {
|
if (!cached) {
|
||||||
QList<Path> *p = new QList<Path>();
|
QList<Path> *p = new QList<Path>();
|
||||||
if (readPaths(tile, zoom, p)) {
|
if (readPaths(tile, zoom, p)) {
|
||||||
copyPaths(rect, p, list);
|
copyPaths(rect, p, set);
|
||||||
_pathCache.insert(key, p);
|
_pathCache.insert(key, p);
|
||||||
} else
|
} else
|
||||||
delete p;
|
delete p;
|
||||||
} else
|
} else
|
||||||
copyPaths(rect, cached, list);
|
copyPaths(rect, cached, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
||||||
@ -604,7 +604,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
|||||||
return false;
|
return false;
|
||||||
|
|
||||||
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
||||||
Path p;
|
Path p(subfile.offset() + subfile.pos());
|
||||||
qint32 lon = 0, lat = 0;
|
qint32 lon = 0, lat = 0;
|
||||||
|
|
||||||
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
||||||
@ -646,8 +646,9 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
|||||||
|
|
||||||
Q_ASSERT(blocks);
|
Q_ASSERT(blocks);
|
||||||
for (unsigned j = 0; j < blocks; j++) {
|
for (unsigned j = 0; j < blocks; j++) {
|
||||||
if (!readPolygon(subfile, tile->pos, flags & 0x04, p.poly))
|
if (!readPolygonPath(subfile, tile->pos, flags & 0x04, p.poly))
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
p.closed = isClosed(p.poly);
|
p.closed = isClosed(p.poly);
|
||||||
if (flags & 0x10)
|
if (flags & 0x10)
|
||||||
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
|
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
|
||||||
@ -655,7 +656,6 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
|||||||
|
|
||||||
list->append(p);
|
list->append(p);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -720,6 +720,7 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
|
|||||||
}
|
}
|
||||||
|
|
||||||
setPointId(p);
|
setPointId(p);
|
||||||
|
|
||||||
list->append(p);
|
list->append(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -735,15 +736,14 @@ QDebug operator<<(QDebug dbg, const Mapsforge::MapData::Tag &tag)
|
|||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const MapData::Path &path)
|
QDebug operator<<(QDebug dbg, const MapData::Path &path)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Path(" << path.poly.boundingRect() << ", " << path.label
|
dbg.nospace() << "Path(" << path.poly.boundingRect() << ", "
|
||||||
<< ", " << path.tags << ")";
|
<< path.tags << ")";
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
|
|
||||||
QDebug operator<<(QDebug dbg, const MapData::Point &point)
|
QDebug operator<<(QDebug dbg, const MapData::Point &point)
|
||||||
{
|
{
|
||||||
dbg.nospace() << "Point(" << point.coordinates << "," << point.label
|
dbg.nospace() << "Point(" << point.coordinates << ", " << point.tags << ")";
|
||||||
<< ", " << point.tags << ")";
|
|
||||||
return dbg.space();
|
return dbg.space();
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
#endif // QT_NO_DEBUG
|
||||||
|
@ -44,29 +44,29 @@ public:
|
|||||||
struct Point {
|
struct Point {
|
||||||
Point(const Coordinates &c) : coordinates(c) {}
|
Point(const Coordinates &c) : coordinates(c) {}
|
||||||
|
|
||||||
|
quint64 id;
|
||||||
Coordinates coordinates;
|
Coordinates coordinates;
|
||||||
QVector<Tag> tags;
|
QVector<Tag> tags;
|
||||||
int layer;
|
int layer;
|
||||||
quint64 id;
|
|
||||||
|
|
||||||
QString label;
|
|
||||||
|
|
||||||
bool operator<(const Point &other) const
|
bool operator<(const Point &other) const
|
||||||
{return id > other.id;}
|
{return id > other.id;}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Path {
|
struct Path {
|
||||||
|
Path(quint64 id) : id(id) {}
|
||||||
|
|
||||||
|
quint64 id;
|
||||||
Polygon poly;
|
Polygon poly;
|
||||||
QVector<Tag> tags;
|
QVector<Tag> tags;
|
||||||
Coordinates labelPos;
|
Coordinates labelPos;
|
||||||
int layer;
|
int layer;
|
||||||
bool closed;
|
bool closed;
|
||||||
|
|
||||||
QString label;
|
|
||||||
QPainterPath path;
|
|
||||||
|
|
||||||
bool operator<(const Path &other) const
|
bool operator<(const Path &other) const
|
||||||
{return layer < other.layer;}
|
{return layer < other.layer;}
|
||||||
|
bool operator==(const Path &other) const
|
||||||
|
{return (id == other.id);}
|
||||||
};
|
};
|
||||||
|
|
||||||
RectC bounds() const;
|
RectC bounds() const;
|
||||||
@ -75,7 +75,7 @@ public:
|
|||||||
int tileSize() const {return _tileSize;}
|
int tileSize() const {return _tileSize;}
|
||||||
|
|
||||||
void points(const RectC &rect, int zoom, QList<Point> *list);
|
void points(const RectC &rect, int zoom, QList<Point> *list);
|
||||||
void paths(const RectC &rect, int zoom, QList<Path> *list);
|
void paths(const RectC &rect, int zoom, QSet<Path> *set);
|
||||||
|
|
||||||
void load();
|
void load();
|
||||||
void clear();
|
void clear();
|
||||||
@ -101,13 +101,13 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct PathCTX {
|
struct PathCTX {
|
||||||
PathCTX(MapData *data, const RectC &rect, int zoom, QList<Path> *list)
|
PathCTX(MapData *data, const RectC &rect, int zoom, QSet<Path> *set)
|
||||||
: data(data), rect(rect), zoom(zoom), list(list) {}
|
: data(data), rect(rect), zoom(zoom), set(set) {}
|
||||||
|
|
||||||
MapData *data;
|
MapData *data;
|
||||||
const RectC ▭
|
const RectC ▭
|
||||||
int zoom;
|
int zoom;
|
||||||
QList<Path> *list;
|
QSet<Path> *set;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PointCTX {
|
struct PointCTX {
|
||||||
@ -140,7 +140,7 @@ private:
|
|||||||
|
|
||||||
int level(int zoom) const;
|
int level(int zoom) const;
|
||||||
void paths(const VectorTile *tile, const RectC &rect, int zoom,
|
void paths(const VectorTile *tile, const RectC &rect, int zoom,
|
||||||
QList<Path> *list);
|
QSet<Path> *set);
|
||||||
void points(const VectorTile *tile, const RectC &rect, int zoom,
|
void points(const VectorTile *tile, const RectC &rect, int zoom,
|
||||||
QList<Point> *list);
|
QList<Point> *list);
|
||||||
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
|
bool readPaths(const VectorTile *tile, int zoom, QList<Path> *list);
|
||||||
@ -175,6 +175,11 @@ inline HASH_T qHash(const MapData::Tag &tag)
|
|||||||
return ::qHash(tag.key) ^ ::qHash(tag.value);
|
return ::qHash(tag.key) ^ ::qHash(tag.value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline HASH_T qHash(const MapData::Path &path)
|
||||||
|
{
|
||||||
|
return ::qHash(path.id);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
#ifndef QT_NO_DEBUG
|
||||||
|
@ -3,7 +3,6 @@
|
|||||||
#include "common/programpaths.h"
|
#include "common/programpaths.h"
|
||||||
#include "map/mapsforgemap.h"
|
#include "map/mapsforgemap.h"
|
||||||
#include "map/textpathitem.h"
|
#include "map/textpathitem.h"
|
||||||
#include "map/textpointitem.h"
|
|
||||||
#include "rastertile.h"
|
#include "rastertile.h"
|
||||||
|
|
||||||
using namespace Mapsforge;
|
using namespace Mapsforge;
|
||||||
@ -44,34 +43,19 @@ static QPointF centroid(const QPainterPath &polygon)
|
|||||||
return QPointF(cx * factor, cy * factor);
|
return QPointF(cx * factor, cy * factor);
|
||||||
}
|
}
|
||||||
|
|
||||||
static QString *pointLabel(const Style::TextRender *ri, MapData::Point &point)
|
static const QByteArray *label(const QByteArray &key,
|
||||||
|
const QVector<MapData::Tag> &tags, bool *limit = 0)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < point.tags.size(); i++) {
|
for (int i = 0; i < tags.size(); i++) {
|
||||||
if (point.tags.at(i).key == ri->key()) {
|
const MapData::Tag &tag = tags.at(i);
|
||||||
if (point.tags.at(i).value.isEmpty())
|
|
||||||
|
if (tag.key == key) {
|
||||||
|
if (tag.value.isEmpty())
|
||||||
return 0;
|
return 0;
|
||||||
else {
|
else {
|
||||||
point.label = point.tags.at(i).value;
|
|
||||||
return &point.label;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static QString *pathLabel(const Style::TextRender *ri, MapData::Path &path,
|
|
||||||
bool *limit = 0)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < path.tags.size(); i++) {
|
|
||||||
if (path.tags.at(i).key == ri->key()) {
|
|
||||||
if (path.tags.at(i).value.isEmpty())
|
|
||||||
return 0;
|
|
||||||
else {
|
|
||||||
path.label = path.tags.at(i).value;
|
|
||||||
if (limit)
|
if (limit)
|
||||||
*limit = (path.tags.at(i).key == "ref");
|
*limit = (tag.key == "ref");
|
||||||
return &path.label;
|
return &tag.value;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -94,14 +78,14 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
|||||||
|
|
||||||
for (int i = 0; i < _points.size(); i++) {
|
for (int i = 0; i < _points.size(); i++) {
|
||||||
MapData::Point &point = _points[i];
|
MapData::Point &point = _points[i];
|
||||||
QString *label = 0;
|
const QByteArray *l = 0;
|
||||||
const Style::TextRender *ti = 0;
|
const Style::TextRender *ti = 0;
|
||||||
const Style::Symbol *si = 0;
|
const Style::Symbol *si = 0;
|
||||||
|
|
||||||
for (int j = 0; j < labels.size(); j++) {
|
for (int j = 0; j < labels.size(); j++) {
|
||||||
const Style::TextRender *ri = labels.at(j);
|
const Style::TextRender *ri = labels.at(j);
|
||||||
if (ri->rule().match(point.tags)) {
|
if (ri->rule().match(point.tags)) {
|
||||||
if ((label = pointLabel(ri, point))) {
|
if ((l = label(ri->key(), point.tags))) {
|
||||||
ti = ri;
|
ti = ri;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -124,9 +108,8 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
|||||||
const QColor *color = ti ? &ti->fillColor() : 0;
|
const QColor *color = ti ? &ti->fillColor() : 0;
|
||||||
const QColor *hColor = ti ? haloColor(ti) : 0;
|
const QColor *hColor = ti ? haloColor(ti) : 0;
|
||||||
|
|
||||||
TextPointItem *item = new TextPointItem(
|
PointItem *item = new PointItem(ll2xy(point.coordinates).toPoint(),
|
||||||
ll2xy(point.coordinates).toPoint(), label, font, img, color,
|
l ? new QString(*l) : 0, font, img, color, hColor);
|
||||||
hColor, 0);
|
|
||||||
if (item->isValid() && !item->collides(textItems))
|
if (item->isValid() && !item->collides(textItems))
|
||||||
textItems.append(item);
|
textItems.append(item);
|
||||||
else
|
else
|
||||||
@ -134,34 +117,36 @@ void RasterTile::processPointLabels(QList<TextItem*> &textItems)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
void RasterTile::processAreaLabels(QList<TextItem*> &textItems,
|
||||||
|
QVector<RenderPath> &renderPaths)
|
||||||
{
|
{
|
||||||
const Style &s = style(_ratio);
|
const Style &s = style(_ratio);
|
||||||
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
|
QList<const Style::TextRender*> labels(s.areaLabels(_zoom));
|
||||||
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
|
QList<const Style::Symbol*> symbols(s.areaSymbols(_zoom));
|
||||||
|
|
||||||
for (int i = 0; i < _paths.size(); i++) {
|
for (int i = 0; i < renderPaths.size(); i++) {
|
||||||
MapData::Path &path = _paths[i];
|
RenderPath &path = renderPaths[i];
|
||||||
QString *label = 0;
|
|
||||||
const Style::TextRender *ti = 0;
|
const Style::TextRender *ti = 0;
|
||||||
const Style::Symbol *si = 0;
|
const Style::Symbol *si = 0;
|
||||||
|
|
||||||
if (!path.closed)
|
if (!path.path->closed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int j = 0; j < labels.size(); j++) {
|
for (int j = 0; j < labels.size(); j++) {
|
||||||
const Style::TextRender *ri = labels.at(j);
|
const Style::TextRender *ri = labels.at(j);
|
||||||
if (ri->rule().match(path.closed, path.tags)) {
|
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||||
if ((label = pathLabel(ri, path))) {
|
const QByteArray *l;
|
||||||
|
if ((l = label(ri->key(), path.path->tags))) {
|
||||||
|
path.label = *l;
|
||||||
ti = ri;
|
ti = ri;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < symbols.size(); j++) {
|
for (int j = 0; j < symbols.size(); j++) {
|
||||||
const Style::Symbol *ri = symbols.at(j);
|
const Style::Symbol *ri = symbols.at(j);
|
||||||
if (ri->rule().match(path.tags)) {
|
if (ri->rule().match(path.path->tags)) {
|
||||||
si = ri;
|
si = ri;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -170,18 +155,15 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
|||||||
if (!ti && !si)
|
if (!ti && !si)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (!path.path.elementCount())
|
|
||||||
path.path = painterPath(path.poly, false);
|
|
||||||
|
|
||||||
const QImage *img = si ? &si->img() : 0;
|
const QImage *img = si ? &si->img() : 0;
|
||||||
const QFont *font = ti ? &ti->font() : 0;
|
const QFont *font = ti ? &ti->font() : 0;
|
||||||
const QColor *color = ti ? &ti->fillColor() : 0;
|
const QColor *color = ti ? &ti->fillColor() : 0;
|
||||||
const QColor *hColor = ti ? haloColor(ti) : 0;
|
const QColor *hColor = ti ? haloColor(ti) : 0;
|
||||||
QPointF pos = path.labelPos.isNull()
|
QPointF pos = path.path->labelPos.isNull()
|
||||||
? centroid(path.path) : ll2xy(path.labelPos);
|
? centroid(path.pp) : ll2xy(path.path->labelPos);
|
||||||
|
|
||||||
TextPointItem *item = new TextPointItem(pos.toPoint(), label, font, img,
|
TextPointItem *item = new TextPointItem(pos.toPoint(), &path.label,
|
||||||
color, hColor, 0);
|
font, img, color, hColor, 0);
|
||||||
if (item->isValid() && _rect.contains(item->boundingRect().toRect())
|
if (item->isValid() && _rect.contains(item->boundingRect().toRect())
|
||||||
&& !item->collides(textItems))
|
&& !item->collides(textItems))
|
||||||
textItems.append(item);
|
textItems.append(item);
|
||||||
@ -190,35 +172,37 @@ void RasterTile::processAreaLabels(QList<TextItem*> &textItems)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterTile::processLineLabels(QList<TextItem*> &textItems)
|
void RasterTile::processLineLabels(QList<TextItem*> &textItems,
|
||||||
|
QVector<RenderPath> &renderPaths)
|
||||||
{
|
{
|
||||||
const Style &s = style(_ratio);
|
const Style &s = style(_ratio);
|
||||||
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
|
QList<const Style::TextRender*> instructions(s.pathLabels(_zoom));
|
||||||
QSet<QString> set;
|
QSet<QByteArray> set;
|
||||||
|
bool limit;
|
||||||
|
|
||||||
for (int i = 0; i < instructions.size(); i++) {
|
for (int i = 0; i < instructions.size(); i++) {
|
||||||
const Style::TextRender *ri = instructions.at(i);
|
const Style::TextRender *ri = instructions.at(i);
|
||||||
|
|
||||||
for (int j = 0; j < _paths.size(); j++) {
|
for (int i = 0; i < renderPaths.size(); i++) {
|
||||||
MapData::Path &path = _paths[j];
|
RenderPath &path = renderPaths[i];
|
||||||
QString *label = 0;
|
const QByteArray *l = label(ri->key(), path.path->tags,
|
||||||
bool limit = false;
|
&limit);
|
||||||
|
|
||||||
if (!path.path.elementCount())
|
if (!l)
|
||||||
continue;
|
continue;
|
||||||
if (!ri->rule().match(path.closed, path.tags))
|
if (!ri->rule().match(path.path->closed, path.path->tags))
|
||||||
continue;
|
continue;
|
||||||
if (!(label = pathLabel(ri, path, &limit)))
|
if (limit && set.contains(*l))
|
||||||
continue;
|
|
||||||
if (limit && set.contains(path.label))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
TextPathItem *item = new TextPathItem(path.path, label, _rect,
|
path.label = *l;
|
||||||
|
|
||||||
|
TextPathItem *item = new TextPathItem(path.pp, &path.label, _rect,
|
||||||
&ri->font(), &ri->fillColor(), haloColor(ri));
|
&ri->font(), &ri->fillColor(), haloColor(ri));
|
||||||
if (item->isValid() && !item->collides(textItems)) {
|
if (item->isValid() && !item->collides(textItems)) {
|
||||||
textItems.append(item);
|
textItems.append(item);
|
||||||
if (limit)
|
if (limit)
|
||||||
set.insert(path.label);
|
set.insert(*l);
|
||||||
} else
|
} else
|
||||||
delete item;
|
delete item;
|
||||||
}
|
}
|
||||||
@ -262,28 +246,35 @@ QPainterPath RasterTile::painterPath(const Polygon &polygon, bool curve) const
|
|||||||
return path;
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<RasterTile::PathInstruction> RasterTile::pathInstructions()
|
QVector<RasterTile::PathInstruction> RasterTile::pathInstructions(
|
||||||
|
QVector<RenderPath> &renderPaths)
|
||||||
{
|
{
|
||||||
QCache<Key, QVector<const Style::PathRender *> > cache(8192);
|
QCache<Key, QList<const Style::PathRender *> > cache(8192);
|
||||||
QVector<PathInstruction> instructions;
|
QVector<PathInstruction> instructions;
|
||||||
const Style &s = style(_ratio);
|
const Style &s = style(_ratio);
|
||||||
QVector<const Style::PathRender*> *ri;
|
QList<const Style::PathRender*> *ri;
|
||||||
|
int i = 0;
|
||||||
for (int i = 0 ; i < _paths.size(); i++) {
|
|
||||||
MapData::Path &path = _paths[i];
|
|
||||||
|
|
||||||
|
for (QSet<MapData::Path>::const_iterator it = _paths.cbegin();
|
||||||
|
it != _paths.cend(); ++it) {
|
||||||
|
const MapData::Path &path = *it;
|
||||||
|
RenderPath &rp = renderPaths[i];
|
||||||
Key key(_zoom, path.closed, path.tags);
|
Key key(_zoom, path.closed, path.tags);
|
||||||
QVector<const Style::PathRender*> *cached = cache.object(key);
|
|
||||||
if (!cached) {
|
rp.path = &path;
|
||||||
ri = new QVector<const Style::PathRender*>(s.paths(_zoom,
|
|
||||||
|
if (!(ri = cache.object(key))) {
|
||||||
|
ri = new QList<const Style::PathRender*>(s.paths(_zoom,
|
||||||
path.closed, path.tags));
|
path.closed, path.tags));
|
||||||
for (int j = 0; j < ri->size(); j++)
|
for (int j = 0; j < ri->size(); j++)
|
||||||
instructions.append(PathInstruction(ri->at(j), &path));
|
instructions.append(PathInstruction(ri->at(j), &rp));
|
||||||
cache.insert(key, ri);
|
cache.insert(key, ri);
|
||||||
} else {
|
} else {
|
||||||
for (int j = 0; j < cached->size(); j++)
|
for (int j = 0; j < ri->size(); j++)
|
||||||
instructions.append(PathInstruction(cached->at(j), &path));
|
instructions.append(PathInstruction(ri->at(j), &rp));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(instructions.begin(), instructions.end());
|
std::sort(instructions.begin(), instructions.end());
|
||||||
@ -291,54 +282,30 @@ QVector<RasterTile::PathInstruction> RasterTile::pathInstructions()
|
|||||||
return instructions;
|
return instructions;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterTile::drawPaths(QPainter *painter)
|
void RasterTile::drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths)
|
||||||
{
|
{
|
||||||
QVector<PathInstruction> instructions(pathInstructions());
|
QVector<PathInstruction> instructions(pathInstructions(renderPaths));
|
||||||
const Style::PathRender *lri = 0;
|
|
||||||
|
|
||||||
QPixmap layer(_pixmap.size());
|
|
||||||
layer.setDevicePixelRatio(_ratio);
|
|
||||||
layer.fill(Qt::transparent);
|
|
||||||
|
|
||||||
QPainter lp(&layer);
|
|
||||||
lp.setRenderHint(QPainter::Antialiasing);
|
|
||||||
lp.translate(-_rect.x(), -_rect.y());
|
|
||||||
lp.setCompositionMode(QPainter::CompositionMode_Source);
|
|
||||||
|
|
||||||
for (int i = 0; i < instructions.size(); i++) {
|
for (int i = 0; i < instructions.size(); i++) {
|
||||||
PathInstruction &is = instructions[i];
|
const PathInstruction &is = instructions.at(i);
|
||||||
const Style::PathRender *ri = is.render();
|
const Style::PathRender *ri = is.render();
|
||||||
|
RenderPath *path = is.path();
|
||||||
|
|
||||||
if (lri && lri != ri) {
|
if (!path->pp.elementCount())
|
||||||
painter->drawPixmap(_rect.topLeft(), layer);
|
path->pp = painterPath(path->path->poly, ri->curve());
|
||||||
lp.fillRect(QRect(_rect.topLeft(), _pixmap.size()), Qt::transparent);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!is.path()->path.elementCount())
|
|
||||||
is.path()->path = painterPath(is.path()->poly, ri->curve());
|
|
||||||
|
|
||||||
if (ri->area()) {
|
|
||||||
lp.setPen(ri->pen(_zoom));
|
|
||||||
lp.setBrush(ri->brush());
|
|
||||||
lp.drawPath(is.path()->path);
|
|
||||||
lri = ri;
|
|
||||||
} else {
|
|
||||||
painter->setPen(ri->pen(_zoom));
|
painter->setPen(ri->pen(_zoom));
|
||||||
painter->setBrush(ri->brush());
|
painter->setBrush(ri->brush());
|
||||||
painter->drawPath(is.path()->path);
|
painter->drawPath(path->pp);
|
||||||
lri = 0;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lri)
|
|
||||||
painter->drawPixmap(_rect.topLeft(), layer);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterTile::render()
|
void RasterTile::render()
|
||||||
{
|
{
|
||||||
std::sort(_points.begin(), _points.end());
|
std::sort(_points.begin(), _points.end());
|
||||||
|
|
||||||
QList<TextItem*> textItems;
|
QList<TextItem*> textItems;
|
||||||
|
QVector<RenderPath> renderPaths(_paths.size());
|
||||||
|
|
||||||
_pixmap.setDevicePixelRatio(_ratio);
|
_pixmap.setDevicePixelRatio(_ratio);
|
||||||
_pixmap.fill(Qt::transparent);
|
_pixmap.fill(Qt::transparent);
|
||||||
@ -347,11 +314,11 @@ void RasterTile::render()
|
|||||||
painter.setRenderHint(QPainter::Antialiasing);
|
painter.setRenderHint(QPainter::Antialiasing);
|
||||||
painter.translate(-_rect.x(), -_rect.y());
|
painter.translate(-_rect.x(), -_rect.y());
|
||||||
|
|
||||||
drawPaths(&painter);
|
drawPaths(&painter, renderPaths);
|
||||||
|
|
||||||
processPointLabels(textItems);
|
processPointLabels(textItems);
|
||||||
processAreaLabels(textItems);
|
processAreaLabels(textItems, renderPaths);
|
||||||
processLineLabels(textItems);
|
processLineLabels(textItems, renderPaths);
|
||||||
drawTextItems(&painter, textItems);
|
drawTextItems(&painter, textItems);
|
||||||
|
|
||||||
//painter.setPen(Qt::red);
|
//painter.setPen(Qt::red);
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <QPixmap>
|
#include <QPixmap>
|
||||||
#include "map/projection.h"
|
#include "map/projection.h"
|
||||||
#include "map/transform.h"
|
#include "map/transform.h"
|
||||||
|
#include "map/textpointitem.h"
|
||||||
#include "style.h"
|
#include "style.h"
|
||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
|
|
||||||
@ -16,7 +17,7 @@ class RasterTile
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
RasterTile(const Projection &proj, const Transform &transform, int zoom,
|
RasterTile(const Projection &proj, const Transform &transform, int zoom,
|
||||||
const QRect &rect, qreal ratio, const QList<MapData::Path> &paths,
|
const QRect &rect, qreal ratio, const QSet<MapData::Path> &paths,
|
||||||
const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
|
const QList<MapData::Point> &points) : _proj(proj), _transform(transform),
|
||||||
_zoom(zoom), _rect(rect), _ratio(ratio),
|
_zoom(zoom), _rect(rect), _ratio(ratio),
|
||||||
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
|
_pixmap(rect.width() * ratio, rect.height() * ratio), _paths(paths),
|
||||||
@ -30,27 +31,35 @@ public:
|
|||||||
void render();
|
void render();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
struct RenderPath {
|
||||||
|
RenderPath() : path(0) {}
|
||||||
|
|
||||||
|
QPainterPath pp;
|
||||||
|
QString label;
|
||||||
|
const MapData::Path *path;
|
||||||
|
};
|
||||||
|
|
||||||
class PathInstruction
|
class PathInstruction
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
PathInstruction() : _render(0), _path(0) {}
|
PathInstruction() : _render(0), _path(0) {}
|
||||||
PathInstruction(const Style::PathRender *render, MapData::Path *path)
|
PathInstruction(const Style::PathRender *render, RenderPath *path)
|
||||||
: _render(render), _path(path) {}
|
: _render(render), _path(path) {}
|
||||||
|
|
||||||
bool operator<(const PathInstruction &other) const
|
bool operator<(const PathInstruction &other) const
|
||||||
{
|
{
|
||||||
if (_path->layer == other._path->layer)
|
if (_path->path->layer == other._path->path->layer)
|
||||||
return _render->zOrder() < other._render->zOrder();
|
return _render->zOrder() < other._render->zOrder();
|
||||||
else
|
else
|
||||||
return (_path->layer < other._path->layer);
|
return (_path->path->layer < other._path->path->layer);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Style::PathRender *render() const {return _render;}
|
const Style::PathRender *render() const {return _render;}
|
||||||
MapData::Path *path() {return _path;}
|
RenderPath *path() const {return _path;}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Style::PathRender *_render;
|
const Style::PathRender *_render;
|
||||||
MapData::Path *_path;
|
RenderPath *_path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Key {
|
struct Key {
|
||||||
@ -67,18 +76,32 @@ private:
|
|||||||
const QVector<MapData::Tag> &tags;
|
const QVector<MapData::Tag> &tags;
|
||||||
};
|
};
|
||||||
|
|
||||||
friend HASH_T qHash(const RasterTile::Key &key);
|
class PointItem : public TextPointItem
|
||||||
friend HASH_T qHash(const RasterTile::PathInstruction &pi);
|
{
|
||||||
|
public:
|
||||||
|
PointItem(const QPoint &point, QString *text, const QFont *font,
|
||||||
|
const QImage *img, const QColor *color, const QColor *haloColor)
|
||||||
|
: TextPointItem(point, text, font, img, color, haloColor, 0),
|
||||||
|
_label(text) {}
|
||||||
|
~PointItem() {delete _label;}
|
||||||
|
|
||||||
QVector<PathInstruction> pathInstructions();
|
private:
|
||||||
|
QString *_label;
|
||||||
|
};
|
||||||
|
|
||||||
|
friend HASH_T qHash(const RasterTile::Key &key);
|
||||||
|
|
||||||
|
QVector<PathInstruction> pathInstructions(QVector<RenderPath> &renderPaths);
|
||||||
QPointF ll2xy(const Coordinates &c) const
|
QPointF ll2xy(const Coordinates &c) const
|
||||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||||
void processPointLabels(QList<TextItem*> &textItems);
|
void processPointLabels(QList<TextItem*> &textItems);
|
||||||
void processAreaLabels(QList<TextItem*> &textItems);
|
void processAreaLabels(QList<TextItem*> &textItems,
|
||||||
void processLineLabels(QList<TextItem*> &textItems);
|
QVector<RenderPath> &renderPaths);
|
||||||
|
void processLineLabels(QList<TextItem*> &textItems,
|
||||||
|
QVector<RenderPath> &renderPaths);
|
||||||
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
||||||
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
|
||||||
void drawPaths(QPainter *painter);
|
void drawPaths(QPainter *painter, QVector<RenderPath> &renderPaths);
|
||||||
|
|
||||||
Projection _proj;
|
Projection _proj;
|
||||||
Transform _transform;
|
Transform _transform;
|
||||||
@ -86,8 +109,9 @@ private:
|
|||||||
QRect _rect;
|
QRect _rect;
|
||||||
qreal _ratio;
|
qreal _ratio;
|
||||||
QPixmap _pixmap;
|
QPixmap _pixmap;
|
||||||
QList<MapData::Path> _paths;
|
QSet<MapData::Path> _paths;
|
||||||
QList<MapData::Point> _points;
|
QList<MapData::Point> _points;
|
||||||
|
|
||||||
bool _valid;
|
bool _valid;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -432,10 +432,10 @@ Style::Style(const QString &path, qreal ratio)
|
|||||||
loadXml(":/mapsforge/default.xml", ratio);
|
loadXml(":/mapsforge/default.xml", ratio);
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
QList<const Style::PathRender *> Style::paths(int zoom, bool closed,
|
||||||
const QVector<MapData::Tag> &tags) const
|
const QVector<MapData::Tag> &tags) const
|
||||||
{
|
{
|
||||||
QVector<const PathRender*> ri;
|
QList<const PathRender*> ri;
|
||||||
|
|
||||||
for (int i = 0; i < _paths.size(); i++)
|
for (int i = 0; i < _paths.size(); i++)
|
||||||
if (_paths.at(i).rule().match(zoom, closed, tags))
|
if (_paths.at(i).rule().match(zoom, closed, tags))
|
||||||
|
@ -221,7 +221,7 @@ public:
|
|||||||
|
|
||||||
Style(const QString &path, qreal ratio);
|
Style(const QString &path, qreal ratio);
|
||||||
|
|
||||||
QVector<const PathRender *> paths(int zoom, bool closed,
|
QList<const PathRender *> paths(int zoom, bool closed,
|
||||||
const QVector<MapData::Tag> &tags) const;
|
const QVector<MapData::Tag> &tags) const;
|
||||||
QList<const TextRender*> pathLabels(int zoom) const;
|
QList<const TextRender*> pathLabels(int zoom) const;
|
||||||
QList<const TextRender*> pointLabels(int zoom) const;
|
QList<const TextRender*> pointLabels(int zoom) const;
|
||||||
|
@ -14,6 +14,7 @@ public:
|
|||||||
: _file(file), _offset(offset), _size(size), _pos(-1),
|
: _file(file), _offset(offset), _size(size), _pos(-1),
|
||||||
_blockNum(-1), _blockPos(-1) {}
|
_blockNum(-1), _blockPos(-1) {}
|
||||||
|
|
||||||
|
quint64 offset() const {return _offset;}
|
||||||
quint64 pos() const {return _pos;}
|
quint64 pos() const {return _pos;}
|
||||||
bool seek(quint64 pos);
|
bool seek(quint64 pos);
|
||||||
|
|
||||||
|
@ -175,7 +175,7 @@ void MapsforgeMap::draw(QPainter *painter, const QRectF &rect, Flags flags)
|
|||||||
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
if (QPixmapCache::find(key(_zoom, ttl), &pm))
|
||||||
painter->drawPixmap(ttl, pm);
|
painter->drawPixmap(ttl, pm);
|
||||||
else {
|
else {
|
||||||
QList<MapData::Path> paths;
|
QSet<MapData::Path> paths;
|
||||||
QList<MapData::Point> points;
|
QList<MapData::Point> points;
|
||||||
|
|
||||||
/* Add a "sub-pixel" margin to assure the tile areas do not
|
/* Add a "sub-pixel" margin to assure the tile areas do not
|
||||||
|
Loading…
x
Reference in New Issue
Block a user