From d2ac9f2ee6fe56ed3ce988f3f416f22f40e44609 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Sat, 12 Apr 2025 13:16:36 +0200 Subject: [PATCH] Added support for Vakaros VKX files --- gpxsee.pro | 2 + src/data/data.cpp | 4 ++ src/data/vkxparser.cpp | 151 +++++++++++++++++++++++++++++++++++++++++ src/data/vkxparser.h | 27 ++++++++ 4 files changed, 184 insertions(+) create mode 100644 src/data/vkxparser.cpp create mode 100644 src/data/vkxparser.h diff --git a/gpxsee.pro b/gpxsee.pro index 567efc7e..9e21e060 100644 --- a/gpxsee.pro +++ b/gpxsee.pro @@ -118,6 +118,7 @@ HEADERS += src/common/config.h \ src/data/style.h \ src/data/twonavparser.h \ src/data/txtparser.h \ + src/data/vkxparser.h \ src/data/vtkparser.h \ src/map/ENC/data.h \ src/map/IMG/light.h \ @@ -347,6 +348,7 @@ SOURCES += src/main.cpp \ src/GUI/projectioncombobox.cpp \ src/GUI/passwordedit.cpp \ src/data/txtparser.cpp \ + src/data/vkxparser.cpp \ src/data/vtkparser.cpp \ src/map/downloader.cpp \ src/map/demloader.cpp \ diff --git a/src/data/data.cpp b/src/data/data.cpp index ecba0159..ada95eda 100644 --- a/src/data/data.cpp +++ b/src/data/data.cpp @@ -25,6 +25,7 @@ #include "gpsdumpparser.h" #include "txtparser.h" #include "vtkparser.h" +#include "vkxparser.h" #include "data.h" @@ -53,6 +54,7 @@ static TwoNavParser twonav; static GPSDumpParser gpsdump; static TXTParser txt; static VTKParser vtk; +static VKXParser vkx; static QMultiMap parsers() { @@ -88,6 +90,7 @@ static QMultiMap parsers() map.insert("wpt", &gpsdump); map.insert("txt", &txt); map.insert("vtk", &vtk); + map.insert("vkx", &vkx); return map; } @@ -248,6 +251,7 @@ QString Data::formats() + qApp->translate("Data", "SML files") + " (*.sml);;" + qApp->translate("Data", "TCX files") + " (*.tcx);;" + qApp->translate("Data", "70mai GPS log files") + " (*.txt);;" + + qApp->translate("Data", "VKX files") + " (*.vkx);;" + qApp->translate("Data", "VTK files") + " (*.vtk);;" + qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;" + qApp->translate("Data", "GPSDump files") + " (*.wpt);;" diff --git a/src/data/vkxparser.cpp b/src/data/vkxparser.cpp new file mode 100644 index 00000000..98af4ba5 --- /dev/null +++ b/src/data/vkxparser.cpp @@ -0,0 +1,151 @@ +#include "vkxparser.h" + +static bool readTrackPoint(QDataStream &stream, SegmentData &segment) +{ + quint64 time; + qint32 lat, lon; + quint32 unused; + float speed, alt; + + stream >> time >> lat >> lon; + if (stream.status() != QDataStream::Ok) + return false; + if (stream.readRawData((char*)&speed, 4) != 4) + return false; + stream >> unused; + if (stream.readRawData((char*)&alt, 4) != 4) + return false; + stream >> unused >> unused >> unused >> unused; + if (stream.status() != QDataStream::Ok) + return false; + + Trackpoint t(Coordinates(lon / 1e7, lat / 1e7)); + if (!t.coordinates().isValid()) + return false; + t.setTimestamp(QDateTime::fromMSecsSinceEpoch(time)); + t.setSpeed(speed); + t.setElevation(alt); + + segment.append(t); + + return true; +} + +bool VKXParser::skip(QDataStream &stream, quint8 key, int len) +{ + if (stream.skipRawData(len) != len) { + _errorString = "Invalid 0x" + QString::number(key, 16) + " row"; + return false; + } + + return true; +} + +bool VKXParser::parse(QFile *file, QList &tracks, + QList &routes, QList &polygons, QVector &waypoints) +{ + Q_UNUSED(routes); + Q_UNUSED(polygons); + Q_UNUSED(waypoints); + quint8 key; + quint64 hdr; + SegmentData segment; + + QDataStream stream(file); + stream.setByteOrder(QDataStream::LittleEndian); + + stream >> hdr; + if ((hdr & 0xFF) != 0xFF) { + _errorString = "Not a Vakaros VKX file"; + return false; + } + + while (stream.status() == QDataStream::Ok) { + stream >> key; + if (stream.status() != QDataStream::Ok) + break; + + switch (key) { + case 0x01: + if (!skip(stream, key, 32)) + return false; + break; + case 0x02: + if (!readTrackPoint(stream, segment)) { + _errorString = "Invalid 0x2 row"; + return false; + } + break; + case 0x03: + if (!skip(stream, key, 20)) + return false; + break; + case 0x04: + if (!skip(stream, key, 13)) + return false; + break; + case 0x05: + if (!skip(stream, key, 17)) + return false; + break; + case 0x06: + if (!skip(stream, key, 18)) + return false; + break; + case 0x07: + if (!skip(stream, key, 12)) + return false; + break; + case 0x08: + if (!skip(stream, key, 13)) + return false; + break; + case 0x0A: + case 0x0B: + if (!skip(stream, key, 16)) + return false; + break; + case 0x0C: + if (!skip(stream, key, 12)) + return false; + break; + case 0x0E: + case 0x0F: + if (!skip(stream, key, 16)) + return false; + break; + case 0x10: + if (!skip(stream, key, 12)) + return false; + break; + case 0x20: + if (!skip(stream, key, 13)) + return false; + break; + case 0x21: + if (!skip(stream, key, 52)) + return false; + break; + case 0xFE: + if (!skip(stream, key, 2)) + return false; + break; + case 0xFF: + if (!skip(stream, key, 7)) + return false; + break; + default: + _errorString = "Unknown row key: 0x" + QString::number(key, 16); + return false; + } + } + + if (stream.status() != QDataStream::ReadPastEnd) { + _errorString = "Unexpected EOF"; + return false; + } + + tracks.append(segment); + + return true; +} diff --git a/src/data/vkxparser.h b/src/data/vkxparser.h new file mode 100644 index 00000000..0459dfe0 --- /dev/null +++ b/src/data/vkxparser.h @@ -0,0 +1,27 @@ +#ifndef VKXPARSER_H +#define VKXPARSER_H + +#include "parser.h" + +class QDataStream; + +class VKXParser : public Parser +{ +public: + VKXParser() + { + static_assert(sizeof(float) == 4, "Invalid float size"); + } + + bool parse(QFile *file, QList &tracks, QList &routes, + QList &polygons, QVector &waypoints); + QString errorString() const {return _errorString;} + int errorLine() const {return 0;} + +private: + bool skip(QDataStream &stream, quint8 key, int len); + + QString _errorString; +}; + +#endif // VKXPARSER_H