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

Redesigned IMG caching

(Cache encoded data rather than raw data)
This commit is contained in:
Martin Tůma 2020-02-07 22:10:06 +01:00
parent df1be4aeb9
commit 325e83569c
9 changed files with 381 additions and 282 deletions

View File

@ -4,23 +4,34 @@
#include "vectortile.h"
#include "img.h"
#define CACHE_SIZE 8388608 /* 8MB */
#define CACHED_SUBDIVS_COUNT 2048 // ~32MB
typedef QMap<QString, VectorTile*> TileMap;
struct CTX
struct PolyCTX
{
CTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
PolyCTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QCache<const SubDiv*, IMG::Polys> *polyCache)
: rect(rect), bits(bits), polygons(polygons), lines(lines),
points(points) {}
polyCache(polyCache) {}
const RectC &rect;
int bits;
QList<IMG::Poly> *polygons;
QList<IMG::Poly> *lines;
QCache<const SubDiv*, IMG::Polys> *polyCache;
};
struct PointCTX
{
PointCTX(const RectC &rect, int bits, QList<IMG::Point> *points,
QCache<const SubDiv*, QList<IMG::Point> > *pointCache)
: rect(rect), bits(bits), points(points), pointCache(pointCache) {}
const RectC &rect;
int bits;
QList<IMG::Point> *points;
QCache<const SubDiv*, QList<IMG::Point> > *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<Poly> *polygons,
QList<Poly> *lines, QList<Point> *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<Poly> *polygons,
QList<Poly> *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<Poly> *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<Point> *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<class T> 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;
}

View File

@ -12,6 +12,7 @@
class VectorTile;
class SubFile;
class SubDiv;
class IMG
{
@ -24,6 +25,7 @@ public:
QVector<QPointF> 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<Poly> &polygons, const QList<Poly> &lines)
: polygons(polygons), lines(lines) {}
QList<Poly> polygons;
QList<Poly> 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<Poly> *polygons,
QList<Poly> *lines, QList<Point> *points);
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
QList<Poly> *lines);
void points(const RectC &rect, int bits, QList<Point> *points);
const Style *style() const {return _style;}
bool isValid() const {return _valid;}
@ -73,7 +84,6 @@ private:
QFile _file;
quint8 _key;
int _blockSize;
QCache<int, QByteArray> _blockCache;
QString _name;
RectC _bounds;
@ -81,6 +91,9 @@ private:
SubFile *_typ;
Style *_style;
QCache<const SubDiv*, Polys> _polyCache;
QCache<const SubDiv*, QList<Point> > _pointCache;
bool _valid;
QString _errorString;
};

View File

@ -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<IMG::Poly> *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<IMG::Poly> *polys, bool line) const
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *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<IMG::Point> *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<IMG::Point> *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<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
SubDiv *subdiv) const
{
Handle rgnHdl, lblHdl, netHdl;
QMap<SegmentType, SubDiv::Segment> ret;
if (!_init && !init(rgnHdl))
return;
QVector<Segment> 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<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *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::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
const
{
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F))
return QVector<Segment>();
return ret;
quint32 offset = _offset + subdiv->offset();
@ -470,57 +407,66 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
no++;
if (!seek(hdl, offset))
return QVector<Segment>();
return ret;
QVector<Segment> 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<Segment>();
if (!readUInt16(hdl, po) || !po)
return QMap<RGNFile::SegmentType, SubDiv::Segment>();
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<RGNFile::SegmentType, SubDiv::Segment> 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

View File

@ -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<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points);
void extObjects(const RectC &rect, const SubDiv *subdiv, quint32 shift,
LBLFile *lbl, QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *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<Segment> 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<IMG::Poly> *polys) const;
bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const;
bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
quint32 shift, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys, bool line) const;
bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Point> *points) const;
bool polyObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl,
QList<IMG::Poly> *polys) const;
bool pointObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const;
bool extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
QList<IMG::Poly> *polys) const;
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
Handle &lblHdl, QList<IMG::Point> *points) const;
bool subdivInit(Handle &hdl, SubDiv *subdiv) const;
private:
QMap<SegmentType, SubDiv::Segment> 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

View File

@ -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

View File

@ -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

View File

@ -1,5 +1,23 @@
#include "vectortile.h"
static void copyPolys(const RectC &rect, QList<IMG::Poly> *src,
QList<IMG::Poly> *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<IMG::Point> *src,
QList<IMG::Point> *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<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
QList<IMG::Point> *points) const
void VectorTile::polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
const
{
SubFile::Handle rgnHdl, lblHdl, netHdl;
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
return;
QList<SubDiv*> 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<IMG::Poly> 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<IMG::Point> *points,
QCache<const SubDiv *, QList<IMG::Point> > *pointCache) const
{
SubFile::Handle rgnHdl, lblHdl;
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
return;
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits);
for (int i = 0; i < subdivs.size(); i++) {
SubDiv *subdiv = subdivs.at(i);
QList<IMG::Point> *pl = pointCache->object(subdiv);
if (!pl) {
QList<IMG::Point> 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<IMG::Point>(p));
} else
copyPoints(rect, pl, points);
}
}

View File

@ -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<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QList<IMG::Point> *points) const;
void polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
const;
void points(const RectC &rect, int bits, QList<IMG::Point> *points,
QCache<const SubDiv*, QList<IMG::Point> > *pointCache) const;
static bool isTileFile(SubFile::Type type)
{

View File

@ -322,7 +322,6 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
return _projection.xy2ll(_transform.img2proj(p));
}
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &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()));
}
}
}