mirror of
https://github.com/tumic0/GPXSee.git
synced 2025-03-17 12:07:47 +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/twonavparser.h \
|
||||
src/data/txtparser.h \
|
||||
src/data/vtkparser.h \
|
||||
src/map/ENC/data.h \
|
||||
src/map/IMG/light.h \
|
||||
src/map/downloader.h \
|
||||
@ -346,6 +347,7 @@ SOURCES += src/main.cpp \
|
||||
src/GUI/projectioncombobox.cpp \
|
||||
src/GUI/passwordedit.cpp \
|
||||
src/data/txtparser.cpp \
|
||||
src/data/vtkparser.cpp \
|
||||
src/map/downloader.cpp \
|
||||
src/map/demloader.cpp \
|
||||
src/map/ENC/atlasdata.cpp \
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include "twonavparser.h"
|
||||
#include "gpsdumpparser.h"
|
||||
#include "txtparser.h"
|
||||
#include "vtkparser.h"
|
||||
#include "data.h"
|
||||
|
||||
|
||||
@ -51,6 +52,7 @@ static GHPParser ghp;
|
||||
static TwoNavParser twonav;
|
||||
static GPSDumpParser gpsdump;
|
||||
static TXTParser txt;
|
||||
static VTKParser vtk;
|
||||
|
||||
static QMultiMap<QString, Parser*> parsers()
|
||||
{
|
||||
@ -85,6 +87,7 @@ static QMultiMap<QString, Parser*> parsers()
|
||||
map.insert("wpt", &twonav);
|
||||
map.insert("wpt", &gpsdump);
|
||||
map.insert("txt", &txt);
|
||||
map.insert("vtk", &vtk);
|
||||
|
||||
return map;
|
||||
}
|
||||
@ -245,6 +248,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", "VTK files") + " (*.vtk);;"
|
||||
+ qApp->translate("Data", "TwoNav files") + " (*.rte *.trk *.wpt);;"
|
||||
+ qApp->translate("Data", "GPSDump files") + " (*.wpt);;"
|
||||
+ 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