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

Added polygon labels rendering

This commit is contained in:
Martin Tůma 2021-04-11 11:37:43 +02:00
parent 983e68b880
commit a42709e6a2
5 changed files with 83 additions and 11 deletions

View File

@ -136,7 +136,7 @@ static qreal area(const QVector<QPointF> &polygon)
}
area /= 2.0;
return area;
return area;
}
static QPointF centroid(const QVector<QPointF> &polygon)

View File

@ -544,7 +544,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
QVector<unsigned> paths(rows);
quint32 blocks, unused, val, cnt = 0;
quint16 bitmap;
quint8 flags;
quint8 sb, flags;
QByteArray label, houseNumber, reference;
@ -565,13 +565,14 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
for (unsigned i = 0; i < paths[zoom - info.min]; i++) {
Path p;
qint32 lon = 0, lat = 0;
if (!(subfile.readVUInt32(unused) && subfile.readUInt16(bitmap)
&& subfile.readByte(flags)))
&& subfile.readByte(sb)))
return false;
p.layer = flags >> 4;
int tags = flags & 0x0F;
p.layer = sb >> 4;
int tags = sb & 0x0F;
if (!readTags(subfile, tags, _pathTags, p.tags))
return false;
@ -592,8 +593,7 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
p.reference = reference;
}
if (flags & 0x10) {
qint32 unused;
if (!(subfile.readVInt32(unused) && subfile.readVInt32(unused)))
if (!(subfile.readVInt32(lat) && subfile.readVInt32(lon)))
return false;
}
if (flags & 0x08) {
@ -607,6 +607,9 @@ bool MapData::readPaths(const VectorTile *tile, int zoom, QList<Path> *list)
if (!readPolygon(subfile, tile->pos, flags & 0x04, p.poly))
return false;
p.closed = isClosed(p.poly);
if (flags & 0x10)
p.labelPos = Coordinates(p.poly.first().first().lon() + MD(lon),
p.poly.first().first().lat() + MD(lat));
list->append(p);
}
@ -622,7 +625,7 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
int rows = info.max - info.min + 1;
QVector<unsigned> points(rows);
quint32 val, unused, cnt = 0;
quint8 flags;
quint8 sb, flags;
QByteArray label, houseNumber;
@ -647,10 +650,10 @@ bool MapData::readPoints(const VectorTile *tile, int zoom, QList<Point> *list)
Point p(Coordinates(tile->pos.lon() + MD(lon),
tile->pos.lat() + MD(lat)));
if (!subfile.readByte(flags))
if (!subfile.readByte(sb))
return false;
p.layer = flags >> 4;
int tags = flags & 0x0F;
p.layer = sb >> 4;
int tags = sb & 0x0F;
if (!readTags(subfile, tags, _pointTags, p.tags))
return false;

View File

@ -57,6 +57,7 @@ public:
QString label;
QString reference;
QVector<Tag> tags;
Coordinates labelPos;
int layer;
bool closed;

View File

@ -14,6 +14,36 @@ static const Style& style()
return s;
}
static qreal area(const QPainterPath &polygon)
{
qreal area = 0;
for (int i = 0; i < polygon.elementCount(); i++) {
int j = (i + 1) % polygon.elementCount();
area += polygon.elementAt(i).x * polygon.elementAt(j).y;
area -= polygon.elementAt(i).y * polygon.elementAt(j).x;
}
area /= 2.0;
return area;
}
static QPointF centroid(const QPainterPath &polygon)
{
qreal cx = 0, cy = 0;
qreal factor = 1.0 / (6.0 * area(polygon));
for (int i = 0; i < polygon.elementCount(); i++) {
int j = (i + 1) % polygon.elementCount();
qreal f = (polygon.elementAt(i).x * polygon.elementAt(j).y
- polygon.elementAt(j).x * polygon.elementAt(i).y);
cx += (polygon.elementAt(i).x + polygon.elementAt(j).x) * f;
cy += (polygon.elementAt(i).y + polygon.elementAt(j).y) * f;
}
return QPointF(cx * factor, cy * factor);
}
void RasterTile::processPoints(QList<TextItem*> &textItems)
{
const Style &s = style();
@ -59,6 +89,42 @@ void RasterTile::processPoints(QList<TextItem*> &textItems)
}
}
void RasterTile::processPolygonNames(const QRect &tileRect,
QList<TextItem*> &textItems)
{
const Style &s = style();
QSet<QString> set;
for (int i = 0; i < s.pointLabels().size(); i++) {
const Style::TextRender &ri = s.pointLabels().at(i);
for (int j = 0; j < _paths.size(); j++) {
const MapData::Path &path = _paths.at(j);
if (path.label.isEmpty())
continue;
if (!path.path.elementCount())
continue;
if (set.contains(path.label))
continue;
if (!ri.rule().match(_zoom, path.closed, path.tags))
continue;
QPointF pos = path.labelPos.isNull()
? centroid(path.path) : ll2xy(path.labelPos);
TextPointItem *item = new TextPointItem(pos.toPoint(), &path.label,
&ri.font(), 0, &ri.fillColor(), 0, false);
if (item->isValid() && tileRect.contains(item->boundingRect().toRect())
&& !item->collides(textItems)) {
textItems.append(item);
set.insert(path.label);
} else
delete item;
}
}
}
void RasterTile::processStreetNames(const QRect &tileRect,
QList<TextItem*> &textItems)
{
@ -173,6 +239,7 @@ void RasterTile::render()
drawPaths(&painter);
processPoints(textItems);
processPolygonNames(tileRect, textItems);
processStreetNames(tileRect, textItems);
drawTextItems(&painter, textItems);

View File

@ -72,6 +72,7 @@ private:
QPointF ll2xy(const Coordinates &c) const
{return _transform.proj2img(_proj.ll2xy(c));}
void processPoints(QList<TextItem*> &textItems);
void processPolygonNames(const QRect &tileRect, QList<TextItem*> &textItems);
void processStreetNames(const QRect &tileRect, QList<TextItem*> &textItems);
QPainterPath painterPath(const Polygon &polygon) const;
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);