mirror of
https://github.com/tumic0/GPXSee.git
synced 2024-11-24 11:45:53 +01:00
Redesigned IMG caching
(Cache encoded data rather than raw data)
This commit is contained in:
parent
df1be4aeb9
commit
325e83569c
@ -4,23 +4,34 @@
|
|||||||
#include "vectortile.h"
|
#include "vectortile.h"
|
||||||
#include "img.h"
|
#include "img.h"
|
||||||
|
|
||||||
|
#define CACHED_SUBDIVS_COUNT 2048 // ~32MB
|
||||||
#define CACHE_SIZE 8388608 /* 8MB */
|
|
||||||
|
|
||||||
typedef QMap<QString, VectorTile*> TileMap;
|
typedef QMap<QString, VectorTile*> TileMap;
|
||||||
|
|
||||||
struct CTX
|
struct PolyCTX
|
||||||
{
|
{
|
||||||
CTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
PolyCTX(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
||||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
|
QList<IMG::Poly> *lines, QCache<const SubDiv*, IMG::Polys> *polyCache)
|
||||||
: rect(rect), bits(bits), polygons(polygons), lines(lines),
|
: rect(rect), bits(bits), polygons(polygons), lines(lines),
|
||||||
points(points) {}
|
polyCache(polyCache) {}
|
||||||
|
|
||||||
const RectC ▭
|
const RectC ▭
|
||||||
int bits;
|
int bits;
|
||||||
QList<IMG::Poly> *polygons;
|
QList<IMG::Poly> *polygons;
|
||||||
QList<IMG::Poly> *lines;
|
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 ▭
|
||||||
|
int bits;
|
||||||
QList<IMG::Point> *points;
|
QList<IMG::Point> *points;
|
||||||
|
QCache<const SubDiv*, QList<IMG::Point> > *pointCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
static SubFile::Type tileType(const char str[3])
|
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)));
|
QByteArray nba(QByteArray(d1, sizeof(d1)) + QByteArray(d2, sizeof(d2)));
|
||||||
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
|
_name = QString::fromLatin1(nba.constData(), nba.size()-1).trimmed();
|
||||||
_blockSize = 1 << (e1 + e2);
|
_blockSize = 1 << (e1 + e2);
|
||||||
_blockCache.setMaxCost(CACHE_SIZE / _blockSize);
|
|
||||||
|
|
||||||
|
_polyCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||||
|
_pointCache.setMaxCost(CACHED_SUBDIVS_COUNT);
|
||||||
|
|
||||||
// Read the FAT table
|
// Read the FAT table
|
||||||
quint8 flag;
|
quint8 flag;
|
||||||
@ -214,20 +226,28 @@ void IMG::clear()
|
|||||||
delete _style;
|
delete _style;
|
||||||
_style = 0;
|
_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;
|
PolyCTX *ctx = (PolyCTX*)context;
|
||||||
tile->objects(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->points);
|
tile->polys(ctx->rect, ctx->bits, ctx->polygons, ctx->lines, ctx->polyCache);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IMG::objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
static bool pointCb(VectorTile *tile, void *context)
|
||||||
QList<Poly> *lines, QList<Point> *points)
|
|
||||||
{
|
{
|
||||||
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];
|
double min[2], max[2];
|
||||||
|
|
||||||
min[0] = rect.left();
|
min[0] = rect.left();
|
||||||
@ -235,7 +255,20 @@ void IMG::objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
|||||||
max[0] = rect.right();
|
max[0] = rect.right();
|
||||||
max[1] = rect.top();
|
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)
|
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)
|
bool IMG::readBlock(int blockNum, QByteArray &data)
|
||||||
{
|
{
|
||||||
QByteArray *block = _blockCache[blockNum];
|
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
||||||
if (!block) {
|
return false;
|
||||||
if (!_file.seek((qint64)blockNum * (qint64)_blockSize))
|
data.resize(_blockSize);
|
||||||
return false;
|
if (read(data.data(), _blockSize) < _blockSize)
|
||||||
data.resize(_blockSize);
|
return false;
|
||||||
if (read(data.data(), _blockSize) < _blockSize)
|
|
||||||
return false;
|
|
||||||
_blockCache.insert(blockNum, new QByteArray(data));
|
|
||||||
} else
|
|
||||||
data = *block;
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
class VectorTile;
|
class VectorTile;
|
||||||
class SubFile;
|
class SubFile;
|
||||||
|
class SubDiv;
|
||||||
|
|
||||||
class IMG
|
class IMG
|
||||||
{
|
{
|
||||||
@ -24,6 +25,7 @@ public:
|
|||||||
QVector<QPointF> points;
|
QVector<QPointF> points;
|
||||||
Label label;
|
Label label;
|
||||||
quint32 type;
|
quint32 type;
|
||||||
|
RectC boundingRect;
|
||||||
|
|
||||||
bool operator<(const Poly &other) const
|
bool operator<(const Poly &other) const
|
||||||
{return type > other.type;}
|
{return type > other.type;}
|
||||||
@ -42,6 +44,14 @@ public:
|
|||||||
{return id < other.id;}
|
{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(const QString &fileName);
|
||||||
~IMG();
|
~IMG();
|
||||||
@ -53,8 +63,9 @@ public:
|
|||||||
const QString &name() const {return _name;}
|
const QString &name() const {return _name;}
|
||||||
const RectC &bounds() const {return _bounds;}
|
const RectC &bounds() const {return _bounds;}
|
||||||
|
|
||||||
void objects(const RectC &rect, int bits, QList<Poly> *polygons,
|
void polys(const RectC &rect, int bits, QList<Poly> *polygons,
|
||||||
QList<Poly> *lines, QList<Point> *points);
|
QList<Poly> *lines);
|
||||||
|
void points(const RectC &rect, int bits, QList<Point> *points);
|
||||||
const Style *style() const {return _style;}
|
const Style *style() const {return _style;}
|
||||||
|
|
||||||
bool isValid() const {return _valid;}
|
bool isValid() const {return _valid;}
|
||||||
@ -73,7 +84,6 @@ private:
|
|||||||
QFile _file;
|
QFile _file;
|
||||||
quint8 _key;
|
quint8 _key;
|
||||||
int _blockSize;
|
int _blockSize;
|
||||||
QCache<int, QByteArray> _blockCache;
|
|
||||||
|
|
||||||
QString _name;
|
QString _name;
|
||||||
RectC _bounds;
|
RectC _bounds;
|
||||||
@ -81,6 +91,9 @@ private:
|
|||||||
SubFile *_typ;
|
SubFile *_typ;
|
||||||
Style *_style;
|
Style *_style;
|
||||||
|
|
||||||
|
QCache<const SubDiv*, Polys> _polyCache;
|
||||||
|
QCache<const SubDiv*, QList<Point> > _pointCache;
|
||||||
|
|
||||||
bool _valid;
|
bool _valid;
|
||||||
QString _errorString;
|
QString _errorString;
|
||||||
};
|
};
|
||||||
|
@ -39,7 +39,7 @@ bool RGNFile::skipClassFields(Handle &hdl) const
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3],
|
||||||
Segment::Type type) const
|
SegmentType type) const
|
||||||
{
|
{
|
||||||
quint32 bitfield = 0xFFFFFFFF;
|
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;
|
quint32 m = flags[(i >> 4) + 1] >> ((i * 2) & 0x1e) & 3;
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 5:
|
case 5:
|
||||||
if (m == 1 && type == Segment::Point) {
|
if (m == 1 && type == Point) {
|
||||||
quint16 u16;
|
quint16 u16;
|
||||||
if (!readUInt16(hdl, u16))
|
if (!readUInt16(hdl, u16))
|
||||||
return false;
|
return false;
|
||||||
@ -116,10 +116,15 @@ bool RGNFile::init(Handle &hdl)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
|
||||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
||||||
Handle &netHdl, QList<IMG::Poly> *polys) const
|
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()))
|
if (!seek(hdl, segment.start()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -145,14 +150,14 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
if (!readUInt8(hdl, bitstreamInfo))
|
if (!readUInt8(hdl, bitstreamInfo))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
poly.type = (segment.type() == Segment::Polygon)
|
poly.type = (segmentType == Polygon)
|
||||||
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
|
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
|
||||||
|
|
||||||
|
|
||||||
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
QPoint pos(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
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()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
|
|
||||||
qint32 lonDelta, latDelta;
|
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()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
br = br.united(c);
|
poly.boundingRect = poly.boundingRect.united(c);
|
||||||
}
|
}
|
||||||
if (!(stream.atEnd() && stream.flush()))
|
if (!(stream.atEnd() && stream.flush()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!rect.intersects(br))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||||
if (labelPtr & 0x800000) {
|
if (labelPtr & 0x800000) {
|
||||||
quint32 lblOff;
|
quint32 lblOff;
|
||||||
@ -188,22 +190,25 @@ bool RGNFile::polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||||
const SubDiv *subdiv, quint32 shift, const Segment &segment, LBLFile *lbl,
|
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
|
||||||
Handle &lblHdl, QList<IMG::Poly> *polys, bool line) const
|
QList<IMG::Poly> *polys) const
|
||||||
{
|
{
|
||||||
quint32 labelPtr, len;
|
quint32 labelPtr, len;
|
||||||
quint8 type, subtype;
|
quint8 type, subtype;
|
||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
|
const SubDiv::Segment &segment = (segmentType == Line)
|
||||||
|
? subdiv->extLines() : subdiv->extPolygons();
|
||||||
|
|
||||||
|
|
||||||
|
if (!segment.isValid())
|
||||||
|
return true;
|
||||||
if (!seek(hdl, segment.start()))
|
if (!seek(hdl, segment.start()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
while (hdl.pos < (int)segment.end()) {
|
while (hdl.pos < (int)segment.end()) {
|
||||||
IMG::Poly poly;
|
IMG::Poly poly;
|
||||||
QPoint pos;
|
QPoint pos;
|
||||||
RectC br;
|
|
||||||
|
|
||||||
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
if (!(readUInt8(hdl, type) && readUInt8(hdl, subtype)
|
||||||
&& readInt16(hdl, lon) && readInt16(hdl, lat)
|
&& 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())));
|
(subdiv->lat()<<8) + ((qint32)lat<<(32-subdiv->bits())));
|
||||||
|
|
||||||
qint32 lonDelta, latDelta;
|
qint32 lonDelta, latDelta;
|
||||||
HuffmanStream stream(*this, hdl, len, _huffmanTable, line);
|
HuffmanStream stream(*this, hdl, len, _huffmanTable,
|
||||||
|
segmentType == Line);
|
||||||
|
|
||||||
if (shift) {
|
if (shift) {
|
||||||
if (!stream.readOffset(lonDelta, latDelta))
|
if (!stream.readOffset(lonDelta, latDelta))
|
||||||
@ -227,7 +233,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
pos.y() | latDelta<<(32-subdiv->bits()-shift));
|
pos.y() | latDelta<<(32-subdiv->bits()-shift));
|
||||||
}
|
}
|
||||||
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
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()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
|
|
||||||
while (stream.readNext(lonDelta, latDelta)) {
|
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()));
|
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
br = br.united(c);
|
poly.boundingRect = poly.boundingRect.united(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(stream.atEnd() && stream.flush()))
|
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())),
|
pos = QPoint(subdiv->lon() + ((qint32)lon<<(24-subdiv->bits())),
|
||||||
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
subdiv->lat() + ((qint32)lat<<(24-subdiv->bits())));
|
||||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
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()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
|
|
||||||
quint8 bitstreamInfo;
|
quint8 bitstreamInfo;
|
||||||
@ -261,7 +267,7 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
|
|
||||||
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
|
||||||
poly.points.append(QPointF(c.lon(), c.lat()));
|
poly.points.append(QPointF(c.lon(), c.lat()));
|
||||||
br = br.united(c);
|
poly.boundingRect = poly.boundingRect.united(c);
|
||||||
}
|
}
|
||||||
if (!(stream.atEnd() && stream.flush()))
|
if (!(stream.atEnd() && stream.flush()))
|
||||||
return false;
|
return false;
|
||||||
@ -271,13 +277,10 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
return false;
|
return false;
|
||||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||||
return false;
|
return false;
|
||||||
if (subtype & 0x40 && !skipLclFields(hdl, line ? _linesFlags
|
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
|
||||||
: _polygonsFlags, segment.type()))
|
? _linesFlags : _polygonsFlags, segmentType))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (!rect.intersects(br))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (lbl && (labelPtr & 0x3FFFFF))
|
if (lbl && (labelPtr & 0x3FFFFF))
|
||||||
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
|
||||||
|
|
||||||
@ -287,14 +290,18 @@ bool RGNFile::extPolyObjects(const RectC &rect, Handle &hdl,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
|
||||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
|
||||||
QList<IMG::Point> *points) const
|
QList<IMG::Point> *points) const
|
||||||
{
|
{
|
||||||
quint8 type, subtype;
|
quint8 type, subtype;
|
||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
quint32 labelPtr;
|
quint32 labelPtr;
|
||||||
|
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
|
||||||
|
? subdiv->idxPoints() : subdiv->points();
|
||||||
|
|
||||||
|
if (!segment.isValid())
|
||||||
|
return true;
|
||||||
if (!seek(hdl, segment.start()))
|
if (!seek(hdl, segment.start()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -317,9 +324,6 @@ bool RGNFile::pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|||||||
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
point.coordinates = Coordinates(toWGS24(subdiv->lon() + lonOffset),
|
||||||
toWGS24(subdiv->lat() + latOffset));
|
toWGS24(subdiv->lat() + latOffset));
|
||||||
|
|
||||||
if (!rect.contains(point.coordinates))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
point.poi = labelPtr & 0x400000;
|
point.poi = labelPtr & 0x400000;
|
||||||
if (lbl && (labelPtr & 0x3FFFFF)) {
|
if (lbl && (labelPtr & 0x3FFFFF)) {
|
||||||
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, point.poi);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||||
const SubDiv *subdiv, const Segment &segment, LBLFile *lbl,
|
|
||||||
Handle &lblHdl, QList<IMG::Point> *points) const
|
Handle &lblHdl, QList<IMG::Point> *points) const
|
||||||
{
|
{
|
||||||
quint8 type, subtype;
|
quint8 type, subtype;
|
||||||
qint16 lon, lat;
|
qint16 lon, lat;
|
||||||
quint32 labelPtr;
|
quint32 labelPtr;
|
||||||
|
const SubDiv::Segment &segment = subdiv->extPoints();
|
||||||
|
|
||||||
|
|
||||||
|
if (!segment.isValid())
|
||||||
|
return true;
|
||||||
if (!seek(hdl, segment.start()))
|
if (!seek(hdl, segment.start()))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
@ -363,10 +370,12 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
|||||||
return false;
|
return false;
|
||||||
if (subtype & 0x80 && !skipClassFields(hdl))
|
if (subtype & 0x80 && !skipClassFields(hdl))
|
||||||
return false;
|
return false;
|
||||||
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, segment.type()))
|
if (subtype & 0x40 && !skipLclFields(hdl, _pointsFlags, Point))
|
||||||
return false;
|
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;
|
continue;
|
||||||
|
|
||||||
point.poi = labelPtr & 0x400000;
|
point.poi = labelPtr & 0x400000;
|
||||||
@ -382,85 +391,13 @@ bool RGNFile::extPointObjects(const RectC &rect, Handle &hdl,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RGNFile::objects(const RectC &rect, const SubDiv *subdiv,
|
QMap<RGNFile::SegmentType, SubDiv::Segment> RGNFile::segments(Handle &hdl,
|
||||||
LBLFile *lbl, NETFile *net, QList<IMG::Poly> *polygons,
|
SubDiv *subdiv) const
|
||||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points)
|
|
||||||
{
|
{
|
||||||
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))
|
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F))
|
||||||
return QVector<Segment>();
|
return ret;
|
||||||
|
|
||||||
quint32 offset = _offset + subdiv->offset();
|
quint32 offset = _offset + subdiv->offset();
|
||||||
|
|
||||||
@ -470,57 +407,66 @@ QVector<RGNFile::Segment> RGNFile::segments(Handle &hdl, const SubDiv *subdiv)
|
|||||||
no++;
|
no++;
|
||||||
|
|
||||||
if (!seek(hdl, offset))
|
if (!seek(hdl, offset))
|
||||||
return QVector<Segment>();
|
return ret;
|
||||||
|
|
||||||
QVector<Segment> ret;
|
|
||||||
quint32 start = offset + 2 * (no - 1);
|
quint32 start = offset + 2 * (no - 1);
|
||||||
|
quint32 ls = 0;
|
||||||
|
SegmentType lt = (SegmentType)0;
|
||||||
quint16 po;
|
quint16 po;
|
||||||
int cnt = 0;
|
int cnt = 0;
|
||||||
|
|
||||||
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
|
for (quint16 mask = 0x1; mask <= 0x10; mask <<= 1) {
|
||||||
if (subdiv->objects() & mask) {
|
if (subdiv->objects() & mask) {
|
||||||
if (cnt) {
|
if (cnt) {
|
||||||
if (!readUInt16(hdl, po))
|
if (!readUInt16(hdl, po) || !po)
|
||||||
return QVector<Segment>();
|
return QMap<RGNFile::SegmentType, SubDiv::Segment>();
|
||||||
start = offset + po;
|
start = offset + po;
|
||||||
}
|
}
|
||||||
if (!ret.isEmpty())
|
if (ls)
|
||||||
ret.last().setEnd(start);
|
ret.insert(lt, SubDiv::Segment(ls, start));
|
||||||
ret.append(Segment(start, (Segment::Type)mask));
|
|
||||||
|
lt = (SegmentType)mask;
|
||||||
|
ls = start;
|
||||||
cnt++;
|
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;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
|
||||||
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment)
|
|
||||||
{
|
{
|
||||||
QString type;
|
QMap<RGNFile::SegmentType, SubDiv::Segment> seg(segments(hdl, subdiv));
|
||||||
switch (segment.type()) {
|
SubDiv::Segment extPoints, extLines, extPolygons;
|
||||||
case RGNFile::Segment::Point:
|
|
||||||
type = "Point";
|
if (subdiv->extPointsOffset() != subdiv->extPointsEnd()) {
|
||||||
break;
|
quint32 start = _pointsOffset + subdiv->extPointsOffset();
|
||||||
case RGNFile::Segment::IndexedPoint:
|
quint32 end = subdiv->extPointsEnd()
|
||||||
type = "IndexedPoint";
|
? _pointsOffset + subdiv->extPointsEnd()
|
||||||
break;
|
: _pointsOffset + _pointsSize;
|
||||||
case RGNFile::Segment::Line:
|
extPoints = SubDiv::Segment(start, end);
|
||||||
type = "Line";
|
}
|
||||||
break;
|
if (subdiv->extPolygonsOffset() != subdiv->extPolygonsEnd()) {
|
||||||
case RGNFile::Segment::Polygon:
|
quint32 start = _polygonsOffset + subdiv->extPolygonsOffset();
|
||||||
type = "Polygon";
|
quint32 end = subdiv->extPolygonsEnd()
|
||||||
break;
|
? _polygonsOffset + subdiv->extPolygonsEnd()
|
||||||
case RGNFile::Segment::RoadReference:
|
: _polygonsOffset + _polygonsSize;
|
||||||
type = "RoadReference";
|
extPolygons = SubDiv::Segment(start, end);
|
||||||
break;
|
}
|
||||||
|
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()
|
subdiv->init(seg.value(Point), seg.value(IndexedPoint), seg.value(Line),
|
||||||
- segment.start() << ", " << type << ")";
|
seg.value(Polygon), seg.value(RoadReference), extPoints, extLines,
|
||||||
|
extPolygons);
|
||||||
|
|
||||||
return dbg.space();
|
return true;
|
||||||
}
|
}
|
||||||
#endif // QT_NO_DEBUG
|
|
||||||
|
@ -12,6 +12,14 @@ class NETFile;
|
|||||||
class RGNFile : public SubFile
|
class RGNFile : public SubFile
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
enum SegmentType {
|
||||||
|
Point = 0x1,
|
||||||
|
IndexedPoint = 0x2,
|
||||||
|
Line = 0x4,
|
||||||
|
Polygon = 0x8,
|
||||||
|
RoadReference = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
RGNFile(IMG *img)
|
RGNFile(IMG *img)
|
||||||
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
: SubFile(img), _offset(0), _size(0), _polygonsOffset(0),
|
||||||
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
_polygonsSize(0), _linesOffset(0), _linesSize(0), _pointsOffset(0),
|
||||||
@ -21,65 +29,29 @@ public:
|
|||||||
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
_linesSize(0), _pointsOffset(0), _pointsSize(0), _init(false)
|
||||||
{clearFlags();}
|
{clearFlags();}
|
||||||
|
|
||||||
void objects(const RectC &rect, const SubDiv *subdiv,
|
bool initialized() const {return _init;}
|
||||||
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 init(Handle &hdl);
|
bool init(Handle &hdl);
|
||||||
|
|
||||||
QVector<Segment> segments(Handle &hdl, const SubDiv *subdiv) const;
|
bool polyObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
|
||||||
bool polyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
LBLFile *lbl, Handle &lblHdl, NETFile *net, Handle &netHdl,
|
||||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl, NETFile *net,
|
QList<IMG::Poly> *polys) const;
|
||||||
Handle &netHdl, QList<IMG::Poly> *polys) const;
|
bool pointObjects(Handle &hdl, const SubDiv *subdiv, SegmentType segmentType,
|
||||||
bool pointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
LBLFile *lbl, Handle &lblHdl, QList<IMG::Point> *points) const;
|
||||||
const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
bool extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
|
||||||
QList<IMG::Point> *points) const;
|
SegmentType segmentType, LBLFile *lbl, Handle &lblHdl,
|
||||||
bool extPolyObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
QList<IMG::Poly> *polys) const;
|
||||||
quint32 shift, const Segment &segment, LBLFile *lbl, Handle &lblHdl,
|
bool extPointObjects(Handle &hdl, const SubDiv *subdiv, LBLFile *lbl,
|
||||||
QList<IMG::Poly> *polys, bool line) const;
|
Handle &lblHdl, QList<IMG::Point> *points) const;
|
||||||
bool extPointObjects(const RectC &rect, Handle &hdl, const SubDiv *subdiv,
|
|
||||||
const Segment &segment, 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();
|
void clearFlags();
|
||||||
|
|
||||||
bool skipClassFields(Handle &hdl) const;
|
bool skipClassFields(Handle &hdl) const;
|
||||||
bool skipLclFields(Handle &hdl, const quint32 flags[3],
|
bool skipLclFields(Handle &hdl, const quint32 flags[3], SegmentType type)
|
||||||
Segment::Type type) const;
|
const;
|
||||||
|
|
||||||
friend QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
|
|
||||||
|
|
||||||
quint32 _offset;
|
quint32 _offset;
|
||||||
quint32 _size;
|
quint32 _size;
|
||||||
@ -99,8 +71,4 @@ private:
|
|||||||
bool _init;
|
bool _init;
|
||||||
};
|
};
|
||||||
|
|
||||||
#ifndef QT_NO_DEBUG
|
|
||||||
QDebug operator<<(QDebug dbg, const RGNFile::Segment &segment);
|
|
||||||
#endif // QT_NO_DEBUG
|
|
||||||
|
|
||||||
#endif // RGNFILE_H
|
#endif // RGNFILE_H
|
||||||
|
@ -939,9 +939,6 @@ Style::Style(SubFile *typ)
|
|||||||
|
|
||||||
if (typ)
|
if (typ)
|
||||||
parseTYPFile(typ);
|
parseTYPFile(typ);
|
||||||
|
|
||||||
// Override stuff breaking the style display logic
|
|
||||||
_points[0x11400] = Point(None);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const Style::Line &Style::line(quint32 type) const
|
const Style::Line &Style::line(quint32 type) const
|
||||||
|
@ -7,55 +7,123 @@
|
|||||||
|
|
||||||
class SubDiv {
|
class SubDiv {
|
||||||
public:
|
public:
|
||||||
SubDiv(quint32 offset, qint32 lon, qint32 lat, int bits, quint8 objects)
|
class Segment {
|
||||||
: _offset(offset), _end(0), _lon(lon), _lat(lat), _bits(bits),
|
public:
|
||||||
_objects(objects), _polygonsOffset(0), _polygonsEnd(0), _linesOffset(0),
|
Segment() : _start(0), _end(0) {}
|
||||||
_linesEnd(0), _pointsOffset(0), _pointsEnd(0) {}
|
Segment(quint32 start, quint32 end) : _start(start), _end(end) {}
|
||||||
void setEnd(quint32 end) {_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 lon() const {return _lon;}
|
||||||
qint32 lat() const {return _lat;}
|
qint32 lat() const {return _lat;}
|
||||||
quint8 bits() const {return _bits;}
|
quint8 bits() const {return _bits;}
|
||||||
quint8 objects() const {return _objects;}
|
|
||||||
|
|
||||||
// Extended types objects (TRE7)
|
// Valid only after initialization
|
||||||
void setExtOffsets(quint32 polygon, quint32 line, quint32 point)
|
const Segment &points() const {return _rgn.points;}
|
||||||
{_polygonsOffset = polygon; _linesOffset = line; _pointsOffset = point;}
|
const Segment &idxPoints() const {return _rgn.idxPoints;}
|
||||||
void setExtEnds(quint32 polygon, quint32 line, quint32 point)
|
const Segment &lines() const {return _rgn.lines;}
|
||||||
{_polygonsEnd = polygon; _linesEnd = line; _pointsEnd = point;}
|
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;}
|
// Valid only until initialization
|
||||||
quint32 polygonsEnd() const {return _polygonsEnd;}
|
quint8 objects() const {return _tre.objects;}
|
||||||
quint32 linesOffset() const {return _linesOffset;}
|
quint32 offset() const {return _tre.offset;}
|
||||||
quint32 linesEnd() const {return _linesEnd;}
|
quint32 end() const {return _tre.end;}
|
||||||
quint32 pointsOffset() const {return _pointsOffset;}
|
quint32 extPolygonsOffset() const {return _tre.polygonsOffset;}
|
||||||
quint32 pointsEnd() const {return _pointsEnd;}
|
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:
|
private:
|
||||||
quint32 _offset;
|
struct TRE
|
||||||
quint32 _end;
|
{
|
||||||
|
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;
|
qint32 _lon, _lat;
|
||||||
quint8 _bits;
|
quint8 _bits;
|
||||||
quint8 _objects;
|
bool _init;
|
||||||
|
union {
|
||||||
quint32 _polygonsOffset;
|
TRE _tre;
|
||||||
quint32 _polygonsEnd;
|
RGN _rgn;
|
||||||
quint32 _linesOffset;
|
};
|
||||||
quint32 _linesEnd;
|
|
||||||
quint32 _pointsOffset;
|
|
||||||
quint32 _pointsEnd;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#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
|
#endif // SUBDIV_H
|
||||||
|
@ -1,5 +1,23 @@
|
|||||||
#include "vectortile.h"
|
#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)
|
SubFile *VectorTile::file(SubFile::Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
@ -70,17 +88,75 @@ bool VectorTile::initGMP()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void VectorTile::objects(const RectC &rect, int bits,
|
void VectorTile::polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
||||||
QList<IMG::Poly> *polygons, QList<IMG::Poly> *lines,
|
QList<IMG::Poly> *lines, QCache<const SubDiv *, IMG::Polys> *polyCache)
|
||||||
QList<IMG::Point> *points) const
|
const
|
||||||
{
|
{
|
||||||
|
SubFile::Handle rgnHdl, lblHdl, netHdl;
|
||||||
|
|
||||||
|
if (!_rgn->initialized() && !_rgn->init(rgnHdl))
|
||||||
|
return;
|
||||||
|
|
||||||
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits);
|
QList<SubDiv*> subdivs = _tre->subdivs(rect, bits);
|
||||||
for (int i = 0; i < subdivs.size(); i++) {
|
for (int i = 0; i < subdivs.size(); i++) {
|
||||||
const SubDiv *subdiv = subdivs.at(i);
|
SubDiv *subdiv = subdivs.at(i);
|
||||||
quint32 shift = _tre->shift(subdiv->bits());
|
|
||||||
|
|
||||||
_rgn->objects(rect, subdiv, _lbl, _net, polygons, lines, points);
|
IMG::Polys *polys = polyCache->object(subdiv);
|
||||||
_rgn->extObjects(rect, subdiv, shift, _lbl, polygons, lines, points);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -24,8 +24,11 @@ public:
|
|||||||
SubFile *file(SubFile::Type type);
|
SubFile *file(SubFile::Type type);
|
||||||
SubFile *addFile(IMG *img, SubFile::Type type);
|
SubFile *addFile(IMG *img, SubFile::Type type);
|
||||||
|
|
||||||
void objects(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
void polys(const RectC &rect, int bits, QList<IMG::Poly> *polygons,
|
||||||
QList<IMG::Poly> *lines, QList<IMG::Point> *points) const;
|
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)
|
static bool isTileFile(SubFile::Type type)
|
||||||
{
|
{
|
||||||
|
@ -322,7 +322,6 @@ Coordinates IMGMap::xy2ll(const QPointF &p)
|
|||||||
return _projection.xy2ll(_transform.img2proj(p));
|
return _projection.xy2ll(_transform.img2proj(p));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
|
void IMGMap::drawPolygons(QPainter *painter, const QList<IMG::Poly> &polygons)
|
||||||
{
|
{
|
||||||
for (int n = 0; n < _img.style()->drawOrder().size(); n++) {
|
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(
|
RectD polyRect(_transform.img2proj(ttl), _transform.img2proj(
|
||||||
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
|
QPointF(ttl.x() + TILE_SIZE, ttl.y() + TILE_SIZE)));
|
||||||
_img.objects(polyRect.toRectC(_projection, 4), _zoom,
|
_img.polys(polyRect.toRectC(_projection, 4), _zoom,
|
||||||
&(tile.polygons()), &(tile.lines()), 0);
|
&(tile.polygons()), &(tile.lines()));
|
||||||
|
|
||||||
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
|
RectD pointRect(_transform.img2proj(QPointF(ttl.x() - TEXT_EXTENT,
|
||||||
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
|
ttl.y() - TEXT_EXTENT)), _transform.img2proj(QPointF(ttl.x()
|
||||||
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
|
+ TILE_SIZE + TEXT_EXTENT, ttl.y() + TILE_SIZE + TEXT_EXTENT)));
|
||||||
_img.objects(pointRect.toRectC(_projection, 4), _zoom,
|
_img.points(pointRect.toRectC(_projection, 4), _zoom,
|
||||||
0, 0, &(tile.points()));
|
&(tile.points()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user