From 92b2fbaf04b1e518809b3f15b964ede2e946569e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 17 Apr 2025 07:42:45 +0200 Subject: [PATCH 01/10] Fixed ISO8211 parser error handling --- src/map/ENC/iso8211.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index 46f86582..e922c6ae 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -187,6 +187,8 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields) SubFieldDefinition sfd(fieldType(typeStr, size)); if (sfd.type() == Unknown) return false; + if (tag >= tags.size()) + return false; defs[tag] = sfd; defTags[tag] = tags.at(tag); tag++; From 91376fd6099cce5f79bd4a997f51abd8366dae80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 17 Apr 2025 08:43:23 +0200 Subject: [PATCH 02/10] Make sure all fields have their definitions --- src/map/ENC/iso8211.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index e922c6ae..b97ca3f7 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -194,6 +194,9 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields) tag++; } } + + if (tag != tags.size()) + return false; } fields = SubFields(defTags, defs, repeat); From f4e19d091796fc4f4729ad5e502500ec852ac86e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 17 Apr 2025 20:25:12 +0200 Subject: [PATCH 03/10] Multiple S-57 files parse optimizations --- src/map/ENC/iso8211.cpp | 56 +++++----- src/map/ENC/iso8211.h | 55 ++++------ src/map/ENC/mapdata.cpp | 226 +++++++++++++++++++++------------------- src/map/ENC/mapdata.h | 20 ++-- src/map/encatlas.cpp | 35 ++++--- src/map/encmap.cpp | 39 ++++--- src/map/encmap.h | 2 +- 7 files changed, 225 insertions(+), 208 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index b97ca3f7..6f497074 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -1,3 +1,4 @@ +#include #include #include #include "common/util.h" @@ -5,13 +6,6 @@ using namespace ENC; -#define UINT16(x) \ - (((quint16)*(const uchar*)(x)) \ - | ((quint16)(*((const uchar*)(x) + 1)) << 8)) - -#define INT32(x) ((qint32)UINT32(x)) -#define INT16(x) ((qint16)UINT16(x)) - struct DR { char RecordLength[5]; char InterchangeLevel; @@ -29,18 +23,18 @@ struct DR { }; -const QVariant *ISO8211::Field::data(const QByteArray &name, int idx) const +const QVariant *ISO8211::Field::data(quint32 name, int idx) const { const QVector &v = _data.at(idx); - for (int i = 0; i < _subFields.size(); i++) - if (_subFields.at(i) == name) + for (int i = 0; i < _subFields->size(); i++) + if (_subFields->at(i) == name) return &v.at(i); return 0; } -bool ISO8211::Field::subfield(const char *name, int *val, int idx) const +bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const { bool ok; @@ -52,7 +46,7 @@ bool ISO8211::Field::subfield(const char *name, int *val, int idx) const return ok; } -bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const +bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const { bool ok; @@ -64,7 +58,7 @@ bool ISO8211::Field::subfield(const char *name, uint *val, int idx) const return ok; } -bool ISO8211::Field::subfield(const char *name, QByteArray *val, int idx) const +bool ISO8211::Field::subfield(quint32 name, QByteArray *val, int idx) const { const QVariant *v = data(name, idx); if (!v) @@ -101,6 +95,7 @@ int ISO8211::readDR(QVector &fields) DR ddr; QByteArray fieldLen, fieldPos; int len, lenSize, posSize, tagSize, offset; + char tag[4]; static_assert(sizeof(ddr) == 24, "Invalid DR alignment"); if (_file.read((char*)&ddr, sizeof(ddr)) != sizeof(ddr)) @@ -115,20 +110,19 @@ int ISO8211::readDR(QVector &fields) if (len < 0 || offset < 0 || lenSize < 0 || posSize < 0 || tagSize < 0) return -1; - fields.resize((offset - 1 - sizeof(DR)) / (lenSize + posSize + tagSize)); + fields.resize((offset - 1 - sizeof(ddr)) / (lenSize + posSize + tagSize)); fieldLen.resize(lenSize); fieldPos.resize(posSize); for (int i = 0; i < fields.size(); i++) { FieldDefinition &r = fields[i]; - r.tag.resize(tagSize); - - if (_file.read(r.tag.data(), tagSize) != tagSize + if (_file.read(tag, sizeof(tag)) != tagSize || _file.read(fieldLen.data(), lenSize) != lenSize || _file.read(fieldPos.data(), posSize) != posSize) return -1; + r.tag = qFromLittleEndian(tag); r.pos = offset + Util::str2int(fieldPos.constData(), posSize); r.size = Util::str2int(fieldLen.constData(), lenSize); @@ -141,11 +135,12 @@ int ISO8211::readDR(QVector &fields) bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields) { - static const QRegularExpression re("(\\d*)(\\w+)\\(*(\\d*)\\)*"); + static const QRegularExpression re( + "([0-9]*)(A|I|R|B|b11|b12|b14|b21|b22|b24)\\(*([0-9]*)\\)*"); QByteArray ba(def.size, Qt::Initialization::Uninitialized); bool repeat = false; QVector defs; - QVector defTags; + QVector defTags; if (!(_file.seek(def.pos) && _file.read(ba.data(), ba.size()) == ba.size())) return false; @@ -155,9 +150,9 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields) repeat = true; list[1].remove(0, 1); } - QList tags(list.at(1).split('!')); if (list.size() > 2) { + QList tags(list.at(1).split('!')); QRegularExpressionMatchIterator it = re.globalMatch(list.at(2)); int tag = 0; @@ -190,7 +185,8 @@ bool ISO8211::readDDA(const FieldDefinition &def, SubFields &fields) if (tag >= tags.size()) return false; defs[tag] = sfd; - defTags[tag] = tags.at(tag); + defTags[tag] = (tags.at(tag).length() == 4) + ? qFromLittleEndian(tags.at(tag).constData()) : 0; tag++; } } @@ -223,7 +219,7 @@ bool ISO8211::readDDR() SubFields def; if (!readDDA(fields.at(i), def)) { _errorString = QString("Error reading %1 DDA field") - .arg(QString(fields.at(i).tag)); + .arg(QByteArray((char*)&fields.at(i).tag, 4)); return false; } _map.insert(fields.at(i).tag, def); @@ -275,11 +271,11 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def, dp++; break; case S16: - row[i] = QVariant(INT16(dp)); + row[i] = QVariant(qFromLittleEndian(dp)); dp += 2; break; case S32: - row[i] = QVariant(INT32(dp)); + row[i] = QVariant(qFromLittleEndian(dp)); dp += 4; break; case U8: @@ -287,11 +283,11 @@ bool ISO8211::readUDA(quint64 pos, const FieldDefinition &def, dp++; break; case U16: - row[i] = QVariant(UINT16(dp)); + row[i] = QVariant(qFromLittleEndian(dp)); dp += 2; break; case U32: - row[i] = QVariant(UINT32(dp)); + row[i] = QVariant(qFromLittleEndian(dp)); dp += 4; break; default: @@ -327,13 +323,14 @@ bool ISO8211::readRecord(Record &record) FieldsMap::const_iterator it(_map.find(def.tag)); if (it == _map.constEnd()) { - _errorString = QString("%1: unknown record").arg(QString(def.tag)); + _errorString = QString("%1: unknown record") + .arg(QByteArray((char*)&def.tag, 4)); return false; } if (!readUDA(pos, def, it->defs(), it->repeat(), data)) { _errorString = QString("Error reading %1 record") - .arg(QString(def.tag)); + .arg(QByteArray((char*)&def.tag, 4)); return false; } @@ -343,8 +340,7 @@ bool ISO8211::readRecord(Record &record) return true; } - -const ISO8211::Field *ISO8211::field(const Record &record, const QByteArray &name) +const ISO8211::Field *ISO8211::field(const Record &record, quint32 name) { for (int i = 0; i < record.size(); i++) if (record.at(i).tag() == name) diff --git a/src/map/ENC/iso8211.h b/src/map/ENC/iso8211.h index bc5bd8f3..ea7e30da 100644 --- a/src/map/ENC/iso8211.h +++ b/src/map/ENC/iso8211.h @@ -4,13 +4,6 @@ #include #include #include -#include - -#define UINT32(x) \ - (((quint32)*(const uchar*)(x)) \ - | ((quint32)(*((const uchar*)(x) + 1)) << 8) \ - | ((quint32)(*((const uchar*)(x) + 2)) << 16) \ - | ((quint32)(*((const uchar*)(x) + 3)) << 24)) namespace ENC { @@ -22,23 +15,22 @@ public: class Field { public: - Field() {} - Field(const QByteArray &tag, const QVector &subFields, - const Data &data) : _tag(tag), _subFields(subFields), _data(data) {} + Field() : _subFields(0) {} + Field(quint32 tag, const QVector &subFields, const Data &data) + : _tag(tag), _subFields(&subFields), _data(data) {} - const QByteArray &tag() const {return _tag;} - const QVector &subFields() const {return _subFields;} + quint32 tag() const {return _tag;} const Data &data() const {return _data;} - bool subfield(const char *name, int *val, int idx = 0) const; - bool subfield(const char *name, uint *val, int idx = 0) const; - bool subfield(const char *name, QByteArray *val, int idx = 0) const; + bool subfield(quint32 name, int *val, int idx = 0) const; + bool subfield(quint32 name, uint *val, int idx = 0) const; + bool subfield(quint32 name, QByteArray *val, int idx = 0) const; private: - const QVariant *data(const QByteArray &name, int idx = 0) const; + const QVariant *data(quint32 name, int idx = 0) const; - QByteArray _tag; - QVector _subFields; + quint32 _tag; + const QVector *_subFields; Data _data; }; @@ -50,14 +42,21 @@ public: const QString &errorString() const {return _errorString;} - static const Field *field(const Record &record, const QByteArray &name); + static const Field *field(const Record &record, quint32 name); + static constexpr quint32 NAME(const char str[4]) + { + return static_cast(str[0]) + + (static_cast(str[1]) << 8) + + (static_cast(str[2]) << 16) + + (static_cast(str[3]) << 24); + } private: enum FieldType {Unknown, String, Array, S8, S16, S32, U8, U16, U32}; struct FieldDefinition { - QByteArray tag; + quint32 tag; int pos; int size; }; @@ -81,22 +80,22 @@ private: { public: SubFields() : _repeat(false) {} - SubFields(const QVector &tags, + SubFields(const QVector &tags, const QVector &defs, bool repeat) : _tags(tags), _defs(defs), _repeat(repeat) {} - const QVector &tags() const {return _tags;} + const QVector &tags() const {return _tags;} const QVector &defs() const {return _defs;} bool repeat() const {return _repeat;} private: - QVector _tags; + QVector _tags; QVector _defs; bool _repeat; }; - typedef QMap FieldsMap; + typedef QMap FieldsMap; static SubFieldDefinition fieldType(const QString &str, int cnt); @@ -110,14 +109,6 @@ private: QString _errorString; }; -#ifndef QT_NO_DEBUG -inline QDebug operator<<(QDebug dbg, const ISO8211::Field &field) -{ - dbg.nospace() << "Field(" << field.tag() << ", " << field.subFields() << ")"; - return dbg.space(); -} -#endif // QT_NO_DEBUG - } #endif // ENC_ISO8211_H diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 210bfa4e..2c931419 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -1,3 +1,4 @@ +#include #include "GUI/units.h" #include "objects.h" #include "attributes.h" @@ -14,6 +15,19 @@ using namespace ENC; #define PRIM_L 2 #define PRIM_A 3 +constexpr quint32 RCID = ISO8211::NAME("RCID"); +constexpr quint32 SG2D = ISO8211::NAME("SG2D"); +constexpr quint32 SG3D = ISO8211::NAME("SG3D"); +constexpr quint32 FSPT = ISO8211::NAME("FSPT"); +constexpr quint32 VRPT = ISO8211::NAME("VRPT"); +constexpr quint32 ATTF = ISO8211::NAME("ATTF"); +constexpr quint32 VRID = ISO8211::NAME("VRID"); +constexpr quint32 FRID = ISO8211::NAME("FRID"); +constexpr quint32 DSPM = ISO8211::NAME("DSPM"); +constexpr quint32 COMF = ISO8211::NAME("COMF"); +constexpr quint32 SOMF = ISO8211::NAME("SOMF"); +constexpr quint32 HUNI = ISO8211::NAME("HUNI"); + static QMap orderMapInit() { QMap map; @@ -90,20 +104,20 @@ static uint order(uint type) return (it == orderMap.constEnd()) ? (type>>16) + 512 : it.value(); } -static void warning(const ISO8211::Field &FRID, uint PRIM) +static void warning(const ISO8211::Field &frid, uint prim) { - uint RCID = 0xFFFFFFFF; - FRID.subfield("RCID", &RCID); + uint rcid = 0xFFFFFFFF; + frid.subfield(RCID, &rcid); - switch (PRIM) { + switch (prim) { case PRIM_P: - qWarning("%u: invalid point feature", RCID); + qWarning("%u: invalid point feature", rcid); break; case PRIM_L: - qWarning("%u: invalid line feature", RCID); + qWarning("%u: invalid line feature", rcid); break; case PRIM_A: - qWarning("%u: invalid area feature", RCID); + qWarning("%u: invalid area feature", rcid); break; } } @@ -132,7 +146,7 @@ static bool parseNAME(const ISO8211::Field *f, quint8 *type, quint32 *id, return false; *type = (quint8)(*ba.constData()); - *id = UINT32(ba.constData() + 1); + *id = qFromLittleEndian(ba.constData() + 1); return true; } @@ -141,9 +155,9 @@ static const ISO8211::Field *SGXD(const ISO8211::Record &r) { const ISO8211::Field *f; - if ((f = ISO8211::field(r, "SG2D"))) + if ((f = ISO8211::field(r, SG2D))) return f; - else if ((f = ISO8211::field(r, "SG3D"))) + else if ((f = ISO8211::field(r, SG3D))) return f; else return 0; @@ -212,12 +226,12 @@ static bool linePointCb(const MapData::Line *line, void *context) return true; } -static Coordinates coordinates(int x, int y, uint COMF) +static Coordinates coordinates(int x, int y, uint comf) { - return Coordinates(x / (double)COMF, y / (double)COMF); + return Coordinates(x / (double)comf, y / (double)comf); } -static Coordinates point(const ISO8211::Record &r, uint COMF) +static Coordinates point(const ISO8211::Record &r, uint comf) { const ISO8211::Field *f = SGXD(r); if (!f) @@ -226,7 +240,7 @@ static Coordinates point(const ISO8211::Record &r, uint COMF) int y = f->data().at(0).at(0).toInt(); int x = f->data().at(0).at(1).toInt(); - return coordinates(x, y, COMF); + return coordinates(x, y, comf); } static uint depthLevel(double minDepth) @@ -477,10 +491,10 @@ RectC MapData::Line::bounds() const } QVector MapData::soundings(const ISO8211::Record &r, - uint COMF, uint SOMF) + uint comf, uint somf) { QVector s; - const ISO8211::Field *f = ISO8211::field(r, "SG3D"); + const ISO8211::Field *f = ISO8211::field(r, SG3D); if (!f) return QVector(); @@ -489,24 +503,24 @@ QVector MapData::soundings(const ISO8211::Record &r, int y = f->data().at(i).at(0).toInt(); int x = f->data().at(i).at(1).toInt(); int z = f->data().at(i).at(2).toInt(); - s.append(Sounding(coordinates(x, y, COMF), z / (double)SOMF)); + s.append(Sounding(coordinates(x, y, comf), z / (double)somf)); } return s; } QVector MapData::soundingGeometry(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF, uint SOMF) + const RecordMap &vi, const RecordMap &vc, uint comf, uint somf) { quint8 type; quint32 id; RecordMapIterator it; - const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT"); - if (!FSPT || FSPT->data().at(0).size() != 4) + const ISO8211::Field *fspt = ISO8211::field(r, FSPT); + if (!fspt || fspt->data().at(0).size() != 4) return QVector(); - if (!parseNAME(FSPT, &type, &id)) + if (!parseNAME(fspt, &type, &id)) return QVector(); if (type == RCNM_VI) { @@ -520,21 +534,21 @@ QVector MapData::soundingGeometry(const ISO8211::Record &r, } else return QVector(); - return soundings(it.value(), COMF, SOMF); + return soundings(it.value(), comf, somf); } Coordinates MapData::pointGeometry(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF) + const RecordMap &vi, const RecordMap &vc, uint comf) { quint8 type; quint32 id; RecordMapIterator it; - const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT"); - if (!FSPT || FSPT->data().at(0).size() != 4) + const ISO8211::Field *fspt = ISO8211::field(r, FSPT); + if (!fspt || fspt->data().at(0).size() != 4) return Coordinates(); - if (!parseNAME(FSPT, &type, &id)) + if (!parseNAME(fspt, &type, &id)) return Coordinates(); if (type == RCNM_VI) { @@ -548,55 +562,55 @@ Coordinates MapData::pointGeometry(const ISO8211::Record &r, } else return Coordinates(); - return point(it.value(), COMF); + return point(it.value(), comf); } QVector MapData::lineGeometry(const ISO8211::Record &r, - const RecordMap &vc, const RecordMap &ve, uint COMF) + const RecordMap &vc, const RecordMap &ve, uint comf) { QVector path; Coordinates c[2]; - uint ORNT; + uint ornt; quint8 type; quint32 id; - const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT"); - if (!FSPT || FSPT->data().at(0).size() != 4) + const ISO8211::Field *fspt = ISO8211::field(r, FSPT); + if (!fspt || fspt->data().at(0).size() != 4) return QVector(); - for (int i = 0; i < FSPT->data().size(); i++) { - if (!parseNAME(FSPT, &type, &id, i) || type != RCNM_VE) + for (int i = 0; i < fspt->data().size(); i++) { + if (!parseNAME(fspt, &type, &id, i) || type != RCNM_VE) return QVector(); - ORNT = FSPT->data().at(i).at(1).toUInt(); + ornt = fspt->data().at(i).at(1).toUInt(); RecordMapIterator it = ve.find(id); if (it == ve.constEnd()) return QVector(); - const ISO8211::Record &FRID = it.value(); - const ISO8211::Field *VRPT = ISO8211::field(FRID, "VRPT"); - if (!VRPT || VRPT->data().size() != 2) + const ISO8211::Record &frid = it.value(); + const ISO8211::Field *vrpt = ISO8211::field(frid, VRPT); + if (!vrpt || vrpt->data().size() != 2) return QVector(); for (int j = 0; j < 2; j++) { - if (!parseNAME(VRPT, &type, &id, j) || type != RCNM_VC) + if (!parseNAME(vrpt, &type, &id, j) || type != RCNM_VC) return QVector(); RecordMapIterator jt = vc.find(id); if (jt == vc.constEnd()) return QVector(); - c[j] = point(jt.value(), COMF); + c[j] = point(jt.value(), comf); if (c[j].isNull()) return QVector(); } - const ISO8211::Field *vertexes = SGXD(FRID); - if (ORNT == 2) { + const ISO8211::Field *vertexes = SGXD(frid); + if (ornt == 2) { path.append(c[1]); if (vertexes) { for (int j = vertexes->data().size() - 1; j >= 0; j--) { const QVector &cv = vertexes->data().at(j); path.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(), - COMF)); + comf)); } } path.append(c[0]); @@ -606,7 +620,7 @@ QVector MapData::lineGeometry(const ISO8211::Record &r, for (int j = 0; j < vertexes->data().size(); j++) { const QVector &cv = vertexes->data().at(j); path.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(), - COMF)); + comf)); } } path.append(c[1]); @@ -617,26 +631,26 @@ QVector MapData::lineGeometry(const ISO8211::Record &r, } Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc, - const RecordMap &ve, uint COMF) + const RecordMap &ve, uint comf) { Polygon path; QVector v; Coordinates c[2]; - uint ORNT, USAG; + uint ornt, usag; quint8 type; quint32 id; - const ISO8211::Field *FSPT = ISO8211::field(r, "FSPT"); - if (!FSPT || FSPT->data().at(0).size() != 4) + const ISO8211::Field *fspt = ISO8211::field(r, FSPT); + if (!fspt || fspt->data().at(0).size() != 4) return Polygon(); - for (int i = 0; i < FSPT->data().size(); i++) { - if (!parseNAME(FSPT, &type, &id, i) || type != RCNM_VE) + for (int i = 0; i < fspt->data().size(); i++) { + if (!parseNAME(fspt, &type, &id, i) || type != RCNM_VE) return Polygon(); - ORNT = FSPT->data().at(i).at(1).toUInt(); - USAG = FSPT->data().at(i).at(2).toUInt(); + ornt = fspt->data().at(i).at(1).toUInt(); + usag = fspt->data().at(i).at(2).toUInt(); - if (USAG == 2 && path.isEmpty()) { + if (usag == 2 && path.isEmpty()) { path.append(v); v.clear(); } @@ -644,55 +658,55 @@ Polygon MapData::polyGeometry(const ISO8211::Record &r, const RecordMap &vc, RecordMapIterator it = ve.find(id); if (it == ve.constEnd()) return Polygon(); - const ISO8211::Record &FRID = it.value(); - const ISO8211::Field *VRPT = ISO8211::field(FRID, "VRPT"); - if (!VRPT || VRPT->data().size() != 2) + const ISO8211::Record &frid = it.value(); + const ISO8211::Field *vrpt = ISO8211::field(frid, VRPT); + if (!vrpt || vrpt->data().size() != 2) return Polygon(); for (int j = 0; j < 2; j++) { - if (!parseNAME(VRPT, &type, &id, j) || type != RCNM_VC) + if (!parseNAME(vrpt, &type, &id, j) || type != RCNM_VC) return Polygon(); RecordMapIterator jt = vc.find(id); if (jt == vc.constEnd()) return Polygon(); - c[j] = point(jt.value(), COMF); + c[j] = point(jt.value(), comf); if (c[j].isNull()) return Polygon(); } - const ISO8211::Field *vertexes = SGXD(FRID); - if (ORNT == 2) { + const ISO8211::Field *vertexes = SGXD(frid); + if (ornt == 2) { v.append(c[1]); - if (USAG == 3) + if (usag == 3) v.append(Coordinates()); if (vertexes) { for (int j = vertexes->data().size() - 1; j >= 0; j--) { const QVector &cv = vertexes->data().at(j); v.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(), - COMF)); + comf)); } } - if (USAG == 3) + if (usag == 3) v.append(Coordinates()); v.append(c[0]); } else { v.append(c[0]); - if (USAG == 3) + if (usag == 3) v.append(Coordinates()); if (vertexes) { for (int j = 0; j < vertexes->data().size(); j++) { const QVector &cv = vertexes->data().at(j); v.append(coordinates(cv.at(1).toInt(), cv.at(0).toInt(), - COMF)); + comf)); } } - if (USAG == 3) + if (usag == 3) v.append(Coordinates()); v.append(c[1]); } - if (USAG == 2 && v.first() == v.last()) { + if (usag == 2 && v.first() == v.last()) { path.append(v); v.clear(); } @@ -708,12 +722,12 @@ MapData::Attributes MapData::attributes(const ISO8211::Record &r) { Attributes attr; - const ISO8211::Field *ATTF = ISO8211::field(r, "ATTF"); - if (!(ATTF && ATTF->data().at(0).size() == 2)) + const ISO8211::Field *attf = ISO8211::field(r, ATTF); + if (!(attf && attf->data().at(0).size() == 2)) return attr; - for (int i = 0; i < ATTF->data().size(); i++) { - const QVector &av = ATTF->data().at(i); + for (int i = 0; i < attf->data().size(); i++) { + const QVector &av = attf->data().at(i); attr.insert(av.at(0).toUInt(), av.at(1).toByteArray()); } @@ -726,64 +740,64 @@ MapData::Point *MapData::pointObject(const Sounding &s) } MapData::Point *MapData::pointObject(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF, uint OBJL, uint HUNI) + const RecordMap &vi, const RecordMap &vc, uint comf, uint objl, uint huni) { - Coordinates c(pointGeometry(r, vi, vc, COMF)); - return (c.isNull() ? 0 : new Point(OBJL, c, attributes(r), HUNI)); + Coordinates c(pointGeometry(r, vi, vc, comf)); + return (c.isNull() ? 0 : new Point(objl, c, attributes(r), huni)); } MapData::Line *MapData::lineObject(const ISO8211::Record &r, - const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL) + const RecordMap &vc, const RecordMap &ve, uint comf, uint objl) { - QVector path(lineGeometry(r, vc, ve, COMF)); - return (path.isEmpty() ? 0 : new Line(OBJL, path, attributes(r))); + QVector path(lineGeometry(r, vc, ve, comf)); + return (path.isEmpty() ? 0 : new Line(objl, path, attributes(r))); } MapData::Poly *MapData::polyObject(const ISO8211::Record &r, - const RecordMap &vc, const RecordMap &ve, uint COMF, uint OBJL, uint HUNI) + const RecordMap &vc, const RecordMap &ve, uint comf, uint objl, uint huni) { - Polygon path(polyGeometry(r, vc, ve, COMF)); - return (path.isEmpty() ? 0 : new Poly(OBJL, path, attributes(r), HUNI)); + Polygon path(polyGeometry(r, vc, ve, comf)); + return (path.isEmpty() ? 0 : new Poly(objl, path, attributes(r), huni)); } bool MapData::processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, - RecordMap &vf, uint &COMF, uint &SOMF, uint &HUNI) + RecordMap &vf, uint &comf, uint &somf, uint &huni) { if (record.size() < 2) return false; const ISO8211::Field &f = record.at(1); - const QByteArray &ba = f.tag(); + quint32 tag = f.tag(); - if (ba == "VRID") { + if (tag == VRID) { if (f.data().at(0).size() < 2) return false; - int RCNM = f.data().at(0).at(0).toInt(); - uint RCID = f.data().at(0).at(1).toUInt(); + int rcnm = f.data().at(0).at(0).toInt(); + uint rcid = f.data().at(0).at(1).toUInt(); - switch (RCNM) { + switch (rcnm) { case RCNM_VI: - vi.insert(RCID, record); + vi.insert(rcid, record); break; case RCNM_VC: - vc.insert(RCID, record); + vc.insert(rcid, record); break; case RCNM_VE: - ve.insert(RCID, record); + ve.insert(rcid, record); break; case RCNM_VF: - vf.insert(RCID, record); + vf.insert(rcid, record); break; default: return false; } - } else if (ba == "FRID") { + } else if (tag == FRID) { fe.append(record); - } else if (ba == "DSPM") { - if (!(f.subfield("COMF", &COMF) && f.subfield("SOMF", &SOMF))) + } else if (tag == DSPM) { + if (!(f.subfield(COMF, &comf) && f.subfield(SOMF, &somf))) return false; - if (!f.subfield("HUNI", &HUNI)) + if (!f.subfield(HUNI, &huni)) return false; } @@ -796,7 +810,7 @@ MapData::MapData(const QString &path) QVector fe; ISO8211 ddf(path); ISO8211::Record record; - uint PRIM, OBJL, COMF = 1, SOMF = 1, HUNI = 1; + uint prim, objl, comf = 1, somf = 1, huni = 1; Poly *poly; Line *line; Point *point; @@ -806,7 +820,7 @@ MapData::MapData(const QString &path) if (!ddf.readDDR()) return; while (ddf.readRecord(record)) - if (!processRecord(record, fe, vi, vc, ve, vf, COMF, SOMF, HUNI)) + if (!processRecord(record, fe, vi, vc, ve, vf, comf, somf, huni)) qWarning("Invalid S-57 record"); for (int i = 0; i < fe.size(); i++) { @@ -815,39 +829,39 @@ MapData::MapData(const QString &path) if (f.data().at(0).size() < 5) continue; - PRIM = f.data().at(0).at(2).toUInt(); - OBJL = f.data().at(0).at(4).toUInt(); + prim = f.data().at(0).at(2).toUInt(); + objl = f.data().at(0).at(4).toUInt(); - switch (PRIM) { + switch (prim) { case PRIM_P: - if (OBJL == SOUNDG) { - QVector s(soundingGeometry(r, vi, vc, COMF, SOMF)); + if (objl == SOUNDG) { + QVector s(soundingGeometry(r, vi, vc, comf, somf)); for (int i = 0; i < s.size(); i++) { point = pointObject(s.at(i)); pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } } else { - if ((point = pointObject(r, vi, vc, COMF, OBJL, HUNI))) { + if ((point = pointObject(r, vi, vc, comf, objl, huni))) { pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } else - warning(f, PRIM); + warning(f, prim); } break; case PRIM_L: - if ((line = lineObject(r, vc, ve, COMF, OBJL))) { + if ((line = lineObject(r, vc, ve, comf, objl))) { rectcBounds(line->bounds(), min, max); _lines.Insert(min, max, line); } else - warning(f, PRIM); + warning(f, prim); break; case PRIM_A: - if ((poly = polyObject(r, vc, ve, COMF, OBJL, HUNI))) { + if ((poly = polyObject(r, vc, ve, comf, objl, huni))) { rectcBounds(poly->bounds(), min, max); _areas.Insert(min, max, poly); } else - warning(f, PRIM); + warning(f, prim); break; } } diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index a767c790..6824173f 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -32,28 +32,28 @@ private: typedef RTree LineTree; typedef RTree PointTree; - static QVector soundings(const ISO8211::Record &r, uint COMF, - uint SOMF); + static QVector soundings(const ISO8211::Record &r, uint comf, + uint somf); static QVector soundingGeometry(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF, uint SOMF); + const RecordMap &vi, const RecordMap &vc, uint comf, uint somf); static Coordinates pointGeometry(const ISO8211::Record &r, - const RecordMap &vi, const RecordMap &vc, uint COMF); + const RecordMap &vi, const RecordMap &vc, uint comf); static QVector lineGeometry(const ISO8211::Record &r, - const RecordMap &vc, const RecordMap &ve, uint COMF); + const RecordMap &vc, const RecordMap &ve, uint comf); static Polygon polyGeometry(const ISO8211::Record &r, const RecordMap &vc, - const RecordMap &ve, uint COMF); + const RecordMap &ve, uint comf); static Attributes attributes(const ISO8211::Record &r); static Point *pointObject(const Sounding &s); static Point *pointObject(const ISO8211::Record &r, const RecordMap &vi, - const RecordMap &vc, uint COMF, uint OBJL, uint HUNI); + const RecordMap &vc, uint comf, uint objl, uint huni); static Line *lineObject(const ISO8211::Record &r, const RecordMap &vc, - const RecordMap &ve, uint COMF, uint OBJL); + const RecordMap &ve, uint comf, uint objl); static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc, - const RecordMap &ve, uint COMF, uint OBJL, uint HUNI); + const RecordMap &ve, uint comf, uint objl, uint huni); static bool processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, - RecordMap &vf, uint &COMF, uint &SOMF, uint &HUNI); + RecordMap &vf, uint &comf, uint &somf, uint &huni); PolygonTree _areas; LineTree _lines; diff --git a/src/map/encatlas.cpp b/src/map/encatlas.cpp index 52cf2ee3..29e18614 100644 --- a/src/map/encatlas.cpp +++ b/src/map/encatlas.cpp @@ -12,6 +12,14 @@ using namespace ENC; #define EPSILON 1e-6 #define TILE_SIZE 512 +constexpr quint32 CATD = ISO8211::NAME("CATD"); +constexpr quint32 IMPL = ISO8211::NAME("IMPL"); +constexpr quint32 F1LE = ISO8211::NAME("FILE"); +constexpr quint32 SLAT = ISO8211::NAME("SLAT"); +constexpr quint32 WLON = ISO8211::NAME("WLON"); +constexpr quint32 NLAT = ISO8211::NAME("NLAT"); +constexpr quint32 ELON = ISO8211::NAME("ELON"); + Range ENCAtlas::zooms(IntendedUsage usage) { switch (usage) { @@ -60,35 +68,34 @@ bool ENCAtlas::processRecord(const ISO8211::Record &record, QByteArray &file, return false; const ENC::ISO8211::Field &f = record.at(1); - const QByteArray &ba = f.tag(); - if (ba == "CATD") { - QByteArray FILE, IMPL; + if (f.tag() == CATD) { + QByteArray impl; - if (!f.subfield("IMPL", &IMPL)) + if (!f.subfield(IMPL, &impl)) return false; - if (!f.subfield("FILE", &FILE)) + if (!f.subfield(F1LE, &file)) return false; - if (IMPL == "BIN" && FILE.endsWith("000")) { - QByteArray SLAT, WLON, NLAT, ELON; + if (impl == "BIN" && file.endsWith("000")) { + QByteArray slat, wlon, nlat, elon; - if (!f.subfield("SLAT", &SLAT)) + if (!f.subfield(SLAT, &slat)) return false; - if (!f.subfield("WLON", &WLON)) + if (!f.subfield(WLON, &wlon)) return false; - if (!f.subfield("NLAT", &NLAT)) + if (!f.subfield(NLAT, &nlat)) return false; - if (!f.subfield("ELON", &ELON)) + if (!f.subfield(ELON, &elon)) return false; bool ok1, ok2, ok3, ok4; - bounds = RectC(Coordinates(WLON.toDouble(&ok1), NLAT.toDouble(&ok2)), - Coordinates(ELON.toDouble(&ok3), SLAT.toDouble(&ok4))); + bounds = RectC(Coordinates(wlon.toDouble(&ok1), nlat.toDouble(&ok2)), + Coordinates(elon.toDouble(&ok3), slat.toDouble(&ok4))); if (!(ok1 && ok2 && ok3 && ok4)) return false; - file = FILE.replace('\\', '/'); + file.replace('\\', '/'); return true; } diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index 6aa687bc..e6792be3 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -15,6 +15,14 @@ using namespace ENC; #define EPSILON 1e-6 #define TILE_SIZE 512 +constexpr quint32 SG2D = ISO8211::NAME("SG2D"); +constexpr quint32 SG3D = ISO8211::NAME("SG3D"); +constexpr quint32 VRID = ISO8211::NAME("VRID"); +constexpr quint32 DSID = ISO8211::NAME("DSID"); +constexpr quint32 DSNM = ISO8211::NAME("DSNM"); +constexpr quint32 DSPM = ISO8211::NAME("DSPM"); +constexpr quint32 COMF = ISO8211::NAME("COMF"); + static Range zooms(const RectC &bounds) { double size = qMin(bounds.width(), bounds.height()); @@ -57,9 +65,9 @@ static const ISO8211::Field *SGXD(const ISO8211::Record &r) { const ISO8211::Field *f; - if ((f = ISO8211::field(r, "SG2D"))) + if ((f = ISO8211::field(r, SG2D))) return f; - else if ((f = ISO8211::field(r, "SG3D"))) + else if ((f = ISO8211::field(r, SG3D))) return f; else return 0; @@ -97,23 +105,21 @@ bool ENCMap::bounds(const QVector &gv, Rect &b) } bool ENCMap::processRecord(const ISO8211::Record &record, - QVector &rv, uint &COMF, QString &name) + QVector &rv, uint &comf, QByteArray &dsnm) { if (record.size() < 2) return false; const ISO8211::Field &f = record.at(1); - const QByteArray &ba = f.tag(); + quint32 tag = f.tag(); - if (ba == "VRID") { + if (tag == VRID) { rv.append(record); - } else if (ba == "DSID") { - QByteArray DSNM; - if (!f.subfield("DSNM", &DSNM)) + } else if (tag == DSID) { + if (!f.subfield(DSNM, &dsnm)) return false; - name = DSNM; - } else if (ba == "DSPM") { - if (!f.subfield("COMF", &COMF)) + } else if (tag == DSPM) { + if (!f.subfield(COMF, &comf)) return false; } @@ -127,14 +133,15 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent) QVector gv; ISO8211 ddf(fileName); ISO8211::Record record; - uint COMF = 1; + uint comf = 1; + QByteArray dsnm; if (!ddf.readDDR()) { _errorString = ddf.errorString(); return; } while (ddf.readRecord(record)) { - if (!processRecord(record, gv, COMF, _name)) { + if (!processRecord(record, gv, comf, dsnm)) { _errorString = "Invalid S-57 record"; return; } @@ -144,13 +151,15 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent) return; } + _name = dsnm; + Rect b; if (!bounds(gv, b)) { _errorString = "Error fetching geometries bounds"; return; } - Coordinates tl(b.minX() / (double)COMF, b.maxY() / (double)COMF); - Coordinates br(b.maxX() / (double)COMF, b.minY() / (double)COMF); + Coordinates tl(b.minX() / (double)comf, b.maxY() / (double)comf); + Coordinates br(b.maxX() / (double)comf, b.minY() / (double)comf); _llBounds = RectC(tl, br); if (!_llBounds.isValid()) { _errorString = "Invalid geometries bounds"; diff --git a/src/map/encmap.h b/src/map/encmap.h index b257d10e..6d66b043 100644 --- a/src/map/encmap.h +++ b/src/map/encmap.h @@ -97,7 +97,7 @@ private: static bool bounds(const ENC::ISO8211::Record &record, Rect &rect); static bool bounds(const QVector &gv, Rect &b); static bool processRecord(const ENC::ISO8211::Record &record, - QVector &rv, uint &COMF, QString &name); + QVector &rv, uint &comf, QByteArray &dsnm); QString _name; ENC::MapData *_data; From 1aa0fa4be425816af870625eb03a1e5244c822a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 17 Apr 2025 20:37:30 +0200 Subject: [PATCH 04/10] Fixed Qt5 build --- src/map/ENC/iso8211.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index 6f497074..c65252f5 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -219,7 +219,7 @@ bool ISO8211::readDDR() SubFields def; if (!readDDA(fields.at(i), def)) { _errorString = QString("Error reading %1 DDA field") - .arg(QByteArray((char*)&fields.at(i).tag, 4)); + .arg(QString(QByteArray((char*)&fields.at(i).tag, 4))); return false; } _map.insert(fields.at(i).tag, def); @@ -324,13 +324,13 @@ bool ISO8211::readRecord(Record &record) FieldsMap::const_iterator it(_map.find(def.tag)); if (it == _map.constEnd()) { _errorString = QString("%1: unknown record") - .arg(QByteArray((char*)&def.tag, 4)); + .arg(QString(QByteArray((char*)&def.tag, 4))); return false; } if (!readUDA(pos, def, it->defs(), it->repeat(), data)) { _errorString = QString("Error reading %1 record") - .arg(QByteArray((char*)&def.tag, 4)); + .arg(QString(QByteArray((char*)&def.tag, 4))); return false; } From 372f2966bb574ed1ccc3c23027f58288efddf6c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Thu, 17 Apr 2025 20:58:27 +0200 Subject: [PATCH 05/10] Properly print the tag name on big-edian systems --- src/map/ENC/iso8211.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index c65252f5..40a1d05d 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -218,8 +218,10 @@ bool ISO8211::readDDR() for (int i = 0; i < fields.size(); i++) { SubFields def; if (!readDDA(fields.at(i), def)) { + QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized); + qToLittleEndian(fields.at(i).tag, tag.data()); _errorString = QString("Error reading %1 DDA field") - .arg(QString(QByteArray((char*)&fields.at(i).tag, 4))); + .arg(QString(tag)); return false; } _map.insert(fields.at(i).tag, def); @@ -323,14 +325,16 @@ bool ISO8211::readRecord(Record &record) FieldsMap::const_iterator it(_map.find(def.tag)); if (it == _map.constEnd()) { - _errorString = QString("%1: unknown record") - .arg(QString(QByteArray((char*)&def.tag, 4))); + QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized); + qToLittleEndian(def.tag, tag.data()); + _errorString = QString("%1: unknown record").arg(QString(tag)); return false; } if (!readUDA(pos, def, it->defs(), it->repeat(), data)) { - _errorString = QString("Error reading %1 record") - .arg(QString(QByteArray((char*)&def.tag, 4))); + QByteArray tag(sizeof(quint32), Qt::Initialization::Uninitialized); + qToLittleEndian(def.tag, tag.data()); + _errorString = QString("Error reading %1 record").arg(QString(tag)); return false; } From b9396e6bbd9f1119a9a8d223030739f8c9274a9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 21 Apr 2025 17:32:11 +0200 Subject: [PATCH 06/10] Version++ --- .appveyor.yml | 2 +- gpxsee.pro | 2 +- pkg/windows/gpxsee64.nsi | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/.appveyor.yml b/.appveyor.yml index 1db0c37d..d9ec599f 100644 --- a/.appveyor.yml +++ b/.appveyor.yml @@ -1,4 +1,4 @@ -version: 13.39.{build} +version: 13.40.{build} configuration: - Release diff --git a/gpxsee.pro b/gpxsee.pro index cd2a4ac9..40a7e5a2 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -3,7 +3,7 @@ unix:!macx:!android { } else { TARGET = GPXSee } -VERSION = 13.39 +VERSION = 13.40 QT += core \ gui \ diff --git a/pkg/windows/gpxsee64.nsi b/pkg/windows/gpxsee64.nsi index 11a0af88..1105db8d 100644 --- a/pkg/windows/gpxsee64.nsi +++ b/pkg/windows/gpxsee64.nsi @@ -49,7 +49,7 @@ Unicode true ; The name of the installer Name "GPXSee" ; Program version -!define VERSION "13.39" +!define VERSION "13.40" ; The file to write OutFile "GPXSee-${VERSION}_x64.exe" From b6c7fe9cd1e3071d86b42682b7abee39791f29a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 21 Apr 2025 17:32:46 +0200 Subject: [PATCH 07/10] Assure that ddf data is valid when accessing it --- src/map/ENC/iso8211.cpp | 22 +++++++++++----------- src/map/ENC/iso8211.h | 15 ++++++++------- src/map/ENC/mapdata.cpp | 41 +++++++++++++++++++++-------------------- src/map/ENC/mapdata.h | 2 +- src/map/encatlas.cpp | 22 +++++++++++----------- src/map/encatlas.h | 4 ++-- src/map/encmap.cpp | 8 ++++---- src/map/encmap.h | 5 +++-- 8 files changed, 61 insertions(+), 58 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index 40a1d05d..73e90191 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -22,23 +22,22 @@ struct DR { char FieldTagSize; }; - -const QVariant *ISO8211::Field::data(quint32 name, int idx) const +const QVariant *ISO8211::data(const Field &field, quint32 name, int idx) const { - const QVector &v = _data.at(idx); + const QVector &v = field.data().at(idx); - for (int i = 0; i < _subFields->size(); i++) - if (_subFields->at(i) == name) + for (int i = 0; i < field.subFields()->size(); i++) + if (field.subFields()->at(i) == name) return &v.at(i); return 0; } -bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, int *val, int idx) const { bool ok; - const QVariant *v = data(name, idx); + const QVariant *v = data(field, name, idx); if (!v) return false; *val = v->toInt(&ok); @@ -46,11 +45,11 @@ bool ISO8211::Field::subfield(quint32 name, int *val, int idx) const return ok; } -bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, uint *val, int idx) const { bool ok; - const QVariant *v = data(name, idx); + const QVariant *v = data(field, name, idx); if (!v) return false; *val = v->toUInt(&ok); @@ -58,9 +57,10 @@ bool ISO8211::Field::subfield(quint32 name, uint *val, int idx) const return ok; } -bool ISO8211::Field::subfield(quint32 name, QByteArray *val, int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, QByteArray *val, + int idx) const { - const QVariant *v = data(name, idx); + const QVariant *v = data(field, name, idx); if (!v) return false; *val = v->toByteArray(); diff --git a/src/map/ENC/iso8211.h b/src/map/ENC/iso8211.h index ea7e30da..9d8d6b51 100644 --- a/src/map/ENC/iso8211.h +++ b/src/map/ENC/iso8211.h @@ -15,20 +15,15 @@ public: class Field { public: - Field() : _subFields(0) {} + Field() : _tag(0), _subFields(0) {} Field(quint32 tag, const QVector &subFields, const Data &data) : _tag(tag), _subFields(&subFields), _data(data) {} quint32 tag() const {return _tag;} const Data &data() const {return _data;} - - bool subfield(quint32 name, int *val, int idx = 0) const; - bool subfield(quint32 name, uint *val, int idx = 0) const; - bool subfield(quint32 name, QByteArray *val, int idx = 0) const; + const QVector *subFields() const {return _subFields;} private: - const QVariant *data(quint32 name, int idx = 0) const; - quint32 _tag; const QVector *_subFields; Data _data; @@ -40,6 +35,11 @@ public: bool readDDR(); bool readRecord(Record &record); + bool subfield(const Field &field, quint32 name, int *val, int idx = 0) const; + bool subfield(const Field &field, quint32 name, uint *val, int idx = 0) const; + bool subfield(const Field &field, quint32 name, QByteArray *val, + int idx = 0) const; + const QString &errorString() const {return _errorString;} static const Field *field(const Record &record, quint32 name); @@ -103,6 +103,7 @@ private: bool readDDA(const FieldDefinition &def, SubFields &fields); bool readUDA(quint64 pos, const FieldDefinition &def, const QVector &fields, bool repeat, Data &data); + const QVariant *data(const Field &field, quint32 name, int idx = 0) const; QFile _file; FieldsMap _map; diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 2c931419..98ea0828 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -104,21 +104,22 @@ static uint order(uint type) return (it == orderMap.constEnd()) ? (type>>16) + 512 : it.value(); } -static void warning(const ISO8211::Field &frid, uint prim) +static void warning(const ISO8211 &ddf, const ISO8211::Field &frid, uint prim) { - uint rcid = 0xFFFFFFFF; - frid.subfield(RCID, &rcid); + uint rcid; - switch (prim) { - case PRIM_P: - qWarning("%u: invalid point feature", rcid); - break; - case PRIM_L: - qWarning("%u: invalid line feature", rcid); - break; - case PRIM_A: - qWarning("%u: invalid area feature", rcid); - break; + if (ddf.subfield(frid, RCID, &rcid)) { + switch (prim) { + case PRIM_P: + qWarning("%u: invalid point feature", rcid); + break; + case PRIM_L: + qWarning("%u: invalid line feature", rcid); + break; + case PRIM_A: + qWarning("%u: invalid area feature", rcid); + break; + } } } @@ -760,7 +761,7 @@ MapData::Poly *MapData::polyObject(const ISO8211::Record &r, return (path.isEmpty() ? 0 : new Poly(objl, path, attributes(r), huni)); } -bool MapData::processRecord(const ISO8211::Record &record, +bool MapData::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, RecordMap &vf, uint &comf, uint &somf, uint &huni) { @@ -795,9 +796,9 @@ bool MapData::processRecord(const ISO8211::Record &record, } else if (tag == FRID) { fe.append(record); } else if (tag == DSPM) { - if (!(f.subfield(COMF, &comf) && f.subfield(SOMF, &somf))) + if (!(ddf.subfield(f, COMF, &comf) && ddf.subfield(f, SOMF, &somf))) return false; - if (!f.subfield(HUNI, &huni)) + if (!ddf.subfield(f, HUNI, &huni)) return false; } @@ -820,7 +821,7 @@ MapData::MapData(const QString &path) if (!ddf.readDDR()) return; while (ddf.readRecord(record)) - if (!processRecord(record, fe, vi, vc, ve, vf, comf, somf, huni)) + if (!processRecord(ddf, record, fe, vi, vc, ve, vf, comf, somf, huni)) qWarning("Invalid S-57 record"); for (int i = 0; i < fe.size(); i++) { @@ -846,7 +847,7 @@ MapData::MapData(const QString &path) pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } else - warning(f, prim); + warning(ddf, f, prim); } break; case PRIM_L: @@ -854,14 +855,14 @@ MapData::MapData(const QString &path) rectcBounds(line->bounds(), min, max); _lines.Insert(min, max, line); } else - warning(f, prim); + warning(ddf, f, prim); break; case PRIM_A: if ((poly = polyObject(r, vc, ve, comf, objl, huni))) { rectcBounds(poly->bounds(), min, max); _areas.Insert(min, max, poly); } else - warning(f, prim); + warning(ddf, f, prim); break; } } diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index 6824173f..a7202bf9 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -51,7 +51,7 @@ private: static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint comf, uint objl, uint huni); - static bool processRecord(const ISO8211::Record &record, + static bool processRecord(const ISO8211 &ddf, const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, RecordMap &vf, uint &comf, uint &somf, uint &huni); diff --git a/src/map/encatlas.cpp b/src/map/encatlas.cpp index 29e18614..b2a342cf 100644 --- a/src/map/encatlas.cpp +++ b/src/map/encatlas.cpp @@ -61,32 +61,32 @@ ENCAtlas::IntendedUsage ENCAtlas::usage(const QString &path) return (IntendedUsage)iu; } -bool ENCAtlas::processRecord(const ISO8211::Record &record, QByteArray &file, - RectC &bounds) +bool ENCAtlas::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, + QByteArray &file, RectC &bounds) { if (record.size() < 2) return false; - const ENC::ISO8211::Field &f = record.at(1); + const ENC::ISO8211::Field &field = record.at(1); - if (f.tag() == CATD) { + if (field.tag() == CATD) { QByteArray impl; - if (!f.subfield(IMPL, &impl)) + if (!ddf.subfield(field, IMPL, &impl)) return false; - if (!f.subfield(F1LE, &file)) + if (!ddf.subfield(field, F1LE, &file)) return false; if (impl == "BIN" && file.endsWith("000")) { QByteArray slat, wlon, nlat, elon; - if (!f.subfield(SLAT, &slat)) + if (!ddf.subfield(field, SLAT, &slat)) return false; - if (!f.subfield(WLON, &wlon)) + if (!ddf.subfield(field, WLON, &wlon)) return false; - if (!f.subfield(NLAT, &nlat)) + if (!ddf.subfield(field, NLAT, &nlat)) return false; - if (!f.subfield(ELON, &elon)) + if (!ddf.subfield(field, ELON, &elon)) return false; bool ok1, ok2, ok3, ok4; @@ -142,7 +142,7 @@ ENCAtlas::ENCAtlas(const QString &fileName, QObject *parent) return; } while (ddf.readRecord(record)) { - if (processRecord(record, file, bounds)) + if (processRecord(ddf, record, file, bounds)) addMap(dir, file, bounds); } if (!ddf.errorString().isNull()) { diff --git a/src/map/encatlas.h b/src/map/encatlas.h index e5fdd8f7..1e8886d6 100644 --- a/src/map/encatlas.h +++ b/src/map/encatlas.h @@ -76,8 +76,8 @@ private: void addMap(const QDir &dir, const QByteArray &file, const RectC &bounds); QList levels() const; - static bool processRecord(const ENC::ISO8211::Record &record, - QByteArray &file, RectC &bounds); + static bool processRecord(const ENC::ISO8211 &ddf, + const ENC::ISO8211::Record &record, QByteArray &file, RectC &bounds); static Range zooms(IntendedUsage usage); static IntendedUsage usage(const QString &path); diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index e6792be3..15402bc7 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -104,7 +104,7 @@ bool ENCMap::bounds(const QVector &gv, Rect &b) return true; } -bool ENCMap::processRecord(const ISO8211::Record &record, +bool ENCMap::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, QVector &rv, uint &comf, QByteArray &dsnm) { if (record.size() < 2) @@ -116,10 +116,10 @@ bool ENCMap::processRecord(const ISO8211::Record &record, if (tag == VRID) { rv.append(record); } else if (tag == DSID) { - if (!f.subfield(DSNM, &dsnm)) + if (!ddf.subfield(f, DSNM, &dsnm)) return false; } else if (tag == DSPM) { - if (!f.subfield(COMF, &comf)) + if (!ddf.subfield(f, COMF, &comf)) return false; } @@ -141,7 +141,7 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent) return; } while (ddf.readRecord(record)) { - if (!processRecord(record, gv, comf, dsnm)) { + if (!processRecord(ddf, record, gv, comf, dsnm)) { _errorString = "Invalid S-57 record"; return; } diff --git a/src/map/encmap.h b/src/map/encmap.h index 6d66b043..eb690a02 100644 --- a/src/map/encmap.h +++ b/src/map/encmap.h @@ -96,8 +96,9 @@ private: static bool bounds(const ENC::ISO8211::Record &record, Rect &rect); static bool bounds(const QVector &gv, Rect &b); - static bool processRecord(const ENC::ISO8211::Record &record, - QVector &rv, uint &comf, QByteArray &dsnm); + static bool processRecord(const ENC::ISO8211 &ddf, + const ENC::ISO8211::Record &record, QVector &rv, + uint &comf, QByteArray &dsnm); QString _name; ENC::MapData *_data; From d6a4e237d6af3ad4721d5e8a71d39297f4af190d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 21 Apr 2025 18:40:15 +0200 Subject: [PATCH 08/10] Remove unused parameters --- src/map/ENC/iso8211.cpp | 17 ++++++++--------- src/map/ENC/iso8211.h | 9 ++++----- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index 73e90191..6c4626b5 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -22,9 +22,9 @@ struct DR { char FieldTagSize; }; -const QVariant *ISO8211::data(const Field &field, quint32 name, int idx) const +const QVariant *ISO8211::data(const Field &field, quint32 name) const { - const QVector &v = field.data().at(idx); + const QVector &v = field.data().first(); for (int i = 0; i < field.subFields()->size(); i++) if (field.subFields()->at(i) == name) @@ -33,11 +33,11 @@ const QVariant *ISO8211::data(const Field &field, quint32 name, int idx) const return 0; } -bool ISO8211::subfield(const Field &field, quint32 name, int *val, int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, int *val) const { bool ok; - const QVariant *v = data(field, name, idx); + const QVariant *v = data(field, name); if (!v) return false; *val = v->toInt(&ok); @@ -45,11 +45,11 @@ bool ISO8211::subfield(const Field &field, quint32 name, int *val, int idx) cons return ok; } -bool ISO8211::subfield(const Field &field, quint32 name, uint *val, int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, uint *val) const { bool ok; - const QVariant *v = data(field, name, idx); + const QVariant *v = data(field, name); if (!v) return false; *val = v->toUInt(&ok); @@ -57,10 +57,9 @@ bool ISO8211::subfield(const Field &field, quint32 name, uint *val, int idx) con return ok; } -bool ISO8211::subfield(const Field &field, quint32 name, QByteArray *val, - int idx) const +bool ISO8211::subfield(const Field &field, quint32 name, QByteArray *val) const { - const QVariant *v = data(field, name, idx); + const QVariant *v = data(field, name); if (!v) return false; *val = v->toByteArray(); diff --git a/src/map/ENC/iso8211.h b/src/map/ENC/iso8211.h index 9d8d6b51..fb7519ea 100644 --- a/src/map/ENC/iso8211.h +++ b/src/map/ENC/iso8211.h @@ -35,10 +35,9 @@ public: bool readDDR(); bool readRecord(Record &record); - bool subfield(const Field &field, quint32 name, int *val, int idx = 0) const; - bool subfield(const Field &field, quint32 name, uint *val, int idx = 0) const; - bool subfield(const Field &field, quint32 name, QByteArray *val, - int idx = 0) const; + bool subfield(const Field &field, quint32 name, int *val) const; + bool subfield(const Field &field, quint32 name, uint *val) const; + bool subfield(const Field &field, quint32 name, QByteArray *val) const; const QString &errorString() const {return _errorString;} @@ -103,7 +102,7 @@ private: bool readDDA(const FieldDefinition &def, SubFields &fields); bool readUDA(quint64 pos, const FieldDefinition &def, const QVector &fields, bool repeat, Data &data); - const QVariant *data(const Field &field, quint32 name, int idx = 0) const; + const QVariant *data(const Field &field, quint32 name) const; QFile _file; FieldsMap _map; From 7d7d62c786224d2f9b3ce11f6f1cb2239ab6a995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Mon, 21 Apr 2025 19:48:48 +0200 Subject: [PATCH 09/10] S-57 ISO8211 subfields can not be ommited --- src/map/ENC/iso8211.cpp | 47 +------------------------------- src/map/ENC/iso8211.h | 13 ++------- src/map/ENC/mapdata.cpp | 59 ++++++++++++++++++++++------------------- src/map/ENC/mapdata.h | 2 +- src/map/encatlas.cpp | 34 +++++++----------------- src/map/encatlas.h | 4 +-- src/map/encmap.cpp | 15 ++++++----- src/map/encmap.h | 5 ++-- 8 files changed, 58 insertions(+), 121 deletions(-) diff --git a/src/map/ENC/iso8211.cpp b/src/map/ENC/iso8211.cpp index 6c4626b5..5ee607de 100644 --- a/src/map/ENC/iso8211.cpp +++ b/src/map/ENC/iso8211.cpp @@ -22,51 +22,6 @@ struct DR { char FieldTagSize; }; -const QVariant *ISO8211::data(const Field &field, quint32 name) const -{ - const QVector &v = field.data().first(); - - for (int i = 0; i < field.subFields()->size(); i++) - if (field.subFields()->at(i) == name) - return &v.at(i); - - return 0; -} - -bool ISO8211::subfield(const Field &field, quint32 name, int *val) const -{ - bool ok; - - const QVariant *v = data(field, name); - if (!v) - return false; - *val = v->toInt(&ok); - - return ok; -} - -bool ISO8211::subfield(const Field &field, quint32 name, uint *val) const -{ - bool ok; - - const QVariant *v = data(field, name); - if (!v) - return false; - *val = v->toUInt(&ok); - - return ok; -} - -bool ISO8211::subfield(const Field &field, quint32 name, QByteArray *val) const -{ - const QVariant *v = data(field, name); - if (!v) - return false; - *val = v->toByteArray(); - - return true; -} - ISO8211::SubFieldDefinition ISO8211::fieldType(const QString &str, int cnt) { if (str == "A" || str == "I" || str == "R") @@ -337,7 +292,7 @@ bool ISO8211::readRecord(Record &record) return false; } - record[i] = Field(def.tag, it->tags(), data); + record[i] = Field(def.tag, data); } return true; diff --git a/src/map/ENC/iso8211.h b/src/map/ENC/iso8211.h index fb7519ea..992f7846 100644 --- a/src/map/ENC/iso8211.h +++ b/src/map/ENC/iso8211.h @@ -15,17 +15,14 @@ public: class Field { public: - Field() : _tag(0), _subFields(0) {} - Field(quint32 tag, const QVector &subFields, const Data &data) - : _tag(tag), _subFields(&subFields), _data(data) {} + Field() : _tag(0) {} + Field(quint32 tag, const Data &data) : _tag(tag), _data(data) {} quint32 tag() const {return _tag;} const Data &data() const {return _data;} - const QVector *subFields() const {return _subFields;} private: quint32 _tag; - const QVector *_subFields; Data _data; }; @@ -34,11 +31,6 @@ public: ISO8211(const QString &path) : _file(path) {} bool readDDR(); bool readRecord(Record &record); - - bool subfield(const Field &field, quint32 name, int *val) const; - bool subfield(const Field &field, quint32 name, uint *val) const; - bool subfield(const Field &field, quint32 name, QByteArray *val) const; - const QString &errorString() const {return _errorString;} static const Field *field(const Record &record, quint32 name); @@ -102,7 +94,6 @@ private: bool readDDA(const FieldDefinition &def, SubFields &fields); bool readUDA(quint64 pos, const FieldDefinition &def, const QVector &fields, bool repeat, Data &data); - const QVariant *data(const Field &field, quint32 name) const; QFile _file; FieldsMap _map; diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index 98ea0828..d8ca4638 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -15,7 +15,6 @@ using namespace ENC; #define PRIM_L 2 #define PRIM_A 3 -constexpr quint32 RCID = ISO8211::NAME("RCID"); constexpr quint32 SG2D = ISO8211::NAME("SG2D"); constexpr quint32 SG3D = ISO8211::NAME("SG3D"); constexpr quint32 FSPT = ISO8211::NAME("FSPT"); @@ -24,9 +23,6 @@ constexpr quint32 ATTF = ISO8211::NAME("ATTF"); constexpr quint32 VRID = ISO8211::NAME("VRID"); constexpr quint32 FRID = ISO8211::NAME("FRID"); constexpr quint32 DSPM = ISO8211::NAME("DSPM"); -constexpr quint32 COMF = ISO8211::NAME("COMF"); -constexpr quint32 SOMF = ISO8211::NAME("SOMF"); -constexpr quint32 HUNI = ISO8211::NAME("HUNI"); static QMap orderMapInit() { @@ -104,22 +100,20 @@ static uint order(uint type) return (it == orderMap.constEnd()) ? (type>>16) + 512 : it.value(); } -static void warning(const ISO8211 &ddf, const ISO8211::Field &frid, uint prim) +static void warning(const ISO8211::Field &frid, uint prim) { - uint rcid; + uint rcid = frid.data().at(0).at(1).toUInt(); - if (ddf.subfield(frid, RCID, &rcid)) { - switch (prim) { - case PRIM_P: - qWarning("%u: invalid point feature", rcid); - break; - case PRIM_L: - qWarning("%u: invalid line feature", rcid); - break; - case PRIM_A: - qWarning("%u: invalid area feature", rcid); - break; - } + switch (prim) { + case PRIM_P: + qWarning("%u: invalid point feature", rcid); + break; + case PRIM_L: + qWarning("%u: invalid line feature", rcid); + break; + case PRIM_A: + qWarning("%u: invalid area feature", rcid); + break; } } @@ -761,7 +755,7 @@ MapData::Poly *MapData::polyObject(const ISO8211::Record &r, return (path.isEmpty() ? 0 : new Poly(objl, path, attributes(r), huni)); } -bool MapData::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, +bool MapData::processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, RecordMap &vf, uint &comf, uint &somf, uint &huni) { @@ -772,10 +766,14 @@ bool MapData::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, quint32 tag = f.tag(); if (tag == VRID) { + bool nmok, idok; + if (f.data().at(0).size() < 2) return false; - int rcnm = f.data().at(0).at(0).toInt(); - uint rcid = f.data().at(0).at(1).toUInt(); + int rcnm = f.data().at(0).at(0).toInt(&nmok); + uint rcid = f.data().at(0).at(1).toUInt(&idok); + if (!(nmok && idok)) + return false; switch (rcnm) { case RCNM_VI: @@ -796,10 +794,15 @@ bool MapData::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, } else if (tag == FRID) { fe.append(record); } else if (tag == DSPM) { - if (!(ddf.subfield(f, COMF, &comf) && ddf.subfield(f, SOMF, &somf))) - return false; - if (!ddf.subfield(f, HUNI, &huni)) + bool cok, sok, hok; + + if (f.data().at(0).size() < 12) return false; + comf = f.data().at(0).at(10).toUInt(&cok); + somf = f.data().at(0).at(11).toUInt(&sok); + huni = f.data().at(0).at(7).toUInt(&hok); + + return (cok && sok && hok); } return true; @@ -821,7 +824,7 @@ MapData::MapData(const QString &path) if (!ddf.readDDR()) return; while (ddf.readRecord(record)) - if (!processRecord(ddf, record, fe, vi, vc, ve, vf, comf, somf, huni)) + if (!processRecord(record, fe, vi, vc, ve, vf, comf, somf, huni)) qWarning("Invalid S-57 record"); for (int i = 0; i < fe.size(); i++) { @@ -847,7 +850,7 @@ MapData::MapData(const QString &path) pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } else - warning(ddf, f, prim); + warning(f, prim); } break; case PRIM_L: @@ -855,14 +858,14 @@ MapData::MapData(const QString &path) rectcBounds(line->bounds(), min, max); _lines.Insert(min, max, line); } else - warning(ddf, f, prim); + warning(f, prim); break; case PRIM_A: if ((poly = polyObject(r, vc, ve, comf, objl, huni))) { rectcBounds(poly->bounds(), min, max); _areas.Insert(min, max, poly); } else - warning(ddf, f, prim); + warning(f, prim); break; } } diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index a7202bf9..6824173f 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -51,7 +51,7 @@ private: static Poly *polyObject(const ISO8211::Record &r, const RecordMap &vc, const RecordMap &ve, uint comf, uint objl, uint huni); - static bool processRecord(const ISO8211 &ddf, const ISO8211::Record &record, + static bool processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, RecordMap &vf, uint &comf, uint &somf, uint &huni); diff --git a/src/map/encatlas.cpp b/src/map/encatlas.cpp index b2a342cf..6a9b78c2 100644 --- a/src/map/encatlas.cpp +++ b/src/map/encatlas.cpp @@ -13,12 +13,6 @@ using namespace ENC; #define TILE_SIZE 512 constexpr quint32 CATD = ISO8211::NAME("CATD"); -constexpr quint32 IMPL = ISO8211::NAME("IMPL"); -constexpr quint32 F1LE = ISO8211::NAME("FILE"); -constexpr quint32 SLAT = ISO8211::NAME("SLAT"); -constexpr quint32 WLON = ISO8211::NAME("WLON"); -constexpr quint32 NLAT = ISO8211::NAME("NLAT"); -constexpr quint32 ELON = ISO8211::NAME("ELON"); Range ENCAtlas::zooms(IntendedUsage usage) { @@ -61,8 +55,8 @@ ENCAtlas::IntendedUsage ENCAtlas::usage(const QString &path) return (IntendedUsage)iu; } -bool ENCAtlas::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, - QByteArray &file, RectC &bounds) +bool ENCAtlas::processRecord(const ISO8211::Record &record, QByteArray &file, + RectC &bounds) { if (record.size() < 2) return false; @@ -70,24 +64,16 @@ bool ENCAtlas::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, const ENC::ISO8211::Field &field = record.at(1); if (field.tag() == CATD) { - QByteArray impl; - - if (!ddf.subfield(field, IMPL, &impl)) - return false; - if (!ddf.subfield(field, F1LE, &file)) + if (field.data().at(0).size() < 10) return false; + QByteArray impl = field.data().at(0).at(5).toByteArray(); + file = field.data().at(0).at(2).toByteArray(); if (impl == "BIN" && file.endsWith("000")) { - QByteArray slat, wlon, nlat, elon; - - if (!ddf.subfield(field, SLAT, &slat)) - return false; - if (!ddf.subfield(field, WLON, &wlon)) - return false; - if (!ddf.subfield(field, NLAT, &nlat)) - return false; - if (!ddf.subfield(field, ELON, &elon)) - return false; + QByteArray slat = field.data().at(0).at(6).toByteArray(); + QByteArray wlon = field.data().at(0).at(7).toByteArray(); + QByteArray nlat = field.data().at(0).at(8).toByteArray(); + QByteArray elon = field.data().at(0).at(9).toByteArray(); bool ok1, ok2, ok3, ok4; bounds = RectC(Coordinates(wlon.toDouble(&ok1), nlat.toDouble(&ok2)), @@ -142,7 +128,7 @@ ENCAtlas::ENCAtlas(const QString &fileName, QObject *parent) return; } while (ddf.readRecord(record)) { - if (processRecord(ddf, record, file, bounds)) + if (processRecord(record, file, bounds)) addMap(dir, file, bounds); } if (!ddf.errorString().isNull()) { diff --git a/src/map/encatlas.h b/src/map/encatlas.h index 1e8886d6..e5fdd8f7 100644 --- a/src/map/encatlas.h +++ b/src/map/encatlas.h @@ -76,8 +76,8 @@ private: void addMap(const QDir &dir, const QByteArray &file, const RectC &bounds); QList levels() const; - static bool processRecord(const ENC::ISO8211 &ddf, - const ENC::ISO8211::Record &record, QByteArray &file, RectC &bounds); + static bool processRecord(const ENC::ISO8211::Record &record, + QByteArray &file, RectC &bounds); static Range zooms(IntendedUsage usage); static IntendedUsage usage(const QString &path); diff --git a/src/map/encmap.cpp b/src/map/encmap.cpp index 15402bc7..1e1cd922 100644 --- a/src/map/encmap.cpp +++ b/src/map/encmap.cpp @@ -19,9 +19,7 @@ constexpr quint32 SG2D = ISO8211::NAME("SG2D"); constexpr quint32 SG3D = ISO8211::NAME("SG3D"); constexpr quint32 VRID = ISO8211::NAME("VRID"); constexpr quint32 DSID = ISO8211::NAME("DSID"); -constexpr quint32 DSNM = ISO8211::NAME("DSNM"); constexpr quint32 DSPM = ISO8211::NAME("DSPM"); -constexpr quint32 COMF = ISO8211::NAME("COMF"); static Range zooms(const RectC &bounds) { @@ -104,7 +102,7 @@ bool ENCMap::bounds(const QVector &gv, Rect &b) return true; } -bool ENCMap::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, +bool ENCMap::processRecord(const ISO8211::Record &record, QVector &rv, uint &comf, QByteArray &dsnm) { if (record.size() < 2) @@ -116,10 +114,15 @@ bool ENCMap::processRecord(const ISO8211 &ddf, const ISO8211::Record &record, if (tag == VRID) { rv.append(record); } else if (tag == DSID) { - if (!ddf.subfield(f, DSNM, &dsnm)) + if (f.data().at(0).size() < 5) return false; + dsnm = f.data().at(0).at(4).toByteArray(); } else if (tag == DSPM) { - if (!ddf.subfield(f, COMF, &comf)) + bool ok; + if (f.data().at(0).size() < 11) + return false; + comf = f.data().at(0).at(10).toUInt(&ok); + if (!ok) return false; } @@ -141,7 +144,7 @@ ENCMap::ENCMap(const QString &fileName, QObject *parent) return; } while (ddf.readRecord(record)) { - if (!processRecord(ddf, record, gv, comf, dsnm)) { + if (!processRecord(record, gv, comf, dsnm)) { _errorString = "Invalid S-57 record"; return; } diff --git a/src/map/encmap.h b/src/map/encmap.h index eb690a02..6d66b043 100644 --- a/src/map/encmap.h +++ b/src/map/encmap.h @@ -96,9 +96,8 @@ private: static bool bounds(const ENC::ISO8211::Record &record, Rect &rect); static bool bounds(const QVector &gv, Rect &b); - static bool processRecord(const ENC::ISO8211 &ddf, - const ENC::ISO8211::Record &record, QVector &rv, - uint &comf, QByteArray &dsnm); + static bool processRecord(const ENC::ISO8211::Record &record, + QVector &rv, uint &comf, QByteArray &dsnm); QString _name; ENC::MapData *_data; From 0da16199f8a424cb2b5517be5abd5ad0b7fd2db8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Tue, 22 Apr 2025 19:14:06 +0200 Subject: [PATCH 10/10] Code cleanup --- src/map/ENC/mapdata.cpp | 24 ++++++++++++------------ src/map/ENC/mapdata.h | 2 +- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/map/ENC/mapdata.cpp b/src/map/ENC/mapdata.cpp index d8ca4638..8576635c 100644 --- a/src/map/ENC/mapdata.cpp +++ b/src/map/ENC/mapdata.cpp @@ -757,7 +757,7 @@ MapData::Poly *MapData::polyObject(const ISO8211::Record &r, bool MapData::processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, - RecordMap &vf, uint &comf, uint &somf, uint &huni) + uint &comf, uint &huni, uint &somf) { if (record.size() < 2) return false; @@ -786,8 +786,8 @@ bool MapData::processRecord(const ISO8211::Record &record, ve.insert(rcid, record); break; case RCNM_VF: - vf.insert(rcid, record); - break; + qWarning("Full topology/faces not supported"); + return false; default: return false; } @@ -810,7 +810,7 @@ bool MapData::processRecord(const ISO8211::Record &record, MapData::MapData(const QString &path) { - RecordMap vi, vc, ve, vf; + RecordMap vi, vc, ve; QVector fe; ISO8211 ddf(path); ISO8211::Record record; @@ -824,17 +824,17 @@ MapData::MapData(const QString &path) if (!ddf.readDDR()) return; while (ddf.readRecord(record)) - if (!processRecord(record, fe, vi, vc, ve, vf, comf, somf, huni)) + if (!processRecord(record, fe, vi, vc, ve, comf, somf, huni)) qWarning("Invalid S-57 record"); for (int i = 0; i < fe.size(); i++) { const ISO8211::Record &r = fe.at(i); - const ISO8211::Field &f = r.at(1); + const ISO8211::Field &frid = r.at(1); - if (f.data().at(0).size() < 5) + if (frid.data().at(0).size() < 5) continue; - prim = f.data().at(0).at(2).toUInt(); - objl = f.data().at(0).at(4).toUInt(); + prim = frid.data().at(0).at(2).toUInt(); + objl = frid.data().at(0).at(4).toUInt(); switch (prim) { case PRIM_P: @@ -850,7 +850,7 @@ MapData::MapData(const QString &path) pointBounds(point->pos(), min, max); _points.Insert(min, max, point); } else - warning(f, prim); + warning(frid, prim); } break; case PRIM_L: @@ -858,14 +858,14 @@ MapData::MapData(const QString &path) rectcBounds(line->bounds(), min, max); _lines.Insert(min, max, line); } else - warning(f, prim); + warning(frid, prim); break; case PRIM_A: if ((poly = polyObject(r, vc, ve, comf, objl, huni))) { rectcBounds(poly->bounds(), min, max); _areas.Insert(min, max, poly); } else - warning(f, prim); + warning(frid, prim); break; } } diff --git a/src/map/ENC/mapdata.h b/src/map/ENC/mapdata.h index 6824173f..6ae1fdcb 100644 --- a/src/map/ENC/mapdata.h +++ b/src/map/ENC/mapdata.h @@ -53,7 +53,7 @@ private: static bool processRecord(const ISO8211::Record &record, QVector &fe, RecordMap &vi, RecordMap &vc, RecordMap &ve, - RecordMap &vf, uint &comf, uint &somf, uint &huni); + uint &comf, uint &somf, uint &huni); PolygonTree _areas; LineTree _lines;