From 325e83569c07d33d890cd449419f8960304dbba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Fri, 7 Feb 2020 22:10:06 +0100 Subject: [PATCH] Redesigned IMG caching (Cache encoded data rather than raw data) --- src/map/IMG/img.cpp | 78 +++++++++---- src/map/IMG/img.h | 19 +++- src/map/IMG/rgnfile.cpp | 226 ++++++++++++++----------------------- src/map/IMG/rgnfile.h | 84 +++++--------- src/map/IMG/style.cpp | 3 - src/map/IMG/subdiv.h | 146 +++++++++++++++++------- src/map/IMG/vectortile.cpp | 90 +++++++++++++-- src/map/IMG/vectortile.h | 7 +- src/map/imgmap.cpp | 10 +- 9 files changed, 381 insertions(+), 282 deletions(-) diff --git a/src/map/IMG/img.cpp b/src/map/IMG/img.cpp index 54426592..2bed58ae 100644 --- a/src/map/IMG/img.cpp +++ b/src/map/IMG/img.cpp @@ -4,23 +4,34 @@ #include "vectortile.h" #include "img.h" - -#define CACHE_SIZE 8388608 /* 8MB */ +#define CACHED_SUBDIVS_COUNT 2048 // ~32MB typedef QMap TileMap; -struct CTX +struct PolyCTX { - CTX(const RectC &rect, int bits, QList *polygons, - QList *lines, QList *points) + PolyCTX(const RectC &rect, int bits, QList *polygons, + QList *lines, QCache *polyCache) : rect(rect), bits(bits), polygons(polygons), lines(lines), - points(points) {} + polyCache(polyCache) {} const RectC ▭ int bits; QList *polygons; QList *lines; + QCache *polyCache; +}; + +struct PointCTX +{ + PointCTX(const RectC &rect, int bits, QList *points, + QCache > *pointCache) + : rect(rect), bits(bits), points(points), pointCache(pointCache) {} + + const RectC ▭ + int bits; QList *points; + QCache > *pointCache; }; static SubFile::Type tileType(const char str[3]) @@ -78,8 +89,9 @@ IMG::IMG(const QString &fileName) QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2))); _name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed(); _blockSize = 1 << (e1 + e2); - _blockCache.setMaxCost(CACHE_SIZE / _blockSize); + _polyCache.setMaxCost(CACHED_SUBDIVS_COUNT); + _pointCache.setMaxCost(CACHED_SUBDIVS_COUNT); // Read the FAT table quint8 flag; @@ -214,20 +226,28 @@ void IMG::clear() delete _style; _style = 0; - _blockCache.clear(); + _polyCache.clear(); + _pointCache.clear(); } -static bool cb(VectorTile *tile, void *context) +static bool polyCb(VectorTile *tile, void *context) { - CTX *ctx = (CTX*)context; - tile->objects(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->points); + PolyCTX *ctx = (PolyCTX*)context; + tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache); return true; } -void IMG::objects(const RectC &rect, int bits, QList *polygons, - QList *lines, QList *points) +static bool pointCb(VectorTile *tile, void *context) { - CTX ctx(rect, bits, polygons, lines, points); + PointCTX *ctx = (PointCTX*)context; + tile->points(ctx->rect, ctx->bits, ctx->points, ctx->pointCache); + return true; +} + +void IMG::polys(const RectC &rect, int bits, QList *polygons, + QList *lines) +{ + PolyCTX ctx(rect, bits, polygons, lines, &_polyCache); double min[2], max[2]; min[0] = rect.left(); @@ -235,7 +255,20 @@ void IMG::objects(const RectC &rect, int bits, QList *polygons, max[0] = rect.right(); max[1] = rect.top(); - _tileTree.Search(min, max, cb, &ctx); + _tileTree.Search(min, max, polyCb, &ctx); +} + +void IMG::points(const RectC &rect, int bits, QList *points) +{ + PointCTX ctx(rect, bits, points, &_pointCache); + double min[2], max[2]; + + min[0] = rect.left(); + min[1] = rect.bottom(); + max[0] = rect.right(); + max[1] = rect.top(); + + _tileTree.Search(min, max, pointCb, &ctx); } qint64 IMG::read(char *data, qint64 maxSize) @@ -261,16 +294,11 @@ template bool IMG::readValue(T &val) bool IMG::readBlock(int blockNum, QByteArray &data) { - QByteArray *block = _blockCache[blockNum]; - if (!block) { - if (!_file.seek((qint64)blockNum * (qint64)_blockSize)) - return false; - data.resize(_blockSize); - if (read(data.data(), _blockSize) < _blockSize) - return false; - _blockCache.insert(blockNum, new QByteArray(data)); - } else - data = *block; + if (!_file.seek((qint64)blockNum * (qint64)_blockSize)) + return false; + data.resize(_blockSize); + if (read(data.data(), _blockSize) < _blockSize) + return false; return true; } diff --git a/src/map/IMG/img.h b/src/map/IMG/img.h index 9ad5add5..6dd88ce9 100644 --- a/src/map/IMG/img.h +++ b/src/map/IMG/img.h @@ -12,6 +12,7 @@ class VectorTile; class SubFile; +class SubDiv; class IMG { @@ -24,6 +25,7 @@ public: QVector points; Label label; quint32 type; + RectC boundingRect; bool operator<(const Poly &other) const {return type > other.type;} @@ -42,6 +44,14 @@ public: {return id < other.id;} }; + struct Polys { + Polys() {} + Polys(const QList &polygons, const QList &lines) + : polygons(polygons), lines(lines) {} + + QList polygons; + QList lines; + }; IMG(const QString &fileName); ~IMG(); @@ -53,8 +63,9 @@ public: const QString &name() const {return _name;} const RectC &bounds() const {return _bounds;} - void objects(const RectC &rect, int bits, QList *polygons, - QList *lines, QList *points); + void polys(const RectC &rect, int bits, QList *polygons, + QList *lines); + void points(const RectC &rect, int bits, QList *points); const Style *style() const {return _style;} bool isValid() const {return _valid;} @@ -73,7 +84,6 @@ private: QFile _file; quint8 _key; int _blockSize; - QCache _blockCache; QString _name; RectC _bounds; @@ -81,6 +91,9 @@ private: SubFile *_typ; Style *_style; + QCache _polyCache; + QCache > _pointCache; + bool _valid; QString _errorString; }; diff --git a/src/map/IMG/rgnfile.cpp b/src/map/IMG/rgnfile.cpp index 5662a151..5105542d 100644 --- a/src/map/IMG/rgnfile.cpp +++ b/src/map/IMG/rgnfile.cpp @@ -39,7 +39,7 @@ bool RGNFile::skipClassFields(Handle &hdl) const } bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3], - Segment::Type type) const + SegmentType type) const { quint32 bitfield = 0xFFFFFFFF; @@ -53,7 +53,7 @@ bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3], quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3; switch (i) { case 5: - if (m == 1 && type == Segment::Point) { + if (m == 1 && type == Point) { quint16 u16; if (!readUInt16(hdl, u16)) return false; @@ -116,10 +116,15 @@ bool RGNFile::init(Handle &hdl) return true; } -bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, +bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv, + SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl, QList *polys) const { + const SubDiv::Segment &segment = (segmentType == Line) + ? subdiv->lines() : subdiv->polygons(); + + if (!segment.isValid()) + return true; if (!seek(hdl, segment.start())) return false; @@ -145,14 +150,14 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, if (!readUInt8(hdl, bitstreamInfo)) return false; - poly.type = (segment.type() == Segment::Polygon) + poly.type = (segmentType == Polygon) ? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8; QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); - RectC br(c, c); + poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); qint32 lonDelta, latDelta; @@ -164,14 +169,11 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); - br = br.united(c); + poly.boundingRect = poly.boundingRect.united(c); } if (!(stream.atEnd() && stream.flush())) return false; - if (!rect.intersects(br)) - continue; - if (lbl && (labelPtr & 0x3FFFFF)) { if (labelPtr & 0x800000) { quint32 lblOff; @@ -188,22 +190,25 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, return true; } -bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, - const SubDiv *subdiv, quint32 shift, const Segment &segment, LBLFile *lbl, - Handle &lblHdl, QList *polys, bool line) const +bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, + SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, + QList *polys) const { quint32 labelPtr, len; quint8 type, subtype; qint16 lon, lat; + const SubDiv::Segment &segment = (segmentType == Line) + ? subdiv->extLines() : subdiv->extPolygons(); + if (!segment.isValid()) + return true; if (!seek(hdl, segment.start())) return false; while (hdl.pos < (int)segment.end()) { IMG::Poly poly; QPoint pos; - RectC br; if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype) && readInt16(hdl, lon) && readInt16(hdl, lat) @@ -218,7 +223,8 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, (subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits()))); qint32 lonDelta, latDelta; - HuffmanStream stream(*this, hdl, len, _huffmanTable, line); + HuffmanStream stream(*this, hdl, len, _huffmanTable, + segmentType == Line); if (shift) { if (!stream.readOffset(lonDelta, latDelta)) @@ -227,7 +233,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, pos.y() | latDelta<<(32-subdiv->bits()-shift)); } Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); - br = RectC(c, c); + poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); while (stream.readNext(lonDelta, latDelta)) { @@ -236,7 +242,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, Coordinates c(toWGS32(pos.x()), toWGS32(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); - br = br.united(c); + poly.boundingRect = poly.boundingRect.united(c); } if (!(stream.atEnd() && stream.flush())) @@ -245,7 +251,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())), subdiv->lat() + ((qint32)lat<<(24-subdiv->bits()))); Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); - br = RectC(c, c); + poly.boundingRect = RectC(c, c); poly.points.append(QPointF(c.lon(), c.lat())); quint8 bitstreamInfo; @@ -261,7 +267,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, Coordinates c(toWGS24(pos.x()), toWGS24(pos.y())); poly.points.append(QPointF(c.lon(), c.lat())); - br = br.united(c); + poly.boundingRect = poly.boundingRect.united(c); } if (!(stream.atEnd() && stream.flush())) return false; @@ -271,13 +277,10 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, return false; if (subtype & 0x80 && !skipClassFields(hdl)) return false; - if (subtype & 0x40 && !skipLclFields(hdl, line ? _linesFlags - : _polygonsFlags, segment.type())) + if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line + ? _linesFlags : _polygonsFlags, segmentType)) return false; - if (!rect.intersects(br)) - continue; - if (lbl && (labelPtr & 0x3FFFFF)) poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF); @@ -287,14 +290,18 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl, return true; } -bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - const Segment &segment, LBLFile *lbl, Handle &lblHdl, +bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv, + SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, QList *points) const { quint8 type, subtype; qint16 lon, lat; quint32 labelPtr; + const SubDiv::Segment &segment = (segmentType == IndexedPoint) + ? subdiv->idxPoints() : subdiv->points(); + if (!segment.isValid()) + return true; if (!seek(hdl, segment.start())) return false; @@ -317,9 +324,6 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset), toWGS24(subdiv->lat() + latOffset)); - if (!rect.contains(point.coordinates)) - continue; - point.poi = labelPtr & 0x400000; if (lbl && (labelPtr & 0x3FFFFF)) { point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi); @@ -333,14 +337,17 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, return true; } -bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl, - const SubDiv *subdiv, const Segment &segment, LBLFile *lbl, +bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, Handle &lblHdl, QList *points) const { quint8 type, subtype; qint16 lon, lat; quint32 labelPtr; + const SubDiv::Segment &segment = subdiv->extPoints(); + + if (!segment.isValid()) + return true; if (!seek(hdl, segment.start())) return false; @@ -363,10 +370,12 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl, return false; if (subtype & 0x80 && !skipClassFields(hdl)) return false; - if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, segment.type())) + if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point)) return false; - if (!rect.contains(point.coordinates)) + // Discard NT points breaking style draw order logic (and causing huge + // performance drawback) + if (point.type == 0x11400) continue; point.poi = labelPtr & 0x400000; @@ -382,85 +391,13 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl, return true; } -void RGNFile::objects(const RectC &rect, const SubDiv *subdiv, - LBLFile *lbl, NETFile *net, QList *polygons, - QList *lines, QList *points) +QMap RGNFile::segments(Handle &hdl, + SubDiv *subdiv) const { - Handle rgnHdl, lblHdl, netHdl; + QMap ret; - if (!_init && !init(rgnHdl)) - return; - - QVector seg(segments(rgnHdl, subdiv)); - - for (int i = 0; i < seg.size(); i++) { - const Segment &segment = seg.at(i); - - if (segment.start() == segment.end()) - continue; - - switch (segment.type()) { - case Segment::Point: - case Segment::IndexedPoint: - if (points) - pointObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, - points); - break; - case Segment::Line: - if (lines) - polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net, - netHdl, lines); - break; - case Segment::Polygon: - if (polygons) - polyObjects(rect, rgnHdl, subdiv, segment, lbl, lblHdl, net, - netHdl, polygons); - break; - case Segment::RoadReference: - break; - } - } -} - -void RGNFile::extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift, - LBLFile *lbl, QList *polygons, QList *lines, - QList *points) -{ - Handle rgnHdl, lblHdl; - - if (!_init && !init(rgnHdl)) - return; - if (polygons && subdiv->polygonsOffset() != subdiv->polygonsEnd()) { - quint32 start = _polygonsOffset + subdiv->polygonsOffset(); - quint32 end = subdiv->polygonsEnd() - ? _polygonsOffset + subdiv->polygonsEnd() - : _polygonsOffset + _polygonsSize; - extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end, - Segment::Polygon), lbl, lblHdl, polygons, false); - } - if (lines && subdiv->linesOffset() != subdiv->linesEnd()) { - quint32 start = _linesOffset + subdiv->linesOffset(); - quint32 end = subdiv->linesEnd() - ? _linesOffset + subdiv->linesEnd() - : _linesOffset + _linesSize; - extPolyObjects(rect, rgnHdl, subdiv, shift, Segment(start, end, - Segment::Line), lbl, lblHdl, lines, true); - } - if (points && subdiv->pointsOffset() != subdiv->pointsEnd()) { - quint32 start = _pointsOffset + subdiv->pointsOffset(); - quint32 end = subdiv->pointsEnd() - ? _pointsOffset + subdiv->pointsEnd() - : _pointsOffset + _pointsSize; - extPointObjects(rect, rgnHdl, subdiv, Segment(start, end, - Segment::Point), lbl, lblHdl, points); - } -} - -QVector RGNFile::segments(Handle &hdl, const SubDiv *subdiv) - const -{ if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F)) - return QVector(); + return ret; quint32 offset = _offset + subdiv->offset(); @@ -470,57 +407,66 @@ QVector RGNFile::segments(Handle &hdl, const SubDiv *subdiv) no++; if (!seek(hdl, offset)) - return QVector(); + return ret; - QVector ret; quint32 start = offset + 2 * (no - 1); + quint32 ls = 0; + SegmentType lt = (SegmentType)0; quint16 po; int cnt = 0; for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) { if (subdiv->objects() & mask) { if (cnt) { - if (!readUInt16(hdl, po)) - return QVector(); + if (!readUInt16(hdl, po) || !po) + return QMap(); start = offset + po; } - if (!ret.isEmpty()) - ret.last().setEnd(start); - ret.append(Segment(start, (Segment::Type)mask)); + if (ls) + ret.insert(lt, SubDiv::Segment(ls, start)); + + lt = (SegmentType)mask; + ls = start; cnt++; } } - ret.last().setEnd(subdiv->end() ? _offset + subdiv->end() : _offset + _size); + ret.insert(lt, SubDiv::Segment(ls, subdiv->end() + ? _offset + subdiv->end() : _offset + _size)); return ret; } -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment) +bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const { - QString type; - switch (segment.type()) { - case RGNFile::Segment::Point: - type = "Point"; - break; - case RGNFile::Segment::IndexedPoint: - type = "IndexedPoint"; - break; - case RGNFile::Segment::Line: - type = "Line"; - break; - case RGNFile::Segment::Polygon: - type = "Polygon"; - break; - case RGNFile::Segment::RoadReference: - type = "RoadReference"; - break; + QMap seg(segments(hdl, subdiv)); + SubDiv::Segment extPoints, extLines, extPolygons; + + if (subdiv->extPointsOffset() != subdiv->extPointsEnd()) { + quint32 start = _pointsOffset + subdiv->extPointsOffset(); + quint32 end = subdiv->extPointsEnd() + ? _pointsOffset + subdiv->extPointsEnd() + : _pointsOffset + _pointsSize; + extPoints = SubDiv::Segment(start, end); + } + if (subdiv->extPolygonsOffset() != subdiv->extPolygonsEnd()) { + quint32 start = _polygonsOffset + subdiv->extPolygonsOffset(); + quint32 end = subdiv->extPolygonsEnd() + ? _polygonsOffset + subdiv->extPolygonsEnd() + : _polygonsOffset + _polygonsSize; + extPolygons = SubDiv::Segment(start, end); + } + if (subdiv->extLinesOffset() != subdiv->extLinesEnd()) { + quint32 start = _linesOffset + subdiv->extLinesOffset(); + quint32 end = subdiv->extLinesEnd() + ? _linesOffset + subdiv->extLinesEnd() + : _linesOffset + _linesSize; + extLines = SubDiv::Segment(start, end); } - dbg.nospace() << "Segment(" << segment.start() << ", " << segment.end() - - segment.start() << ", " << type << ")"; + subdiv->init(seg.value(Point), seg.value(IndexedPoint), seg.value(Line), + seg.value(Polygon), seg.value(RoadReference), extPoints, extLines, + extPolygons); - return dbg.space(); + return true; } -#endif // QT_NO_DEBUG diff --git a/src/map/IMG/rgnfile.h b/src/map/IMG/rgnfile.h index d1533a5b..f9336385 100644 --- a/src/map/IMG/rgnfile.h +++ b/src/map/IMG/rgnfile.h @@ -12,6 +12,14 @@ class NETFile; class RGNFile : public SubFile { public: + enum SegmentType { + Point = 0x1, + IndexedPoint = 0x2, + Line = 0x4, + Polygon = 0x8, + RoadReference = 0x10 + }; + RGNFile(IMG *img) : SubFile(img), _offset(0), _size(0), _polygonsOffset(0), _polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0), @@ -21,65 +29,29 @@ public: _linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false) {clearFlags();} - void objects(const RectC &rect, const SubDiv *subdiv, - LBLFile *lbl, NETFile *net, QList *polygons, - QList *lines, QList *points); - void extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift, - LBLFile *lbl, QList *polygons, QList *lines, - QList *points); - -private: - class Segment { - public: - enum Type { - Point = 0x1, - IndexedPoint = 0x2, - Line = 0x4, - Polygon = 0x8, - RoadReference = 0x10 - }; - - Segment() : _start(0), _end(0), _type(Point) {} - Segment(quint32 start, Type type) - : _start(start), _end(0), _type(type) {} - Segment(quint32 start, quint32 end, Type type) - : _start(start), _end(end), _type(type) {} - - void setEnd(quint32 end) {_end = end;} - - quint32 start() const {return _start;} - quint32 end() const {return _end;} - Type type() const {return _type;} - - private: - quint32 _start; - quint32 _end; - Type _type; - }; - + bool initialized() const {return _init;} bool init(Handle &hdl); - QVector segments(Handle &hdl, const SubDiv *subdiv) const; - bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net, - Handle &netHdl, QList *polys) const; - bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - const Segment &segment, LBLFile *lbl, Handle &lblHdl, - QList *points) const; - bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - quint32 shift, const Segment &segment, LBLFile *lbl, Handle &lblHdl, - QList *polys, bool line) const; - bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv, - const Segment &segment, LBLFile *lbl, Handle &lblHdl, - QList *points) const; + bool polyObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType, + LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl, + QList *polys) const; + bool pointObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType, + LBLFile *lbl, Handle &lblHdl, QList *points) const; + bool extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift, + SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, + QList *polys) const; + bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl, + Handle &lblHdl, QList *points) const; + bool subdivInit(Handle &hdl, SubDiv *subdiv) const; + +private: + QMap segments(Handle &hdl, SubDiv *subdiv) + const; void clearFlags(); - bool skipClassFields(Handle &hdl) const; - bool skipLclFields(Handle &hdl, const quint32 flags[3], - Segment::Type type) const; - - friend QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment); + bool skipLclFields(Handle &hdl, const quint32 flags[3], SegmentType type) + const; quint32 _offset; quint32 _size; @@ -99,8 +71,4 @@ private: bool _init; }; -#ifndef QT_NO_DEBUG -QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment); -#endif // QT_NO_DEBUG - #endif // RGNFILE_H diff --git a/src/map/IMG/style.cpp b/src/map/IMG/style.cpp index 8a6c38dc..5b38d96c 100644 --- a/src/map/IMG/style.cpp +++ b/src/map/IMG/style.cpp @@ -939,9 +939,6 @@ Style::Style(SubFile *typ) if (typ) parseTYPFile(typ); - - // Override stuff breaking the style display logic - _points[0x11400] = Point(None); } const Style::Line &Style::line(quint32 type) const diff --git a/src/map/IMG/subdiv.h b/src/map/IMG/subdiv.h index dd2f7d31..36956898 100644 --- a/src/map/IMG/subdiv.h +++ b/src/map/IMG/subdiv.h @@ -7,55 +7,123 @@ class SubDiv { public: - SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects) - : _offset(offset), _end(0), _lon(lon), _lat(lat), _bits(bits), - _objects(objects), _polygonsOffset(0), _polygonsEnd(0), _linesOffset(0), - _linesEnd(0), _pointsOffset(0), _pointsEnd(0) {} - void setEnd(quint32 end) {_end = end;} + class Segment { + public: + Segment() : _start(0), _end(0) {} + Segment(quint32 start, quint32 end) : _start(start), _end(end) {} + + bool isValid() const {return (_end > _start);} + + quint32 start() const {return _start;} + quint32 end() const {return _end;} + + private: + quint32 _start, _end; + }; + + SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects) + : _lon(lon), _lat(lat), _bits(bits), _init(false) + { + _tre.objects = objects; + _tre.offset = offset; + _tre.end = 0; + + _tre.polygonsOffset = 0; + _tre.polygonsEnd = 0; + _tre.linesOffset = 0; + _tre.linesEnd = 0; + _tre.pointsOffset = 0; + _tre.pointsEnd = 0; + } + void setEnd(quint32 end) {_tre.end = end;} + void setExtOffsets(quint32 polygon, quint32 line, quint32 point) + { + _tre.polygonsOffset = polygon; + _tre.linesOffset = line; + _tre.pointsOffset = point; + } + void setExtEnds(quint32 polygon, quint32 line, quint32 point) + { + _tre.polygonsEnd = polygon; + _tre.linesEnd = line; + _tre.pointsEnd = point; + } + + void init(const Segment &points, const Segment &idxPoints, + const Segment &lines, const Segment &polygons, + const Segment &roadReferences, const Segment &extPoints, + const Segment &extLines, const Segment &extPolygons) + { + _rgn.points = points; + _rgn.idxPoints = idxPoints; + _rgn.lines = lines; + _rgn.polygons = polygons; + _rgn.roadReferences = roadReferences; + _rgn.extPoints = extPoints; + _rgn.extLines = extLines; + _rgn.extPolygons = extPolygons; + _init = true; + } + bool initialized() const {return _init;} - quint32 offset() const {return _offset;} - quint32 end() const {return _end;} qint32 lon() const {return _lon;} qint32 lat() const {return _lat;} quint8 bits() const {return _bits;} - quint8 objects() const {return _objects;} - // Extended types objects (TRE7) - void setExtOffsets(quint32 polygon, quint32 line, quint32 point) - {_polygonsOffset = polygon; _linesOffset = line; _pointsOffset = point;} - void setExtEnds(quint32 polygon, quint32 line, quint32 point) - {_polygonsEnd = polygon; _linesEnd = line; _pointsEnd = point;} + // Valid only after initialization + const Segment &points() const {return _rgn.points;} + const Segment &idxPoints() const {return _rgn.idxPoints;} + const Segment &lines() const {return _rgn.lines;} + const Segment &polygons() const {return _rgn.polygons;} + const Segment &extPoints() const {return _rgn.extPoints;} + const Segment &extLines() const {return _rgn.extLines;} + const Segment &extPolygons() const {return _rgn.extPolygons;} - quint32 polygonsOffset() const {return _polygonsOffset;} - quint32 polygonsEnd() const {return _polygonsEnd;} - quint32 linesOffset() const {return _linesOffset;} - quint32 linesEnd() const {return _linesEnd;} - quint32 pointsOffset() const {return _pointsOffset;} - quint32 pointsEnd() const {return _pointsEnd;} + // Valid only until initialization + quint8 objects() const {return _tre.objects;} + quint32 offset() const {return _tre.offset;} + quint32 end() const {return _tre.end;} + quint32 extPolygonsOffset() const {return _tre.polygonsOffset;} + quint32 extPolygonsEnd() const {return _tre.polygonsEnd;} + quint32 extLinesOffset() const {return _tre.linesOffset;} + quint32 extLinesEnd() const {return _tre.linesEnd;} + quint32 extPointsOffset() const {return _tre.pointsOffset;} + quint32 extPointsEnd() const {return _tre.pointsEnd;} private: - quint32 _offset; - quint32 _end; + struct TRE + { + quint8 objects; + quint32 offset; + quint32 end; + + quint32 polygonsOffset; + quint32 polygonsEnd; + quint32 linesOffset; + quint32 linesEnd; + quint32 pointsOffset; + quint32 pointsEnd; + }; + + struct RGN + { + Segment points; + Segment idxPoints; + Segment lines; + Segment polygons; + Segment roadReferences; + Segment extPoints; + Segment extLines; + Segment extPolygons; + }; + qint32 _lon, _lat; quint8 _bits; - quint8 _objects; - - quint32 _polygonsOffset; - quint32 _polygonsEnd; - quint32 _linesOffset; - quint32 _linesEnd; - quint32 _pointsOffset; - quint32 _pointsEnd; + bool _init; + union { + TRE _tre; + RGN _rgn; + }; }; -#ifndef QT_NO_DEBUG -inline QDebug operator<<(QDebug dbg, const SubDiv &subdiv) -{ - Coordinates c(toWGS24(subdiv.lon()), toWGS24(subdiv.lat())); - dbg.nospace() << "SubDiv(" << c << ", " << subdiv.offset() - << ", " << subdiv.end() << ", " << subdiv.objects() << ")"; - return dbg.space(); -} -#endif // QT_NO_DEBUG - #endif // SUBDIV_H diff --git a/src/map/IMG/vectortile.cpp b/src/map/IMG/vectortile.cpp index b4a46244..e10a2792 100644 --- a/src/map/IMG/vectortile.cpp +++ b/src/map/IMG/vectortile.cpp @@ -1,5 +1,23 @@ #include "vectortile.h" + +static void copyPolys(const RectC &rect, QList *src, + QList *dst) +{ + for (int i = 0; i < src->size(); i++) + if (rect.intersects(src->at(i).boundingRect)) + dst->append(src->at(i)); +} + +static void copyPoints(const RectC &rect, QList *src, + QList *dst) +{ + for (int j = 0; j < src->size(); j++) + if (rect.contains(src->at(j).coordinates)) + dst->append(src->at(j)); +} + + SubFile *VectorTile::file(SubFile::Type type) { switch (type) { @@ -70,17 +88,75 @@ bool VectorTile::initGMP() return true; } -void VectorTile::objects(const RectC &rect, int bits, - QList *polygons, QList *lines, - QList *points) const +void VectorTile::polys(const RectC &rect, int bits, QList *polygons, + QList *lines, QCache *polyCache) + const { + SubFile::Handle rgnHdl, lblHdl, netHdl; + + if (!_rgn->initialized() && !_rgn->init(rgnHdl)) + return; + QList subdivs = _tre->subdivs(rect, bits); for (int i = 0; i < subdivs.size(); i++) { - const SubDiv *subdiv = subdivs.at(i); - quint32 shift = _tre->shift(subdiv->bits()); + SubDiv *subdiv = subdivs.at(i); - _rgn->objects(rect, subdiv, _lbl, _net, polygons, lines, points); - _rgn->extObjects(rect, subdiv, shift, _lbl, polygons, lines, points); + IMG::Polys *polys = polyCache->object(subdiv); + if (!polys) { + quint32 shift = _tre->shift(subdiv->bits()); + QList p, l; + + if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv)) + continue; + + _rgn->polyObjects(rgnHdl, subdiv, RGNFile::Polygon, _lbl, lblHdl, + _net, netHdl, &p); + _rgn->polyObjects(rgnHdl, subdiv, RGNFile::Line, _lbl, lblHdl, + _net, netHdl, &l); + _rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Polygon, _lbl, + lblHdl, &p); + _rgn->extPolyObjects(rgnHdl, subdiv, shift, RGNFile::Line, _lbl, + lblHdl, &l); + + copyPolys(rect, &p, polygons); + copyPolys(rect, &l, lines); + polyCache->insert(subdiv, new IMG::Polys(p, l)); + } else { + copyPolys(rect, &(polys->polygons), polygons); + copyPolys(rect, &(polys->lines), lines); + } + } +} + +void VectorTile::points(const RectC &rect, int bits, QList *points, + QCache > *pointCache) const +{ + SubFile::Handle rgnHdl, lblHdl; + + if (!_rgn->initialized() && !_rgn->init(rgnHdl)) + return; + + QList subdivs = _tre->subdivs(rect, bits); + for (int i = 0; i < subdivs.size(); i++) { + SubDiv *subdiv = subdivs.at(i); + + QList *pl = pointCache->object(subdiv); + if (!pl) { + QList p; + + if (!subdiv->initialized() && !_rgn->subdivInit(rgnHdl, subdiv)) + continue; + + _rgn->pointObjects(rgnHdl, subdiv, RGNFile::Point, _lbl, lblHdl, + &p); + _rgn->pointObjects(rgnHdl, subdiv, RGNFile::IndexedPoint, _lbl, + lblHdl, &p); + _rgn->extPointObjects(rgnHdl, subdiv, _lbl, lblHdl, &p); + + copyPoints(rect, &p, points); + pointCache->insert(subdiv, new QList(p)); + } else + copyPoints(rect, pl, points); } } diff --git a/src/map/IMG/vectortile.h b/src/map/IMG/vectortile.h index b5d517df..76f39061 100644 --- a/src/map/IMG/vectortile.h +++ b/src/map/IMG/vectortile.h @@ -24,8 +24,11 @@ public: SubFile *file(SubFile::Type type); SubFile *addFile(IMG *img, SubFile::Type type); - void objects(const RectC &rect, int bits, QList *polygons, - QList *lines, QList *points) const; + void polys(const RectC &rect, int bits, QList *polygons, + QList *lines, QCache *polyCache) + const; + void points(const RectC &rect, int bits, QList *points, + QCache > *pointCache) const; static bool isTileFile(SubFile::Type type) { diff --git a/src/map/imgmap.cpp b/src/map/imgmap.cpp index c838cf4e..038c145b 100644 --- a/src/map/imgmap.cpp +++ b/src/map/imgmap.cpp @@ -322,7 +322,6 @@ Coordinates IMGMap::xy2ll(const QPointF &p) return _projection.xy2ll(_transform.img2proj(p)); } - void IMGMap::drawPolygons(QPainter *painter, const QList &polygons) { for (int n = 0; n < _img.style()->drawOrder().size(); n++) { @@ -585,13 +584,14 @@ void IMGMap::draw(QPainter *painter, const QRectF &rect, Flags flags) RectD polyRect(_transform.img2proj(ttl), _transform.img2proj( QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE))); - _img.objects(polyRect.toRectC(_projection, 4), _zoom, - &(tile.polygons()), &(tile.lines()), 0); + _img.polys(polyRect.toRectC(_projection, 4), _zoom, + &(tile.polygons()), &(tile.lines())); + RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT, ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x() + TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT))); - _img.objects(pointRect.toRectC(_projection, 4), _zoom, - 0, 0, &(tile.points())); + _img.points(pointRect.toRectC(_projection, 4), _zoom, + &(tile.points())); } } }