1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 05:34:47 +01:00

Properly match symbols to captions

This commit is contained in:
Martin Tůma 2023-06-10 08:11:18 +02:00
parent 5ddd63e697
commit 9afeaf672a
6 changed files with 105 additions and 54 deletions

View File

@ -106,40 +106,43 @@ void RasterTile::processPointLabels(const QList<MapData::Point> &points,
{ {
QList<const Style::TextRender*> labels(_style->pointLabels(_zoom)); QList<const Style::TextRender*> labels(_style->pointLabels(_zoom));
QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom)); QList<const Style::Symbol*> symbols(_style->pointSymbols(_zoom));
QList<PainterPoint> painterPoints; QList<PointText> items;
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);
const QByteArray *lbl = 0;
const Style::TextRender *ti = 0; const Style::TextRender *ti = 0;
const Style::Symbol *si = 0; const Style::Symbol *si = 0;
const QByteArray *lbl = 0;
for (int j = 0; j < symbols.size(); j++) {
const Style::Symbol *ri = symbols.at(j);
if (ri->rule().match(point.tags))
if (!si || si->priority() < ri->priority())
si = ri;
}
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 ((lbl = label(ri->key(), point.tags))) { if ((lbl = label(ri->key(), point.tags))) {
if (si && si->id() != ri->symbolId())
continue;
ti = ri; ti = ri;
break; break;
} }
} }
} }
for (int j = 0; j < symbols.size(); j++) {
const Style::Symbol *ri = symbols.at(j);
if (ri->rule().match(point.tags)) {
si = ri;
break;
}
}
if (ti || si) if (ti || si)
painterPoints.append(PainterPoint(&point, lbl, si, ti)); items.append(PointText(&point, lbl, si, ti));
} }
std::sort(painterPoints.begin(), painterPoints.end()); std::sort(items.begin(), items.end());
for (int i = 0; i < painterPoints.size(); i++) { for (int i = 0; i < items.size(); i++) {
const PainterPoint &p = painterPoints.at(i); const PointText &p = items.at(i);
const QImage *img = p.si ? &p.si->img() : 0; const QImage *img = p.si ? &p.si->img() : 0;
const QFont *font = p.ti ? &p.ti->font() : 0; const QFont *font = p.ti ? &p.ti->font() : 0;
const QColor *color = p.ti ? &p.ti->fillColor() : 0; const QColor *color = p.ti ? &p.ti->fillColor() : 0;
@ -159,6 +162,7 @@ void RasterTile::processAreaLabels(const QVector<PainterPath> &paths,
{ {
QList<const Style::TextRender*> labels(_style->areaLabels(_zoom)); QList<const Style::TextRender*> labels(_style->areaLabels(_zoom));
QList<const Style::Symbol*> symbols(_style->areaSymbols(_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);
@ -169,34 +173,43 @@ 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++) {
const Style::Symbol *ri = symbols.at(j);
if (ri->rule().match(path.path->closed, path.path->tags))
if (!si || si->priority() < ri->priority())
si = ri;
}
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.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())
continue;
ti = ri; ti = ri;
break; break;
}
} }
} }
for (int j = 0; j < symbols.size(); j++) { if (ti || si)
const Style::Symbol *ri = symbols.at(j); items.append(PathText(&path, lbl, si, ti));
if (ri->rule().match(path.path->tags)) { }
si = ri;
break;
}
}
if (!ti && !si) std::sort(items.begin(), items.end());
continue;
const QImage *img = si ? &si->img() : 0; for (int i = 0; i < items.size(); i++) {
const QFont *font = ti ? &ti->font() : 0; const PathText &p = items.at(i);
const QColor *color = ti ? &ti->fillColor() : 0; const QImage *img = p.si ? &p.si->img() : 0;
const QColor *hColor = ti ? haloColor(ti) : 0; const QFont *font = p.ti ? &p.ti->font() : 0;
QPointF pos = path.path->labelPos.isNull() const QColor *color = p.ti ? &p.ti->fillColor() : 0;
? centroid(path.pp) : ll2xy(path.path->labelPos); const QColor *hColor = p.ti ? haloColor(p.ti) : 0;
QPointF pos = p.p->path->labelPos.isNull()
? centroid(p.p->pp) : ll2xy(p.p->path->labelPos);
PointItem *item = new PointItem(pos.toPoint(), lbl, font, img, color, PointItem *item = new PointItem(pos.toPoint(), p.lbl, font, img, 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))
@ -211,6 +224,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;
QSet<QByteArray> set; QSet<QByteArray> set;
for (int i = 0; i < paths.size(); i++) { for (int i = 0; i < paths.size(); i++) {
@ -218,7 +232,6 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
const Style::TextRender *ti = 0; const Style::TextRender *ti = 0;
const Style::Symbol *si = 0; const Style::Symbol *si = 0;
const QByteArray *lbl = 0; const QByteArray *lbl = 0;
bool limit = false;
if (path.path->closed) if (path.path->closed)
continue; continue;
@ -234,37 +247,44 @@ void RasterTile::processLineLabels(const QVector<PainterPath> &paths,
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.path->tags)) { if (ri->rule().match(path.path->closed, path.path->tags)) {
si = ri; si = ri;
break; break;
} }
} }
if (!ti && !si) if (ti || si)
continue; items.append(PathText(&path, lbl, si, ti));
if (ti) { }
limit = (ti->key() == ID_ELE || ti->key() == ID_REF);
if (limit && set.contains(*lbl)) std::sort(items.begin(), items.end());
for (int i = 0; i < items.size(); i++) {
const PathText &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;
bool rotate = p.si ? p.si->rotate() : false;
bool limit = false;
if (p.ti) {
limit = (p.ti->key() == ID_ELE || p.ti->key() == ID_REF);
if (limit && set.contains(*p.lbl))
continue; continue;
} }
const QImage *img = si ? &si->img() : 0; PathItem *item = new PathItem(p.p->pp, p.lbl, img, _rect, font, color,
const QFont *font = ti ? &ti->font() : 0;
const QColor *color = ti ? &ti->fillColor() : 0;
const QColor *hColor = ti ? haloColor(ti) : 0;
bool rotate = si ? si->rotate() : false;
PathItem *item = new PathItem(path.pp, lbl, img, _rect, font, color,
hColor, rotate); 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(*lbl); set.insert(*p.lbl);
} else { } else {
delete item; delete item;
if (img && lbl) { if (img && p.lbl) {
PathItem *item = new PathItem(path.pp, 0, img, _rect, 0, 0, 0, PathItem *item = new PathItem(p.p->pp, 0, img, _rect, 0, 0, 0,
rotate); rotate);
if (item->isValid() && !item->collides(textItems)) if (item->isValid() && !item->collides(textItems))
textItems.append(item); textItems.append(item);

View File

@ -35,15 +35,15 @@ private:
const MapData::Path *path; const MapData::Path *path;
}; };
struct PainterPoint { struct PointText {
PainterPoint(const MapData::Point *p, const QByteArray *lbl, PointText(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) : p(p), lbl(lbl), ti(ti), si(si)
{ {
Q_ASSERT(si || ti); Q_ASSERT(si || ti);
} }
bool operator<(const PainterPoint &other) const bool operator<(const PointText &other) const
{ {
if (priority() == other.priority()) if (priority() == other.priority())
return p->id < other.p->id; return p->id < other.p->id;
@ -58,6 +58,26 @@ private:
const Style::Symbol *si; 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 Style::TextRender *ti;
const Style::Symbol *si;
};
class RenderInstruction class RenderInstruction
{ {
public: public:

View File

@ -421,6 +421,8 @@ void Style::text(QXmlStreamReader &reader, const MapData &data, const Rule &rule
return; return;
} }
} }
if (attr.hasAttribute("symbol-id"))
ri._symbolId = attr.value("symbol-id").toString();
ri._font.setFamily(fontFamily); ri._font.setFamily(fontFamily);
ri._font.setPixelSize(fontSize); ri._font.setPixelSize(fontSize);
@ -482,6 +484,8 @@ void Style::symbol(QXmlStreamReader &reader, const QString &dir, qreal ratio,
if (attr.value("rotate").toString() == "false") if (attr.value("rotate").toString() == "false")
ri._rotate = false; ri._rotate = false;
} }
if (attr.hasAttribute("id"))
ri._id = attr.value("id").toString();
ri._img = image(file, width, height, percent, ratio); ri._img = image(file, width, height, percent, ratio);

View File

@ -192,6 +192,7 @@ public:
: Render(rule), _priority(0), _fillColor(Qt::black), : Render(rule), _priority(0), _fillColor(Qt::black),
_strokeColor(Qt::black), _strokeWidth(0) {} _strokeColor(Qt::black), _strokeWidth(0) {}
const QString &symbolId() const {return _symbolId;}
const QFont &font() const {return _font;} const QFont &font() const {return _font;}
const QColor &fillColor() const {return _fillColor;} const QColor &fillColor() const {return _fillColor;}
const QColor &strokeColor() const {return _strokeColor;} const QColor &strokeColor() const {return _strokeColor;}
@ -202,6 +203,7 @@ public:
private: private:
friend class Style; friend class Style;
QString _symbolId;
int _priority; int _priority;
QColor _fillColor, _strokeColor; QColor _fillColor, _strokeColor;
qreal _strokeWidth; qreal _strokeWidth;
@ -212,15 +214,18 @@ public:
class Symbol : public Render class Symbol : public Render
{ {
public: public:
Symbol(const Rule &rule) : Render(rule), _priority(0), _rotate(true) {} Symbol(const Rule &rule)
: Render(rule), _priority(0), _rotate(true) {}
const QString &id() const {return _id;}
const QImage &img() const {return _img;} const QImage &img() const {return _img;}
int priority() const {return _priority;}
bool rotate() const {return _rotate;} bool rotate() const {return _rotate;}
int priority() const {return _priority;}
private: private:
friend class Style; friend class Style;
QString _id;
int _priority; int _priority;
bool _rotate; bool _rotate;
QImage _img; QImage _img;

View File

@ -382,5 +382,6 @@ void TextPathItem::paint(QPainter *painter) const
//painter->setBrush(Qt::NoBrush); //painter->setBrush(Qt::NoBrush);
//painter->setPen(Qt::red); //painter->setPen(Qt::red);
//painter->setRenderHint(QPainter::Antialiasing, false);
//painter->drawPath(_shape); //painter->drawPath(_shape);
} }

View File

@ -109,6 +109,7 @@ void TextPointItem::paint(QPainter *painter) const
} }
//painter->setPen(Qt::red); //painter->setPen(Qt::red);
//painter.setBrush(Qt::NoBrush);
//painter->setRenderHint(QPainter::Antialiasing, false); //painter->setRenderHint(QPainter::Antialiasing, false);
//painter->drawRect(_rect); //painter->drawRect(_rect);
} }