1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-28 13:41:16 +01:00

Improved shields layout algorithm

This commit is contained in:
Martin Tůma 2019-07-13 08:36:04 +02:00
parent a20fd3e474
commit c1f36e5fbb
2 changed files with 68 additions and 36 deletions

View File

@ -20,6 +20,9 @@
#define TEXT_EXTENT 256 #define TEXT_EXTENT 256
#define LINE_TEXT_MIN_ZOOM 22 #define LINE_TEXT_MIN_ZOOM 22
#define AREA(rect) \
(rect.size().width() * rect.size().height())
class RasterTile class RasterTile
{ {
public: public:
@ -35,13 +38,14 @@ public:
QList<IMG::Poly> &lines() {return _lines;} QList<IMG::Poly> &lines() {return _lines;}
QList<IMG::Point> &points() {return _points;} QList<IMG::Point> &points() {return _points;}
void load() void render()
{ {
QList<TextItem*> textItems; QList<TextItem*> textItems;
_map->processPolygons(_polygons); _map->processPolygons(_polygons);
_map->processPoints(_points, textItems); _map->processPoints(_points, textItems);
_map->processLines(_lines, _xy, textItems); _map->processLines(_lines, QRect(_xy, QSize(TILE_SIZE, TILE_SIZE)),
textItems);
_img.fill(Qt::transparent); _img.fill(Qt::transparent);
@ -53,6 +57,8 @@ public:
_map->drawPolygons(&painter, _polygons); _map->drawPolygons(&painter, _polygons);
_map->drawLines(&painter, _lines); _map->drawLines(&painter, _lines);
_map->drawTextItems(&painter, textItems); _map->drawTextItems(&painter, textItems);
//painter.setPen(Qt::red);
//painter.drawRect(QRect(_xy, QSize(TILE_SIZE, TILE_SIZE)));
qDeleteAll(textItems); qDeleteAll(textItems);
} }
@ -338,11 +344,9 @@ void IMGMap::processPolygons(QList<IMG::Poly> &polygons)
} }
} }
void IMGMap::processLines(QList<IMG::Poly> &lines, const QPoint &tile, void IMGMap::processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems) QList<TextItem*> &textItems)
{ {
QRect tileRect(tile, QSize(TILE_SIZE, TILE_SIZE));
qStableSort(lines); qStableSort(lines);
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
@ -353,6 +357,13 @@ void IMGMap::processLines(QList<IMG::Poly> &lines, const QPoint &tile,
} }
} }
processStreetNames(lines, tileRect, textItems);
processShields(lines, tileRect, textItems);
}
void IMGMap::processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems)
{
if (_zoom >= LINE_TEXT_MIN_ZOOM) { if (_zoom >= LINE_TEXT_MIN_ZOOM) {
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
IMG::Poly &poly = lines[i]; IMG::Poly &poly = lines[i];
@ -379,51 +390,68 @@ void IMGMap::processLines(QList<IMG::Poly> &lines, const QPoint &tile,
delete item; delete item;
} }
} }
}
void IMGMap::processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems)
{
for (int type = Label::Shield::USInterstate; type <= Label::Shield::Oval; for (int type = Label::Shield::USInterstate; type <= Label::Shield::Oval;
type++) { type++) {
if (minShieldZoom(static_cast<Label::Shield::Type>(type)) > _zoom) if (minShieldZoom(static_cast<Label::Shield::Type>(type)) > _zoom)
continue; continue;
QSet<Label::Shield> shields; QHash<Label::Shield, QPolygonF> shields;
QHash<Label::Shield, const Label::Shield*> sp;
for (int i = 0; i < lines.size(); i++) { for (int i = 0; i < lines.size(); i++) {
const IMG::Poly &poly = lines.at(i); const IMG::Poly &poly = lines.at(i);
const Label::Shield &shield = poly.label.shield(); const Label::Shield &shield = poly.label.shield();
if (shield.type() != type || !Style::isMajorRoad(poly.type)) if (!shield.isValid() || shield.type() != type
|| !Style::isMajorRoad(poly.type))
continue; continue;
if (poly.label.shield().isValid() && !shields.contains(shield)) { QPolygonF &p = shields[shield];
bool valid = false; for (int j = 0; j < poly.points.size(); j++)
int idx = poly.points.size()/2, inc = 0, sign = 1; p.append(poly.points.at(j));
TextPointItem *item = new TextPointItem( sp.insert(shield, &shield);
poly.points.at(idx).toPoint(), &shield.text(), poiFont(), }
0, &shieldColor, shieldBgColor(shield.type()));
while (1) { for (QHash<Label::Shield, QPolygonF>::const_iterator it
if (!item->collides(textItems) = shields.constBegin(); it != shields.constEnd(); ++it) {
&& tileRect.contains(item->boundingRect().toRect())) { const QPolygonF &p = it.value();
valid = true; QRectF rect(p.boundingRect() & tileRect);
break; if (qSqrt(AREA(rect)) < qSqrt(AREA(tileRect)) / 8)
} continue;
inc++;
sign = (sign < 0) ? 1 : -1;
idx += inc * sign;
if (!(idx >= 0 && idx < poly.points.size())) QMap<qreal, int> map;
break; QPointF center = rect.center();
for (int j = 0; j < p.size(); j++) {
item->setPos(poly.points.at(idx).toPoint()); QLineF l(p.at(j), center);
} map.insert(l.length(), j);
if (valid) {
textItems.append(item);
shields.insert(shield);
} else
delete item;
} }
TextPointItem *item = new TextPointItem(
p.at(map.first()).toPoint(), &(sp.value(it.key())->text()),
poiFont(), 0, &shieldColor, shieldBgColor(it.key().type()));
bool valid = false;
QMap<qreal, int>::const_iterator jt = map.constBegin();
while (true) {
if (!item->collides(textItems)
&& tileRect.contains(item->boundingRect().toRect())) {
valid = true;
break;
}
if (++jt == map.constEnd())
break;
item->setPos(p.at(jt.value()).toPoint());
}
if (valid)
textItems.append(item);
else
delete item;
} }
} }
} }
@ -470,7 +498,7 @@ void IMGMap::processPoints(QList<IMG::Point> &points,
static void render(RasterTile &tile) static void render(RasterTile &tile)
{ {
tile.load(); tile.render();
} }
void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags)

View File

@ -50,9 +50,13 @@ private:
void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems); void drawTextItems(QPainter *painter, const QList<TextItem*> &textItems);
void processPolygons(QList<IMG::Poly> &polygons); void processPolygons(QList<IMG::Poly> &polygons);
void processLines(QList<IMG::Poly> &lines, const QPoint &tile, void processLines(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems); QList<TextItem*> &textItems);
void processPoints(QList<IMG::Point> &points, QList<TextItem*> &textItems); void processPoints(QList<IMG::Point> &points, QList<TextItem*> &textItems);
void processShields(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems);
void processStreetNames(QList<IMG::Poly> &lines, const QRect &tileRect,
QList<TextItem*> &textItems);
IMG _img; IMG _img;
int _zoom; int _zoom;