mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-03-17 20:17:45 +01:00
Added support for Velocitek VTK files
This commit is contained in:
parent
912a00c80e
commit
28f55b7e0d
@ -118,6 +118,7 @@ HEADERS += src/common/config.h \
|
|||||||
src/data/style.h \
|
src/data/style.h \
|
||||||
src/data/twonavparser.h \
|
src/data/twonavparser.h \
|
||||||
src/data/txtparser.h \
|
src/data/txtparser.h \
|
||||||
|
src/data/vtkparser.h \
|
||||||
src/map/ENC/data.h \
|
src/map/ENC/data.h \
|
||||||
src/map/IMG/light.h \
|
src/map/IMG/light.h \
|
||||||
src/map/downloader.h \
|
src/map/downloader.h \
|
||||||
@ -346,6 +347,7 @@ SOURCES += src/main.cpp \
|
|||||||
src/GUI/projectioncombobox.cpp \
|
src/GUI/projectioncombobox.cpp \
|
||||||
src/GUI/passwordedit.cpp \
|
src/GUI/passwordedit.cpp \
|
||||||
src/data/txtparser.cpp \
|
src/data/txtparser.cpp \
|
||||||
|
src/data/vtkparser.cpp \
|
||||||
src/map/downloader.cpp \
|
src/map/downloader.cpp \
|
||||||
src/map/demloader.cpp \
|
src/map/demloader.cpp \
|
||||||
src/map/ENC/atlasdata.cpp \
|
src/map/ENC/atlasdata.cpp \
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
#include "twonavparser.h"
|
#include "twonavparser.h"
|
||||||
#include "gpsdumpparser.h"
|
#include "gpsdumpparser.h"
|
||||||
#include "txtparser.h"
|
#include "txtparser.h"
|
||||||
|
#include "vtkparser.h"
|
||||||
#include "data.h"
|
#include "data.h"
|
||||||
|
|
||||||
|
|
||||||
@ -51,6 +52,7 @@ static GHPParser ghp;
|
|||||||
static TwoNavParser twonav;
|
static TwoNavParser twonav;
|
||||||
static GPSDumpParser gpsdump;
|
static GPSDumpParser gpsdump;
|
||||||
static TXTParser txt;
|
static TXTParser txt;
|
||||||
|
static VTKParser vtk;
|
||||||
|
|
||||||
static QMultiMap<QString, Parser*> parsers()
|
static QMultiMap<QString, Parser*> parsers()
|
||||||
{
|
{
|
||||||
@ -85,6 +87,7 @@ static QMultiMap<QString, Parser*> parsers()
|
|||||||
map.insert("wpt", &twonav);
|
map.insert("wpt", &twonav);
|
||||||
map.insert("wpt", &gpsdump);
|
map.insert("wpt", &gpsdump);
|
||||||
map.insert("txt", &txt);
|
map.insert("txt", &txt);
|
||||||
|
map.insert("vtk", &vtk);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
@ -245,6 +248,7 @@ QString Data::formats()
|
|||||||
+ qApp->translate("Data", "SML files") + " (*.sml);;"
|
+ qApp->translate("Data", "SML files") + " (*.sml);;"
|
||||||
+ qApp->translate("Data", "TCX files") + " (*.tcx);;"
|
+ qApp->translate("Data", "TCX files") + " (*.tcx);;"
|
||||||
+ qApp->translate("Data", "70mai GPS log files") + " (*.txt);;"
|
+ qApp->translate("Data", "70mai GPS log files") + " (*.txt);;"
|
||||||
|
+ qApp->translate("Data", "VTK files") + " (*.vtk);;"
|
||||||
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
|
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
|
||||||
+ qApp->translate("Data", "GPSDump files") + " (*.wpt);;"
|
+ qApp->translate("Data", "GPSDump files") + " (*.wpt);;"
|
||||||
+ qApp->translate("Data", "All files") + " (*)";
|
+ qApp->translate("Data", "All files") + " (*)";
|
||||||
|
214
src/data/vtkparser.cpp
Normal file
214
src/data/vtkparser.cpp
Normal file
@ -0,0 +1,214 @@
|
|||||||
|
#include <QtEndian>
|
||||||
|
#include <QTimeZone>
|
||||||
|
#include "vtkparser.h"
|
||||||
|
|
||||||
|
#define TYPE(tag) (tag & 0x07)
|
||||||
|
#define FIELD(tag) (tag >> 3)
|
||||||
|
|
||||||
|
#define VARINT 0
|
||||||
|
#define I64 1
|
||||||
|
#define LEN 2
|
||||||
|
#define I32 5
|
||||||
|
|
||||||
|
struct CTX
|
||||||
|
{
|
||||||
|
CTX(const QByteArray &ba)
|
||||||
|
: bp(ba.constData()), be(bp + ba.size()), tag(0) {}
|
||||||
|
|
||||||
|
const char *bp;
|
||||||
|
const char *be;
|
||||||
|
quint32 tag;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline qint32 zigzag32decode(quint32 value)
|
||||||
|
{
|
||||||
|
return static_cast<qint32>((value >> 1u) ^ static_cast<quint32>(
|
||||||
|
-static_cast<qint32>(value & 1u)));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
static bool varint(CTX &ctx, T &val)
|
||||||
|
{
|
||||||
|
unsigned int shift = 0;
|
||||||
|
val = 0;
|
||||||
|
|
||||||
|
while (ctx.bp < ctx.be) {
|
||||||
|
val |= ((quint8)*ctx.bp & 0x7F) << shift;
|
||||||
|
shift += 7;
|
||||||
|
if (!((quint8)*ctx.bp++ & 0x80))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool length(CTX &ctx, qint32 &val)
|
||||||
|
{
|
||||||
|
if (TYPE(ctx.tag) != LEN)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!varint(ctx, val))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return (val >= 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool skip(CTX &ctx)
|
||||||
|
{
|
||||||
|
qint32 len = 0;
|
||||||
|
|
||||||
|
switch (TYPE(ctx.tag)) {
|
||||||
|
case VARINT:
|
||||||
|
return varint(ctx, len);
|
||||||
|
case I64:
|
||||||
|
len = 8;
|
||||||
|
break;
|
||||||
|
case LEN:
|
||||||
|
if (!varint(ctx, len) || len < 0)
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case I32:
|
||||||
|
len = 4;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctx.bp + len > ctx.be)
|
||||||
|
return false;
|
||||||
|
ctx.bp += len;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool trackpoint(CTX &ctx, Trackpoint &t)
|
||||||
|
{
|
||||||
|
qint32 len, lon = 0xFFFFFFF, lat = 0xFFFFFFF;
|
||||||
|
quint32 val, seconds = 0, centiSeconds = 0, speed = 0;
|
||||||
|
|
||||||
|
if (!length(ctx, len))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
const char *ee = ctx.bp + len;
|
||||||
|
if (ee > ctx.be)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
while (ctx.bp < ee) {
|
||||||
|
if (!varint(ctx, ctx.tag))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (FIELD(ctx.tag)) {
|
||||||
|
case 1:
|
||||||
|
if (TYPE(ctx.tag) != VARINT)
|
||||||
|
return false;
|
||||||
|
if (!varint(ctx, seconds))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (TYPE(ctx.tag) != VARINT)
|
||||||
|
return false;
|
||||||
|
if (!varint(ctx, centiSeconds))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (TYPE(ctx.tag) != VARINT)
|
||||||
|
return false;
|
||||||
|
if (!varint(ctx, val))
|
||||||
|
return false;
|
||||||
|
lat = zigzag32decode(val);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
if (TYPE(ctx.tag) != VARINT)
|
||||||
|
return false;
|
||||||
|
if (!varint(ctx, val))
|
||||||
|
return false;
|
||||||
|
lon = zigzag32decode(val);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
if (TYPE(ctx.tag) != VARINT)
|
||||||
|
return false;
|
||||||
|
if (!varint(ctx, speed))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!skip(ctx))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
t.setCoordinates(Coordinates(lon / 1e7, lat / 1e7));
|
||||||
|
t.setTimestamp(QDateTime::fromMSecsSinceEpoch(
|
||||||
|
((qint64)seconds * 1000) + ((qint64)centiSeconds * 10),
|
||||||
|
QTimeZone::utc()));
|
||||||
|
t.setSpeed(speed / 5.1444);
|
||||||
|
|
||||||
|
return (ctx.bp == ee);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool record(CTX &ctx, Trackpoint &t)
|
||||||
|
{
|
||||||
|
while (ctx.bp < ctx.be) {
|
||||||
|
if (!varint(ctx, ctx.tag))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
switch (FIELD(ctx.tag)) {
|
||||||
|
case 1:
|
||||||
|
if (!trackpoint(ctx, t))
|
||||||
|
return false;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
if (!skip(ctx))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ctx.bp == ctx.be);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VTKParser::parse(QFile *file, QList<TrackData> &tracks,
|
||||||
|
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
|
||||||
|
{
|
||||||
|
Q_UNUSED(routes);
|
||||||
|
Q_UNUSED(polygons);
|
||||||
|
Q_UNUSED(waypoints);
|
||||||
|
qint64 len;
|
||||||
|
quint16 recordLen;
|
||||||
|
QByteArray ba;
|
||||||
|
SegmentData segment;
|
||||||
|
Trackpoint t;
|
||||||
|
|
||||||
|
_errorString = "";
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
len = file->read((char*)&recordLen, 2);
|
||||||
|
if (len < 0) {
|
||||||
|
_errorString = "I/O error";
|
||||||
|
return false;
|
||||||
|
} else if (len == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
recordLen = qFromLittleEndian(recordLen);
|
||||||
|
ba.resize(recordLen);
|
||||||
|
if (file->read(ba.data(), ba.size()) != ba.size()) {
|
||||||
|
_errorString = "Error reading VTK record";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
CTX ctx(ba);
|
||||||
|
t.setCoordinates(Coordinates());
|
||||||
|
if (!record(ctx, t)) {
|
||||||
|
_errorString = "Invalid VTK record";
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
if (t.coordinates().isValid())
|
||||||
|
segment.append(t);
|
||||||
|
else if (!t.coordinates().isNull()) {
|
||||||
|
_errorString = "Invalid VTK record coordinates";
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
tracks.append(segment);
|
||||||
|
return true;
|
||||||
|
}
|
18
src/data/vtkparser.h
Normal file
18
src/data/vtkparser.h
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
#ifndef VTKPARSER_H
|
||||||
|
#define VTKPARSER_H
|
||||||
|
|
||||||
|
#include "parser.h"
|
||||||
|
|
||||||
|
class VTKParser : public Parser
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
bool parse(QFile *file, QList<TrackData> &tracks, QList<RouteData> &routes,
|
||||||
|
QList<Area> &polygons, QVector<Waypoint> &waypoints);
|
||||||
|
QString errorString() const {return _errorString;}
|
||||||
|
int errorLine() const {return 0;}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString _errorString;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // VTKPARSER_H
|
Loading…
x
Reference in New Issue
Block a user