mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-23 19:25:54 +01:00
Unified point and areal labels processing
This commit is contained in:
parent
7c59998f96
commit
62651666e1
@ -613,8 +613,8 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
|
|||||||
paths.reserve(paths[zoom - info.min]);
|
paths.reserve(paths[zoom - info.min]);
|
||||||
|
|
||||||
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
|
||||||
Path p;
|
|
||||||
qint32 lon = 0, lat = 0;
|
qint32 lon = 0, lat = 0;
|
||||||
|
Path p(subfile.pos());
|
||||||
|
|
||||||
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
|
||||||
&& subfile.readByte(sb)))
|
&& subfile.readByte(sb)))
|
||||||
|
@ -46,6 +46,9 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
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;
|
||||||
|
@ -16,9 +16,10 @@ using namespace Mapsforge;
|
|||||||
|
|
||||||
static double LIMIT = cos(deg2rad(170));
|
static double LIMIT = cos(deg2rad(170));
|
||||||
|
|
||||||
static bool rectNearPolygon(const QPainterPath &path, const QRectF &rect)
|
static bool rectNearPolygon(const QRectF &tileRect, const QPainterPath &path,
|
||||||
|
const QRectF &rect)
|
||||||
{
|
{
|
||||||
return (path.boundingRect().contains(rect)
|
return ((tileRect.contains(rect) || path.boundingRect().contains(rect))
|
||||||
&& (path.contains(rect.topLeft()) || path.contains(rect.topRight())
|
&& (path.contains(rect.topLeft()) || path.contains(rect.topRight())
|
||||||
|| path.contains(rect.bottomLeft()) || path.contains(rect.bottomRight())));
|
|| path.contains(rect.bottomLeft()) || path.contains(rect.bottomRight())));
|
||||||
}
|
}
|
||||||
@ -100,12 +101,14 @@ static QPainterPath parallelPath(const QPainterPath &p, double dy)
|
|||||||
return h;
|
return h;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RasterTile::processPointLabels(const QList<MapData::Point> &points,
|
void RasterTile::processLabels(const QList<MapData::Point> &points,
|
||||||
QList<TextItem*> &textItems) const
|
const QVector<PainterPath> &paths, QList<TextItem*> &textItems) const
|
||||||
{
|
{
|
||||||
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
|
QList<Label> items;
|
||||||
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
|
QList<const Style::TextRender*> pointLabels(_style->pointLabels(_zoom));
|
||||||
QList<PointText> items;
|
QList<const Style::Symbol*> pointSymbols(_style->pointSymbols(_zoom));
|
||||||
|
QList<const Style::TextRender*> areaLabels(_style->areaLabels(_zoom));
|
||||||
|
QList<const Style::Symbol*> areaSymbols(_style->areaSymbols(_zoom));
|
||||||
|
|
||||||
for (int i = 0; i < points.size(); i++) {
|
for (int i = 0; i < points.size(); i++) {
|
||||||
const MapData::Point &point = points.at(i);
|
const MapData::Point &point = points.at(i);
|
||||||
@ -113,16 +116,16 @@ void RasterTile::processPointLabels(const QList<MapData::Point> &points,
|
|||||||
const Style::Symbol *si = 0;
|
const Style::Symbol *si = 0;
|
||||||
const QByteArray *lbl = 0;
|
const QByteArray *lbl = 0;
|
||||||
|
|
||||||
for (int j = 0; j < symbols.size(); j++) {
|
for (int j = 0; j < pointSymbols.size(); j++) {
|
||||||
const Style::Symbol *ri = symbols.at(j);
|
const Style::Symbol *ri = pointSymbols.at(j);
|
||||||
if (ri->rule().match(point.tags)) {
|
if (ri->rule().match(point.tags)) {
|
||||||
si = ri;
|
si = ri;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < labels.size(); j++) {
|
for (int j = 0; j < pointLabels.size(); j++) {
|
||||||
const Style::TextRender *ri = labels.at(j);
|
const Style::TextRender *ri = pointLabels.at(j);
|
||||||
if (ri->rule().match(point.tags)) {
|
if (ri->rule().match(point.tags)) {
|
||||||
if ((lbl = label(ri->key(), point.tags))) {
|
if ((lbl = label(ri->key(), point.tags))) {
|
||||||
if (!si || si->id() == ri->symbolId()) {
|
if (!si || si->id() == ri->symbolId()) {
|
||||||
@ -134,34 +137,9 @@ void RasterTile::processPointLabels(const QList<MapData::Point> &points,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ti || si)
|
if (ti || si)
|
||||||
items.append(PointText(&point, lbl, si, ti));
|
items.append(Label(&point, lbl, si, ti));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(items.begin(), items.end());
|
|
||||||
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
|
||||||
const PointText &p = items.at(i);
|
|
||||||
const QImage *img = p.si ? &p.si->img() : 0;
|
|
||||||
const QFont *font = p.ti ? &p.ti->font() : 0;
|
|
||||||
const QColor *color = p.ti ? &p.ti->fillColor() : 0;
|
|
||||||
const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
|
|
||||||
|
|
||||||
PointItem *item = new PointItem(ll2xy(p.p->coordinates).toPoint(),
|
|
||||||
p.lbl, font, img, color, hColor);
|
|
||||||
if (item->isValid() && !item->collides(textItems))
|
|
||||||
textItems.append(item);
|
|
||||||
else
|
|
||||||
delete item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void RasterTile::processAreaLabels(const QVector<PainterPath> &paths,
|
|
||||||
QList<TextItem*> &textItems) const
|
|
||||||
{
|
|
||||||
QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
|
|
||||||
QList<const Style::Symbol*> symbols(_style->areaSymbols(_zoom));
|
|
||||||
QList<PathText> items;
|
|
||||||
|
|
||||||
for (int i = 0; i < paths.size(); i++) {
|
for (int i = 0; i < paths.size(); i++) {
|
||||||
const PainterPath &path = paths.at(i);
|
const PainterPath &path = paths.at(i);
|
||||||
const Style::TextRender *ti = 0;
|
const Style::TextRender *ti = 0;
|
||||||
@ -171,16 +149,16 @@ void RasterTile::processAreaLabels(const QVector<PainterPath> &paths,
|
|||||||
if (!path.path->closed)
|
if (!path.path->closed)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
for (int j = 0; j < symbols.size(); j++) {
|
for (int j = 0; j < areaSymbols.size(); j++) {
|
||||||
const Style::Symbol *ri = symbols.at(j);
|
const Style::Symbol *ri = areaSymbols.at(j);
|
||||||
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||||
si = ri;
|
si = ri;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int j = 0; j < labels.size(); j++) {
|
for (int j = 0; j < areaLabels.size(); j++) {
|
||||||
const Style::TextRender *ri = labels.at(j);
|
const Style::TextRender *ri = areaLabels.at(j);
|
||||||
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
if (ri->rule().match(path.path->closed, path.path->tags)) {
|
||||||
if ((lbl = label(ri->key(), path.path->tags))) {
|
if ((lbl = label(ri->key(), path.path->tags))) {
|
||||||
if (!si || si->id() == ri->symbolId()) {
|
if (!si || si->id() == ri->symbolId()) {
|
||||||
@ -192,27 +170,36 @@ void RasterTile::processAreaLabels(const QVector<PainterPath> &paths,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ti || si)
|
if (ti || si)
|
||||||
items.append(PathText(&path, lbl, si, ti));
|
items.append(Label(&path, lbl, si, ti));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(items.begin(), items.end());
|
std::sort(items.begin(), items.end());
|
||||||
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
const PathText &p = items.at(i);
|
const Label &l = items.at(i);
|
||||||
const QImage *img = p.si ? &p.si->img() : 0;
|
const QImage *img = l.si ? &l.si->img() : 0;
|
||||||
const QFont *font = p.ti ? &p.ti->font() : 0;
|
const QFont *font = l.ti ? &l.ti->font() : 0;
|
||||||
const QColor *color = p.ti ? &p.ti->fillColor() : 0;
|
const QColor *color = l.ti ? &l.ti->fillColor() : 0;
|
||||||
const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
|
const QColor *hColor = l.ti ? haloColor(l.ti) : 0;
|
||||||
|
|
||||||
QPointF pos = p.p->path->labelPos.isNull()
|
if (l.point) {
|
||||||
? centroid(p.p->pp) : ll2xy(p.p->path->labelPos);
|
PointItem *item = new PointItem(ll2xy(l.point->coordinates).toPoint(),
|
||||||
PointItem *item = new PointItem(pos.toPoint(), p.lbl, font, img, color,
|
l.lbl, font, img, color, hColor);
|
||||||
hColor);
|
if (item->isValid() && !item->collides(textItems))
|
||||||
if (item->isValid() && rectNearPolygon(p.p->pp, item->boundingRect())
|
textItems.append(item);
|
||||||
&& !item->collides(textItems))
|
else
|
||||||
textItems.append(item);
|
delete item;
|
||||||
else
|
} else {
|
||||||
delete item;
|
QPointF pos = l.path->path->labelPos.isNull()
|
||||||
|
? centroid(l.path->pp) : ll2xy(l.path->path->labelPos);
|
||||||
|
PointItem *item = new PointItem(pos.toPoint(), l.lbl, font, img,
|
||||||
|
color, hColor);
|
||||||
|
if (item->isValid() && rectNearPolygon(_rect, l.path->pp,
|
||||||
|
item->boundingRect()) && !item->collides(textItems))
|
||||||
|
textItems.append(item);
|
||||||
|
else
|
||||||
|
delete item;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -221,7 +208,7 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
|
|||||||
{
|
{
|
||||||
QList<const Style::TextRender*> labels(_style->pathLabels(_zoom));
|
QList<const Style::TextRender*> labels(_style->pathLabels(_zoom));
|
||||||
QList<const Style::Symbol*> symbols(_style->lineSymbols(_zoom));
|
QList<const Style::Symbol*> symbols(_style->lineSymbols(_zoom));
|
||||||
QList<PathText> items;
|
QList<Label> items;
|
||||||
QSet<QByteArray> set;
|
QSet<QByteArray> set;
|
||||||
|
|
||||||
for (int i = 0; i < paths.size(); i++) {
|
for (int i = 0; i < paths.size(); i++) {
|
||||||
@ -254,57 +241,57 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ti || si)
|
if (ti || si)
|
||||||
items.append(PathText(&path, lbl, si, ti));
|
items.append(Label(&path, lbl, si, ti));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::sort(items.begin(), items.end());
|
std::sort(items.begin(), items.end());
|
||||||
|
|
||||||
for (int i = 0; i < items.size(); i++) {
|
for (int i = 0; i < items.size(); i++) {
|
||||||
const PathText &p = items.at(i);
|
const Label &l = items.at(i);
|
||||||
const QImage *img = p.si ? &p.si->img() : 0;
|
const QImage *img = l.si ? &l.si->img() : 0;
|
||||||
const QFont *font = p.ti ? &p.ti->font() : 0;
|
const QFont *font = l.ti ? &l.ti->font() : 0;
|
||||||
const QColor *color = p.ti ? &p.ti->fillColor() : 0;
|
const QColor *color = l.ti ? &l.ti->fillColor() : 0;
|
||||||
const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
|
const QColor *hColor = l.ti ? haloColor(l.ti) : 0;
|
||||||
bool rotate = p.si ? p.si->rotate() : false;
|
bool rotate = l.si ? l.si->rotate() : false;
|
||||||
bool limit = false;
|
bool limit = false;
|
||||||
|
|
||||||
if (p.ti) {
|
if (l.ti) {
|
||||||
limit = (p.ti->key() == ID_ELE || p.ti->key() == ID_REF
|
limit = (l.ti->key() == ID_ELE || l.ti->key() == ID_REF
|
||||||
|| (!p.si && p.ti->shield()));
|
|| (!l.si && l.ti->shield()));
|
||||||
if (limit && set.contains(*p.lbl))
|
if (limit && set.contains(*l.lbl))
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!p.si && p.ti && p.ti->shield()) {
|
if (!l.si && l.ti && l.ti->shield()) {
|
||||||
if (p.ti && p.lbl && set.contains(*p.lbl))
|
if (l.ti && l.lbl && set.contains(*l.lbl))
|
||||||
continue;
|
continue;
|
||||||
if (p.p->pp.length() < _rect.width() / 3.0)
|
if (l.path->pp.length() < _rect.width() / 3.0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QPointF pos = p.p->pp.pointAtPercent(0.5);
|
QPointF pos = l.path->pp.pointAtPercent(0.5);
|
||||||
|
|
||||||
PointItem *item = new PointItem(pos.toPoint(), p.lbl, font, color,
|
PointItem *item = new PointItem(pos.toPoint(), l.lbl, font, color,
|
||||||
hColor);
|
hColor);
|
||||||
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);
|
||||||
if (p.ti && p.lbl)
|
if (l.ti && l.lbl)
|
||||||
set.insert(*p.lbl);
|
set.insert(*l.lbl);
|
||||||
} else
|
} else
|
||||||
delete item;
|
delete item;
|
||||||
} else {
|
} else {
|
||||||
PathItem *item = new PathItem(p.p->pp, p.lbl, img, _rect, font,
|
PathItem *item = new PathItem(l.path->pp, l.lbl, img, _rect, font,
|
||||||
color, hColor, rotate);
|
color, hColor, rotate);
|
||||||
if (item->isValid() && !item->collides(textItems)) {
|
if (item->isValid() && !item->collides(textItems)) {
|
||||||
textItems.append(item);
|
textItems.append(item);
|
||||||
if (limit)
|
if (limit)
|
||||||
set.insert(*p.lbl);
|
set.insert(*l.lbl);
|
||||||
} else {
|
} else {
|
||||||
delete item;
|
delete item;
|
||||||
|
|
||||||
if (img && p.lbl) {
|
if (img && l.lbl) {
|
||||||
PathItem *item = new PathItem(p.p->pp, 0, img, _rect, 0, 0,
|
PathItem *item = new PathItem(l.path->pp, 0, img, _rect, 0,
|
||||||
0, rotate);
|
0, 0, rotate);
|
||||||
if (item->isValid() && !item->collides(textItems))
|
if (item->isValid() && !item->collides(textItems))
|
||||||
textItems.append(item);
|
textItems.append(item);
|
||||||
else
|
else
|
||||||
@ -431,6 +418,7 @@ void RasterTile::drawPaths(QPainter *painter, const QList<MapData::Path> &paths,
|
|||||||
hillShadingInstructions(instructions);
|
hillShadingInstructions(instructions);
|
||||||
std::sort(instructions.begin(), instructions.end());
|
std::sort(instructions.begin(), instructions.end());
|
||||||
|
|
||||||
|
qDebug() << instructions.size();
|
||||||
for (int i = 0; i < instructions.size(); i++) {
|
for (int i = 0; i < instructions.size(); i++) {
|
||||||
const RenderInstruction &is = instructions.at(i);
|
const RenderInstruction &is = instructions.at(i);
|
||||||
PainterPath *path = is.path();
|
PainterPath *path = is.path();
|
||||||
@ -543,8 +531,7 @@ void RasterTile::render()
|
|||||||
|
|
||||||
drawPaths(&painter, paths, points, renderPaths);
|
drawPaths(&painter, paths, points, renderPaths);
|
||||||
|
|
||||||
processPointLabels(points, textItems);
|
processLabels(points, renderPaths, textItems);
|
||||||
processAreaLabels(renderPaths, textItems);
|
|
||||||
processLineLabels(renderPaths, textItems);
|
processLineLabels(renderPaths, textItems);
|
||||||
drawTextItems(&painter, textItems);
|
drawTextItems(&painter, textItems);
|
||||||
|
|
||||||
|
@ -43,44 +43,34 @@ private:
|
|||||||
const MapData::Path *path;
|
const MapData::Path *path;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct PointText {
|
struct Label {
|
||||||
PointText(const MapData::Point *p, const QByteArray *lbl,
|
Label(const MapData::Point *p, const QByteArray *lbl,
|
||||||
const Style::Symbol *si, const Style::TextRender *ti)
|
const Style::Symbol *si, const Style::TextRender *ti)
|
||||||
: p(p), lbl(lbl), ti(ti), si(si)
|
: point(p), path(0), lbl(lbl), ti(ti), si(si)
|
||||||
|
{
|
||||||
|
Q_ASSERT(si || ti);
|
||||||
|
}
|
||||||
|
Label(const PainterPath *p, const QByteArray *lbl,
|
||||||
|
const Style::Symbol *si, const Style::TextRender *ti)
|
||||||
|
: point(0), path(p), lbl(lbl), ti(ti), si(si)
|
||||||
{
|
{
|
||||||
Q_ASSERT(si || ti);
|
Q_ASSERT(si || ti);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool operator<(const PointText &other) const
|
bool operator<(const Label &other) const
|
||||||
{
|
{
|
||||||
|
quint64 id = point ? point->id : path->path->id;
|
||||||
|
quint64 oid = other.point ? other.point->id : other.path->path->id;
|
||||||
|
|
||||||
if (priority() == other.priority())
|
if (priority() == other.priority())
|
||||||
return p->id < other.p->id;
|
return id < oid;
|
||||||
else
|
else
|
||||||
return (priority() > other.priority());
|
return (priority() > other.priority());
|
||||||
}
|
}
|
||||||
int priority() const {return si ? si->priority() : ti->priority();}
|
int priority() const {return si ? si->priority() : ti->priority();}
|
||||||
|
|
||||||
const MapData::Point *p;
|
const MapData::Point *point;
|
||||||
const QByteArray *lbl;
|
const PainterPath *path;
|
||||||
const Style::TextRender *ti;
|
|
||||||
const Style::Symbol *si;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct PathText {
|
|
||||||
PathText(const PainterPath *p, const QByteArray *lbl,
|
|
||||||
const Style::Symbol *si, const Style::TextRender *ti)
|
|
||||||
: p(p), lbl(lbl), ti(ti), si(si)
|
|
||||||
{
|
|
||||||
Q_ASSERT(si || ti);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool operator<(const PathText &other) const
|
|
||||||
{
|
|
||||||
return (priority() > other.priority());
|
|
||||||
}
|
|
||||||
int priority() const {return si ? si->priority() : ti->priority();}
|
|
||||||
|
|
||||||
const PainterPath *p;
|
|
||||||
const QByteArray *lbl;
|
const QByteArray *lbl;
|
||||||
const Style::TextRender *ti;
|
const Style::TextRender *ti;
|
||||||
const Style::Symbol *si;
|
const Style::Symbol *si;
|
||||||
@ -208,10 +198,8 @@ private:
|
|||||||
{return _transform.proj2img(_proj.ll2xy(c));}
|
{return _transform.proj2img(_proj.ll2xy(c));}
|
||||||
Coordinates xy2ll(const QPointF &p) const
|
Coordinates xy2ll(const QPointF &p) const
|
||||||
{return _proj.xy2ll(_transform.img2proj(p));}
|
{return _proj.xy2ll(_transform.img2proj(p));}
|
||||||
void processPointLabels(const QList<MapData::Point> &points,
|
void processLabels(const QList<MapData::Point> &points,
|
||||||
QList<TextItem*> &textItems) const;
|
const QVector<PainterPath> &paths, QList<TextItem*> &textItems) const;
|
||||||
void processAreaLabels(const QVector<PainterPath> &paths,
|
|
||||||
QList<TextItem*> &textItems) const;
|
|
||||||
void processLineLabels(const QVector<PainterPath> &paths,
|
void processLineLabels(const QVector<PainterPath> &paths,
|
||||||
QList<TextItem*> &textItems) const;
|
QList<TextItem*> &textItems) const;
|
||||||
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
QPainterPath painterPath(const Polygon &polygon, bool curve) const;
|
||||||
|
Loading…
Reference in New Issue
Block a user