1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2025-02-26 12:10:49 +01:00
GPXSee/src/map/IMG/rgnfile.cpp

630 lines
16 KiB
C++
Raw Normal View History

2019-09-20 00:23:47 +02:00
#include "common/rectc.h"
#include "common/garmin.h"
#include "deltastream.h"
#include "huffmanstream.h"
2021-01-31 14:54:21 +01:00
#include "style.h"
2019-05-10 18:56:19 +02:00
#include "lblfile.h"
#include "netfile.h"
#include "nodfile.h"
2019-05-10 18:56:19 +02:00
#include "rgnfile.h"
2021-09-20 21:43:17 +02:00
using namespace Garmin;
2021-04-10 15:27:40 +02:00
using namespace IMG;
2019-05-10 18:56:19 +02:00
2021-05-31 22:37:55 +02:00
#define MASK(bits) ((1U << (bits)) - 1U)
2020-02-16 15:59:51 +01:00
static quint64 pointId(const QPoint &pos, quint32 type, quint32 labelPtr)
2020-02-16 12:57:40 +01:00
{
quint64 id;
2021-01-11 00:30:52 +01:00
uint hash = (uint)qHash(QPair<uint,uint>((uint)qHash(
QPair<int, int>(pos.x(), pos.y())), labelPtr & 0x3FFFFF));
2020-02-16 12:57:40 +01:00
id = ((quint64)type)<<32 | hash;
// Make country labels precedent over city labels
2021-01-31 14:54:21 +01:00
if (!Style::isCountry(type))
2020-02-16 12:57:40 +01:00
id |= 1ULL<<63;
return id;
}
RGNFile::~RGNFile()
{
delete _huffmanTable;
}
bool RGNFile::readClassFields(Handle &hdl, SegmentType segmentType,
void *object, const LBLFile *lbl, Handle &lblHdl) const
2019-09-20 00:23:47 +02:00
{
quint8 flags;
quint32 rs;
MapData::Poly *poly = (segmentType == Polygon)
? (MapData::Poly *) object : 0;
MapData::Point *point = (segmentType == Point)
? (MapData::Point *) object : 0;
2019-09-20 00:23:47 +02:00
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &flags))
return false;
2019-05-10 18:56:19 +02:00
switch (flags >> 5) {
case 4:
rs = 1;
break;
case 5:
rs = 2;
break;
case 6:
rs = 3;
break;
case 7:
if (!readVUInt32(hdl, rs))
2019-05-10 18:56:19 +02:00
return false;
break;
default:
rs = 0;
break;
2019-05-10 18:56:19 +02:00
}
if (poly && Style::isRaster(poly->type) && lbl && lbl->imageIdSize()) {
quint32 id;
quint32 top, right, bottom, left;
2021-03-19 09:12:42 +01:00
if (rs < lbl->imageIdSize() + 16U)
return false;
if (!(readVUInt32(hdl, lbl->imageIdSize(), id)
&& readUInt32(hdl, top) && readUInt32(hdl, right)
&& readUInt32(hdl, bottom) && readUInt32(hdl, left)))
return false;
2021-01-27 21:18:06 +01:00
poly->raster = Raster(lbl, id, QRect(QPoint(left, top), QPoint(right,
bottom)));
rs -= lbl->imageIdSize() + 16;
}
if (point && (flags & 1) && lbl) {
quint32 p = pos(hdl);
point->label = lbl->label(lblHdl, this, hdl);
point->classLabel = true;
Q_ASSERT(pos(hdl) - p <= rs + 4);
rs -= pos(hdl) - p;
}
return seek(hdl, pos(hdl) + rs);
2019-05-10 18:56:19 +02:00
}
bool RGNFile::skipLclFields(Handle &hdl, const quint32 flags[3]) const
2019-09-20 00:23:47 +02:00
{
quint32 bitfield = 0xFFFFFFFF;
2019-05-10 18:56:19 +02:00
if (flags[0] & 0x20000000)
if (!readVBitfield32(hdl, bitfield))
return false;
2019-05-10 18:56:19 +02:00
for (int i = 0, j = 0; i < 29; i++) {
if ((flags[0] >> i) & 1) {
if (bitfield & 1) {
quint32 m = flags[(j >> 4) + 1] >> ((j * 2) & 0x1e) & 3;
quint32 skip = 0;
if (m == 3) {
if (!readVUInt32(hdl, skip))
return false;
} else
skip = m + 1;
if (!seek(hdl, pos(hdl) + skip))
return false;
2019-05-10 18:56:19 +02:00
}
bitfield >>= 1;
j++;
2019-05-10 18:56:19 +02:00
}
}
return true;
}
bool RGNFile::skipGblFields(Handle &hdl, quint32 flags) const
{
int cnt = 0;
do {
cnt = cnt + (flags & 3);
flags = flags >> 2;
} while (flags != 0);
return seek(hdl, pos(hdl) + cnt);
}
bool RGNFile::load(Handle &hdl)
2019-05-10 18:56:19 +02:00
{
quint16 hdrLen;
2019-05-10 18:56:19 +02:00
if (!(seek(hdl, _gmpOffset) && readUInt16(hdl, hdrLen)
&& seek(hdl, _gmpOffset + 0x15) && readUInt32(hdl, _offset)
&& readUInt32(hdl, _size)))
2019-05-10 18:56:19 +02:00
return false;
if (hdrLen >= 0x68) {
if (!(readUInt32(hdl, _polygonsOffset) && readUInt32(hdl, _polygonsSize)
2020-07-02 00:17:41 +02:00
&& seek(hdl, _gmpOffset + 0x29) && readUInt32(hdl, _polygonsGblFlags)
&& readUInt32(hdl, _polygonsLclFlags[0])
&& readUInt32(hdl, _polygonsLclFlags[1])
&& readUInt32(hdl, _polygonsLclFlags[2])
&& readUInt32(hdl, _linesOffset) && readUInt32(hdl, _linesSize)
&& seek(hdl, _gmpOffset + 0x45) && readUInt32(hdl, _linesGblFlags)
2020-07-02 00:17:41 +02:00
&& readUInt32(hdl, _linesLclFlags[0])
&& readUInt32(hdl, _linesLclFlags[1])
&& readUInt32(hdl, _linesLclFlags[2])
&& readUInt32(hdl, _pointsOffset) && readUInt32(hdl, _pointsSize)
&& seek(hdl, _gmpOffset + 0x61) && readUInt32(hdl, _pointsGblFlags)
2020-07-02 00:17:41 +02:00
&& readUInt32(hdl, _pointsLclFlags[0])
&& readUInt32(hdl, _pointsLclFlags[1])
&& readUInt32(hdl, _pointsLclFlags[2])))
return false;
}
if (hdrLen >= 0x7D) {
quint32 info;
if (!(seek(hdl, _gmpOffset + 0x71) && readUInt32(hdl, _dictOffset)
&& readUInt32(hdl, _dictSize) && readUInt32(hdl, info)))
return false;
if (_dictSize && _dictOffset && (info & 0x1E)) {
_huffmanTable = new HuffmanTable(((info >> 1) & 0xF) - 1);
if (!_huffmanTable->load(this, hdl))
return false;
}
}
2019-05-10 18:56:19 +02:00
return true;
}
void RGNFile::clear()
{
delete _huffmanTable;
_huffmanTable = 0;
}
bool RGNFile::polyObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl, NETFile *net,
Handle &netHdl, QList<MapData::Poly> *polys) const
2019-05-10 18:56:19 +02:00
{
const SubDiv::Segment &segment = (segmentType == Line)
? subdiv->lines() : subdiv->polygons();
if (!segment.isValid())
return true;
2020-02-08 10:54:59 +01:00
if (!seek(hdl, segment.offset()))
2019-05-10 18:56:19 +02:00
return false;
quint32 labelPtr;
quint8 type, len8, bitstreamInfo;
qint16 lon, lat;
quint16 len;
while (pos(hdl) < segment.end()) {
MapData::Poly poly;
2019-05-10 18:56:19 +02:00
2021-02-01 20:06:05 +01:00
if (!(readByte(hdl, &type) && readUInt24(hdl, labelPtr)
2019-05-10 18:56:19 +02:00
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
return false;
if (type & 0x80) {
if (!readUInt16(hdl, len))
return false;
} else {
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &len8))
2019-05-10 18:56:19 +02:00
return false;
len = len8;
}
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &bitstreamInfo))
2019-05-10 18:56:19 +02:00
return false;
poly.type = (segmentType == Polygon)
2019-05-10 18:56:19 +02:00
? ((quint32)(type & 0x7F)) << 8 : ((quint32)(type & 0x3F)) << 8;
2019-09-21 00:36:49 +02:00
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
subdiv->lat() + LS(lat, 24-subdiv->bits()));
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.boundingRect = RectC(c, c);
2019-05-10 18:56:19 +02:00
poly.points.append(QPointF(c.lon(), c.lat()));
2019-09-21 00:36:49 +02:00
qint32 lonDelta, latDelta;
DeltaStream stream(*this, hdl, len);
if (!stream.init(bitstreamInfo, labelPtr & 0x400000, false))
return false;
2019-09-21 00:36:49 +02:00
while (stream.readNext(lonDelta, latDelta)) {
pos.rx() += LS(lonDelta, (24-subdiv->bits()));
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
pos.rx() = 0x7fffff;
pos.ry() += LS(latDelta, (24-subdiv->bits()));
2019-05-10 18:56:19 +02:00
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
2019-05-10 18:56:19 +02:00
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
2019-05-10 18:56:19 +02:00
}
2019-09-21 00:36:49 +02:00
if (!(stream.atEnd() && stream.flush()))
2019-05-10 18:56:19 +02:00
return false;
2020-02-11 21:16:31 +01:00
if (lbl && (labelPtr & 0x3FFFFF)) {
2019-05-10 18:56:19 +02:00
if (labelPtr & 0x800000) {
quint32 lblOff;
2019-07-01 22:53:34 +02:00
if (net && net->lblOffset(netHdl, labelPtr & 0x3FFFFF, lblOff)
&& lblOff)
poly.label = lbl->label(lblHdl, lblOff, false, true,
Style::isContourLine(poly.type));
2019-05-10 18:56:19 +02:00
} else
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false,
true, Style::isContourLine(poly.type));
2019-05-10 18:56:19 +02:00
}
polys->append(poly);
}
return true;
}
bool RGNFile::extPolyObjects(Handle &hdl, const SubDiv *subdiv, quint32 shift,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Poly> *polys) const
2019-05-10 18:56:19 +02:00
{
quint32 labelPtr, len;
quint8 type, subtype;
2019-05-10 18:56:19 +02:00
qint16 lon, lat;
const SubDiv::Segment &segment = (segmentType == Line)
? subdiv->extLines() : subdiv->extPolygons();
2019-05-10 18:56:19 +02:00
if (!segment.isValid())
return true;
2020-02-08 10:54:59 +01:00
if (!seek(hdl, segment.offset()))
2019-05-10 18:56:19 +02:00
return false;
while (pos(hdl) < segment.end()) {
MapData::Poly poly;
QPoint pos;
2019-05-10 18:56:19 +02:00
2021-02-01 20:06:05 +01:00
if (!(readByte(hdl, &type) && readByte(hdl, &subtype)
&& readInt16(hdl, lon) && readInt16(hdl, lat)
&& readVUInt32(hdl, len)))
2019-05-10 18:56:19 +02:00
return false;
Q_ASSERT(SubFile::pos(hdl) + len <= segment.end());
2019-05-10 18:56:19 +02:00
poly.type = 0x10000 | (quint16(type)<<8) | (subtype & 0x1F);
labelPtr = 0;
2019-05-10 18:56:19 +02:00
if (_huffmanTable) {
pos = QPoint(LS(subdiv->lon(), 8) + LS(lon, 32-subdiv->bits()),
LS(subdiv->lat(), 8) + LS(lat, (32-subdiv->bits())));
2019-05-10 18:56:19 +02:00
qint32 lonDelta, latDelta;
BitStream4F bs(*this, hdl, len);
2021-11-04 23:01:33 +01:00
HuffmanDeltaStreamF stream(bs, *_huffmanTable);
if (!stream.init(segmentType == Line))
return false;
2019-05-10 18:56:19 +02:00
if (shift) {
if (!stream.readOffset(lonDelta, latDelta))
return false;
pos = QPoint(pos.x() | LS(lonDelta, 32-subdiv->bits()-shift),
pos.y() | LS(latDelta, 32-subdiv->bits()-shift));
}
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.boundingRect = RectC(c, c);
poly.points.append(QPointF(c.lon(), c.lat()));
while (stream.readNext(lonDelta, latDelta)) {
pos.rx() += LS(lonDelta, 32-subdiv->bits()-shift);
if (pos.rx() < 0 && subdiv->lon() >= 0)
pos.rx() = 0x7fffffff;
pos.ry() += LS(latDelta, 32-subdiv->bits()-shift);
Coordinates c(toWGS32(pos.x()), toWGS32(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
}
2019-05-10 18:56:19 +02:00
2021-11-10 20:33:13 +01:00
if (!(stream.atEnd() && bs.flush()))
return false;
} else {
pos = QPoint(subdiv->lon() + LS(lon, 24-subdiv->bits()),
subdiv->lat() + LS(lat, 24-subdiv->bits()));
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.boundingRect = RectC(c, c);
2019-05-10 18:56:19 +02:00
poly.points.append(QPointF(c.lon(), c.lat()));
quint8 bitstreamInfo;
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &bitstreamInfo))
2019-05-10 18:56:19 +02:00
return false;
qint32 lonDelta, latDelta;
DeltaStream stream(*this, hdl, len - 1);
if (!stream.init(bitstreamInfo, false, true))
return false;
while (stream.readNext(lonDelta, latDelta)) {
pos.rx() += LS(lonDelta, 24-subdiv->bits());
if (pos.rx() >= 0x800000 && subdiv->lon() >= 0)
pos.rx() = 0x7fffff;
pos.ry() += LS(latDelta, 24-subdiv->bits());
Coordinates c(toWGS24(pos.x()), toWGS24(pos.y()));
poly.points.append(QPointF(c.lon(), c.lat()));
poly.boundingRect = poly.boundingRect.united(c);
}
if (!(stream.atEnd() && stream.flush()))
return false;
}
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
return false;
if (subtype & 0x80 && !readClassFields(hdl, segmentType, &poly, lbl,
lblHdl))
return false;
if (subtype & 0x40 && !skipLclFields(hdl, segmentType == Line
2020-07-02 00:17:41 +02:00
? _linesLclFlags : _polygonsLclFlags))
return false;
quint32 gblFlags = (segmentType == Line)
2020-07-02 00:17:41 +02:00
? _linesGblFlags : _polygonsGblFlags;
if (gblFlags && !skipGblFields(hdl, gblFlags))
return false;
2019-05-10 18:56:19 +02:00
2020-02-11 21:16:31 +01:00
if (lbl && (labelPtr & 0x3FFFFF))
poly.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF, false, true,
Style::isContourLine(poly.type));
2019-09-21 00:36:49 +02:00
2019-05-10 18:56:19 +02:00
polys->append(poly);
}
return true;
}
bool RGNFile::pointObjects(Handle &hdl, const SubDiv *subdiv,
SegmentType segmentType, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Point> *points) const
2019-05-10 18:56:19 +02:00
{
const SubDiv::Segment &segment = (segmentType == IndexedPoint)
? subdiv->idxPoints() : subdiv->points();
2019-05-10 18:56:19 +02:00
if (!segment.isValid())
return true;
2020-02-08 10:54:59 +01:00
if (!seek(hdl, segment.offset()))
2019-05-10 18:56:19 +02:00
return false;
while (pos(hdl) < segment.end()) {
MapData::Point point;
2020-02-16 12:57:40 +01:00
quint8 type, subtype;
qint16 lon, lat;
quint32 labelPtr;
2019-05-10 18:56:19 +02:00
2021-02-01 20:06:05 +01:00
if (!(readByte(hdl, &type) && readUInt24(hdl, labelPtr)
2019-05-10 18:56:19 +02:00
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
return false;
if (labelPtr & 0x800000) {
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &subtype))
2019-05-10 18:56:19 +02:00
return false;
} else
subtype = 0;
2020-02-16 12:57:40 +01:00
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
subdiv->lat() + LS(lat, 24-subdiv->bits()));
2019-05-10 18:56:19 +02:00
2020-02-16 12:57:40 +01:00
point.type = (quint16)type<<8 | subtype;
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
2020-02-16 15:59:51 +01:00
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
if (lbl && (labelPtr & 0x3FFFFF))
2021-01-31 14:54:21 +01:00
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF,
labelPtr & 0x400000, !(Style::isCountry(point.type)
|| Style::isState(point.type)), Style::isSpot(point.type));
2019-05-10 18:56:19 +02:00
points->append(point);
}
return true;
}
bool RGNFile::extPointObjects(Handle &hdl, const SubDiv *subdiv,
const LBLFile *lbl, Handle &lblHdl, QList<MapData::Point> *points) const
2019-05-10 18:56:19 +02:00
{
const SubDiv::Segment &segment = subdiv->extPoints();
if (!segment.isValid())
return true;
2020-02-08 10:54:59 +01:00
if (!seek(hdl, segment.offset()))
2019-05-10 18:56:19 +02:00
return false;
while (pos(hdl) < segment.end()) {
MapData::Point point;
2020-02-16 12:57:40 +01:00
qint16 lon, lat;
quint8 type, subtype;
quint32 labelPtr = 0;
2019-05-10 18:56:19 +02:00
2021-02-01 20:06:05 +01:00
if (!(readByte(hdl, &type) && readByte(hdl, &subtype)
2019-05-10 18:56:19 +02:00
&& readInt16(hdl, lon) && readInt16(hdl, lat)))
return false;
point.type = 0x10000 | (((quint32)type)<<8) | (subtype & 0x1F);
if (subtype & 0x20 && !readUInt24(hdl, labelPtr))
return false;
if (subtype & 0x80 && !readClassFields(hdl, Point, &point, lbl, lblHdl))
return false;
2020-07-02 00:17:41 +02:00
if (subtype & 0x40 && !skipLclFields(hdl, _pointsLclFlags))
return false;
if (_pointsGblFlags && !skipGblFields(hdl, _pointsGblFlags))
return false;
2020-02-16 12:57:40 +01:00
QPoint pos(subdiv->lon() + LS(lon, 24-subdiv->bits()),
subdiv->lat() + LS(lat, 24-subdiv->bits()));
// Discard NT points breaking style draw order logic (and causing huge
// performance drawback)
if (point.type == 0x11400)
continue;
2020-02-16 12:57:40 +01:00
point.coordinates = Coordinates(toWGS24(pos.x()), toWGS24(pos.y()));
2020-02-16 15:59:51 +01:00
point.id = pointId(pos, point.type, labelPtr & 0x3FFFFF);
if (lbl && (labelPtr & 0x3FFFFF))
point.label = lbl->label(lblHdl, labelPtr & 0x3FFFFF);
2019-05-10 18:56:19 +02:00
points->append(point);
2019-05-10 18:56:19 +02:00
}
return true;
}
2020-09-18 20:56:00 +02:00
bool RGNFile::links(Handle &hdl, const SubDiv *subdiv, quint32 shift,
const NETFile *net, Handle &netHdl, const NODFile *nod, Handle &nodHdl,
Handle &nodHdl2, const LBLFile *lbl, Handle &lblHdl,
QList<MapData::Poly> *lines) const
{
quint32 size, blockIndexId;
quint8 flags;
const SubDiv::Segment &segment = subdiv->roadReferences();
if (!net || !nod)
return false;
if (!segment.isValid())
return true;
if (!seek(hdl, segment.offset()))
return false;
while (pos(hdl) < segment.end()) {
if (!readVUInt32(hdl, size))
return false;
2020-08-26 18:20:15 +02:00
quint32 entryStart = pos(hdl);
2021-02-01 20:06:05 +01:00
if (!(readByte(hdl, &flags) && readVUInt32(hdl, nod->indexIdSize(),
blockIndexId)))
return false;
quint8 bits[3];
for (int i = 0; i < 3; i++)
bits[i] = 0x4000a08 >> (((flags >> (2*i) & 3) << 3) ^ 0x10);
2021-05-09 22:35:05 +02:00
quint8 byteSize = bs(bits[0] + bits[1] + bits[2]);
quint32 counts;
if (!readVUInt32(hdl, byteSize, counts))
return false;
quint16 b8 = bits[0] ? (MASK(bits[0]) & counts) + 1 : 0;
quint16 b10 = bits[1] ? (MASK(bits[1]) & (counts >> bits[0])) + 1 : 0;
quint16 b16 = bits[2] ? (MASK(bits[2]) & (counts >> (bits[0] + bits[1])))
+ 1 : 0;
NODFile::BlockInfo blockInfo;
if (!nod->blockInfo(nodHdl, blockIndexId, blockInfo))
return false;
quint8 linkId, lineId;
for (int i = 0; i < b8 + b10 + b16; i++) {
if (!b8 || b8 <= i) {
quint16 v16;
if (!readUInt16(hdl, v16))
return false;
if (!b16 || b8 + b16 <= i) {
2021-05-09 22:35:05 +02:00
int shift = ((i - (b8 + b16)) * 10) & 7;
linkId = (quint8)(v16 >> shift);
lineId = (((v16 >> shift) >> 8) & 3) + 1;
if (shift < 6 && i < b8 + b10 + b16 - 1)
2020-08-26 18:20:15 +02:00
seek(hdl, pos(hdl) - 1);
} else {
linkId = (quint8)v16;
lineId = v16 >> 8;
Q_ASSERT(lineId > 4);
}
} else {
2021-02-01 20:06:05 +01:00
if (!readByte(hdl, &linkId))
return false;
lineId = 0;
}
net->link(subdiv, shift, netHdl, nod, nodHdl, nodHdl2, lbl, lblHdl,
blockInfo, linkId, lineId, lines);
}
if (entryStart + size != pos(hdl))
return false;
}
return true;
}
bool RGNFile::segments(Handle &hdl, SubDiv *subdiv, SubDiv::Segment seg[5]) const
2019-05-10 18:56:19 +02:00
{
if (subdiv->offset() == subdiv->end() || !(subdiv->objects() & 0x1F))
return true;
2019-05-10 18:56:19 +02:00
quint32 offset = _offset + subdiv->offset();
if (!seek(hdl, offset))
return false;
2019-05-10 18:56:19 +02:00
int no = 0;
for (int i = 0; i < 5; i++)
if (subdiv->objects() & (1<<i))
2019-05-10 18:56:19 +02:00
no++;
quint32 start = offset + 2 * (no - 1);
quint32 ls = 0;
int lt = 0;
2019-05-10 18:56:19 +02:00
for (int i = 0; i < 5; i++) {
if (subdiv->objects() & (1<<i)) {
2020-02-08 10:54:59 +01:00
if (ls) {
quint16 po;
if (!readUInt16(hdl, po) || !po)
return false;
2019-05-10 18:56:19 +02:00
start = offset + po;
seg[lt] = SubDiv::Segment(ls, start);
2020-02-08 10:54:59 +01:00
}
lt = i;
ls = start;
2019-05-10 18:56:19 +02:00
}
}
seg[lt] = SubDiv::Segment(ls,
subdiv->end() ? _offset + subdiv->end() : _offset + _size);
2019-05-10 18:56:19 +02:00
return true;
2019-05-10 18:56:19 +02:00
}
2021-02-03 23:15:52 +01:00
bool RGNFile::subdivInit(Handle &hdl, SubDiv *subdiv) const
2019-05-10 18:56:19 +02:00
{
2021-10-23 10:27:41 +02:00
SubDiv::Segment std[5], extPoints, extLines, extPolygons;
2021-10-23 10:27:41 +02:00
if (!segments(hdl, subdiv, std))
return false;
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);
}
2021-10-23 10:27:41 +02:00
subdiv->init(std[Point], std[IndexedPoint], std[Line], std[Polygon],
std[RoadReference], extPoints, extLines, extPolygons);
return true;
2019-05-10 18:56:19 +02:00
}