From 320b04c3fadf617d5ef9f445d8522b55b915f57d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 22 May 2023 23:29:04 +0200 Subject: [PATCH] Added support for line "dy" parameter --- src/map/mapsforge/rastertile.cpp | 50 +++++++++++++++++++++++++++++++- src/map/mapsforge/style.cpp | 12 ++++++++ src/map/mapsforge/style.h | 4 ++- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/src/map/mapsforge/rastertile.cpp b/src/map/mapsforge/rastertile.cpp index aea46555..bfce1971 100644 --- a/src/map/mapsforge/rastertile.cpp +++ b/src/map/mapsforge/rastertile.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "common/programpaths.h" @@ -8,6 +9,8 @@ using namespace Mapsforge; #define TEXT_EXTENT 160 +static double limit = cos(deg2rad(170)); + static qreal area(const QPainterPath &polygon) { qreal area = 0; @@ -55,6 +58,47 @@ static const QColor *haloColor(const Style::TextRender *ti) ? &ti->strokeColor() : 0; } +static QPainterPath parallelPath(const QPainterPath &p, double dy) +{ + int n = p.elementCount() - 1; + QVector u(n); + QPainterPath h; + +#if QT_VERSION >= QT_VERSION_CHECK(5, 13, 0) + h.reserve(p.elementCount()); +#endif // QT 5.13 + + for (int k = 0; k < n; k++) { + qreal c = p.elementAt(k + 1).x - p.elementAt(k).x; + qreal s = p.elementAt(k + 1).y - p.elementAt(k).y; + qreal l = sqrt(c * c + s * s); + + u[k] = (l == 0) ? QPointF(0, 0) : QPointF(c / l, s / l); + + if (k == 0) + continue; + if (u.at(k).x() * u.at(k-1).x() + u.at(k).y() * u.at(k-1).y() < limit) + return p; + } + + h.moveTo(QPointF(p.elementAt(0).x - dy * u.at(0).y(), + p.elementAt(0).y + dy * u.at(0).x())); + + for (int k = 1; k < n; k++) { + qreal l = dy / (1 + u.at(k).x() * u.at(k-1).x() + + u.at(k).y() * u.at(k-1).y()); + QPainterPath::Element e(p.elementAt(k)); + + h.lineTo(QPointF(e.x - l * (u.at(k).y() + u.at(k-1).y()), + e.y + l * (u.at(k).x() + u.at(k-1).x()))); + } + + h.lineTo(QPointF(p.elementAt(n).x - dy * u.at(n-1).y(), + p.elementAt(n).y + dy * u.at(n-1).x())); + + return h; +} + void RasterTile::processPointLabels(const QList &points, QList &textItems) { @@ -306,13 +350,17 @@ void RasterTile::drawPaths(QPainter *painter, const QList &paths, if (path) { const Style::PathRender *ri = is.pathRender(); + qreal dy = ri->dy(_zoom); if (!path->pp.elementCount()) path->pp = painterPath(path->path->poly, ri->curve()); painter->setPen(ri->pen(_zoom)); painter->setBrush(ri->brush()); - painter->drawPath(path->pp); + if (dy != 0) + painter->drawPath(parallelPath(path->pp, dy)); + else + painter->drawPath(path->pp); } else { const Style::CircleRender *ri = is.circleRender(); qreal radius = ri->radius(_zoom); diff --git a/src/map/mapsforge/style.cpp b/src/map/mapsforge/style.cpp index 32b18538..49df83c3 100644 --- a/src/map/mapsforge/style.cpp +++ b/src/map/mapsforge/style.cpp @@ -245,6 +245,13 @@ void Style::line(QXmlStreamReader &reader, const Rule &rule) if (curve == "cubic") ri._curve = true; } + if (attr.hasAttribute("dy")) { + ri._dy = attr.value("dy").toDouble(&ok); + if (!ok) { + reader.raiseError("invalid dy value"); + return; + } + } if (ri.rule()._type == Rule::AnyType || ri.rule()._type == Rule::WayType) _paths.append(ri); @@ -689,6 +696,11 @@ QPen Style::PathRender::pen(int zoom) const return Qt::NoPen; } +qreal Style::PathRender::dy(int zoom) const +{ + return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _dy : _dy; +} + qreal Style::CircleRender::radius(int zoom) const { return (_scale && zoom >= 12) ? pow(1.5, zoom - 12) * _radius : _radius; diff --git a/src/map/mapsforge/style.h b/src/map/mapsforge/style.h index 69b11092..bff58dde 100644 --- a/src/map/mapsforge/style.h +++ b/src/map/mapsforge/style.h @@ -137,13 +137,14 @@ public: PathRender(const Rule &rule, int zOrder) : Render(rule), _zOrder(zOrder), _strokeWidth(0), _strokeCap(Qt::RoundCap), _strokeJoin(Qt::RoundJoin), _area(false), _curve(false), - _scale(Stroke) {} + _scale(Stroke), _dy(0) {} int zOrder() const {return _zOrder;} QPen pen(int zoom) const; const QBrush &brush() const {return _brush;} bool area() const {return _area;} bool curve() const {return _curve;} + qreal dy(int zoom) const; private: friend class Style; @@ -159,6 +160,7 @@ public: QBrush _brush; bool _area, _curve; Scale _scale; + qreal _dy; }; class CircleRender : public Render