From 4d33631844e2601c2df34cbeccd7f18ec22977c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sat, 10 May 2025 14:27:51 +0200 Subject: [PATCH] Render marine lines with the propper direction --- src/map/IMG/mapdata.h | 10 +++++++--- src/map/IMG/netfile.cpp | 2 +- src/map/IMG/rastertile.cpp | 11 +++++++---- src/map/IMG/rgnfile.cpp | 24 ++++++++++++++++++++++-- src/map/IMG/rgnfile.h | 1 + src/map/IMG/style.h | 2 ++ src/map/bitmapline.cpp | 20 ++++++++++++++++++++ src/map/bitmapline.h | 1 + 8 files changed, 61 insertions(+), 10 deletions(-) diff --git a/src/map/IMG/mapdata.h b/src/map/IMG/mapdata.h index 3920ef24..12c2c5e4 100644 --- a/src/map/IMG/mapdata.h +++ b/src/map/IMG/mapdata.h @@ -29,7 +29,12 @@ class MapData { public: struct Poly { - Poly() : oneway(false) {} + Poly() : flags(0) {} + + enum Flags { + OneWay = 1, + Invert = 2 + }; /* QPointF insted of Coordinates for performance reasons (no need to duplicate all the vectors for drawing). Note, that we do not want to @@ -40,7 +45,7 @@ public: Raster raster; quint32 type; RectC boundingRect; - bool oneway; + quint32 flags; bool operator<(const Poly &other) const {return type > other.type;} @@ -50,7 +55,6 @@ public: Point() : id(0), flags(0) {} enum Flags { - NoFlag = 0, ClassLabel = 1, }; diff --git a/src/map/IMG/netfile.cpp b/src/map/IMG/netfile.cpp index e37b27fe..c54e0560 100644 --- a/src/map/IMG/netfile.cpp +++ b/src/map/IMG/netfile.cpp @@ -480,7 +480,7 @@ bool NETFile::link(const SubDiv *subdiv, quint32 shift, Handle &hdl, if (lbl) linkLabel(hdl, linkOffset, lbl, lblHdl, poly.label); if ((linkInfo.flags >> 3) & 1) - poly.oneway = true; + poly.flags |= MapData::Poly::OneWay; lines->append(poly); diff --git a/src/map/IMG/rastertile.cpp b/src/map/IMG/rastertile.cpp index ccaadd3c..00f5882d 100644 --- a/src/map/IMG/rastertile.cpp +++ b/src/map/IMG/rastertile.cpp @@ -206,9 +206,12 @@ void RasterTile::drawLines(QPainter *painter, const MapData::Poly &poly = lines.at(i); const Style::Line &style = _data->style()->line(poly.type); - if (!style.img().isNull()) - BitmapLine::draw(painter, poly.points, style.img()); - else if (style.foreground() != Qt::NoPen) { + if (!style.img().isNull()) { + if (poly.flags & MapData::Poly::Invert) + BitmapLine::drawr(painter, poly.points, style.img()); + else + BitmapLine::draw(painter, poly.points, style.img()); + } else if (style.foreground() != Qt::NoPen) { painter->setPen(style.foreground()); painter->drawPolyline(poly.points); } @@ -383,7 +386,7 @@ void RasterTile::processStreetNames(const QList &lines, ? &style.text().color() : Style::isContourLine(poly.type) ? 0 : &textColor; const QColor *hColor = Style::isContourLine(poly.type) ? 0 : &haloColor; - const QImage *img = poly.oneway + const QImage *img = (poly.flags & MapData::Poly::OneWay) ? Style::isWaterLine(poly.type) ? &arrows[WATER] : &arrows[ROAD] : 0; const QString *label = poly.label.text().isEmpty() diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 8baed229..399d1db8 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -244,6 +244,22 @@ bool RGNFile::readLabel(Handle &hdl, LBLFile *lbl, Handle &lblHdl, return true; } +bool RGNFile::readLineInfo(Handle &hdl, quint32 size, MapData::Poly *line) const +{ + if (size == 1) { + quint32 val; + + if (!readUInt8(hdl, val)) + return false; + + if (((val >> 3) & 3) & 2) + line->flags |= MapData::Poly::Invert; + + return true; + } else + return (!size); +} + bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, void *object, LBLFile *lbl, Handle &lblHdl) const { @@ -251,6 +267,8 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, quint32 rs = 0; MapData::Poly *poly = (segmentType == Polygon) ? (MapData::Poly *) object : 0; + MapData::Poly *line = (segmentType == Line) + ? (MapData::Poly *) object : 0; MapData::Point *point = (segmentType == Point) ? (MapData::Point *) object : 0; @@ -289,6 +307,9 @@ bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType, if (point && Style::isLight(point->type)) readLightInfo(hdl, flags, rs, point); + if (line && Style::isMarineLine(line->type)) + readLineInfo(hdl, rs, line); + return seek(hdl, off + rs); } @@ -597,8 +618,7 @@ bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv, poly.type = (segmentType == Polygon) ? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8; if (segmentType == Line && type & 0x40) - poly.oneway = true; - + poly.flags |= MapData::Poly::OneWay; QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()), subdiv->lat() + LS(lat, 24-subdiv->bits())); diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index 47558dc8..76ed48cb 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -69,6 +69,7 @@ private: MapData::Point *point) const; bool readLightInfo(Handle &hdl, quint8 flags, quint32 size, MapData::Point *point) const; + bool readLineInfo(Handle &hdl, quint32 size, MapData::Poly *line) const; bool readLabel(Handle &hdl, LBLFile *lbl, Handle &lblHdl, quint8 flags, quint32 size, MapData::Point *point) const; bool readLclNavaid(Handle &hdl, quint32 size, diff --git a/src/map/IMG/style.h b/src/map/IMG/style.h index ff1efbfb..57f8a18b 100644 --- a/src/map/IMG/style.h +++ b/src/map/IMG/style.h @@ -154,6 +154,8 @@ public: {return (type >= 0x10100 && type < 0x10200);} static bool isMarinePoint(quint32 type) {return type >= 0x10100 && type < 0x10a00;} + static bool isMarineLine(quint32 type) + {return type >= 0x10400 && type < 0x10700;} static bool isMarina(quint32 type) {return type == 0x10703;} static bool hasColorset(quint32 type) diff --git a/src/map/bitmapline.cpp b/src/map/bitmapline.cpp index 49420510..4afb8360 100644 --- a/src/map/bitmapline.cpp +++ b/src/map/bitmapline.cpp @@ -53,6 +53,26 @@ void BitmapLine::draw(QPainter *painter, const QPolygonF &line, } } +void BitmapLine::drawr(QPainter *painter, const QPolygonF &line, + const QImage &img) +{ + int offset = 0; + + for (int i = line.size() - 1; i > 0; i--) { + QLineF segment(line.at(i).x(), line.at(i).y(), line.at(i-1).x(), + line.at(i-1).y()); + int len = qCeil(segment.length() * img.devicePixelRatio()); + + painter->save(); + painter->translate(segment.p1()); + painter->rotate(-segment.angle()); + painter->drawImage(0.0, -img.height()/2.0, img2line(img, len, offset)); + painter->restore(); + + offset = (len + offset) % img.width(); + } +} + void BitmapLine::draw(QPainter *painter, const QVector &lines, const QImage &img) { diff --git a/src/map/bitmapline.h b/src/map/bitmapline.h index fcaef143..4e95df64 100644 --- a/src/map/bitmapline.h +++ b/src/map/bitmapline.h @@ -11,6 +11,7 @@ class QPainterPath; namespace BitmapLine { void draw(QPainter *painter, const QPolygonF &line, const QImage &img); + void drawr(QPainter *painter, const QPolygonF &line, const QImage &img); void draw(QPainter *painter, const QVector &lines, const QImage &img); void draw(QPainter *painter, const QPainterPath &line, const QImage &img);