1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-11-30 22:51:16 +01:00

Added support for OnMove OMD files

This commit is contained in:
Martin Tůma 2021-08-18 21:29:28 +02:00
parent ab062cc3ff
commit 221d1b3fdb
4 changed files with 223 additions and 0 deletions

View File

@ -95,6 +95,7 @@ HEADERS += src/common/config.h \
src/GUI/areaitem.h \
src/data/itnparser.h \
src/data/link.h \
src/data/omdparser.h \
src/data/ov2parser.h \
src/map/IMG/bitmapline.h \
src/map/IMG/bitstream.h \
@ -289,6 +290,7 @@ SOURCES += src/main.cpp \
src/GUI/areaitem.cpp \
src/data/address.cpp \
src/data/itnparser.cpp \
src/data/omdparser.cpp \
src/data/ov2parser.cpp \
src/data/waypoint.cpp \
src/map/IMG/bitmapline.cpp \

View File

@ -19,6 +19,7 @@
#include "smlparser.h"
#include "ov2parser.h"
#include "itnparser.h"
#include "omdparser.h"
#include "data.h"
@ -41,6 +42,7 @@ static GPIParser gpi;
static SMLParser sml;
static OV2Parser ov2;
static ITNParser itn;
static OMDParser omd;
static QMap<QString, Parser*> parsers()
{
@ -67,6 +69,7 @@ static QMap<QString, Parser*> parsers()
map.insert("sml", &sml);
map.insert("ov2", &ov2);
map.insert("itn", &itn);
map.insert("omd", &omd);
return map;
}
@ -144,6 +147,7 @@ QString Data::formats()
+ qApp->translate("Data", "KML files") + " (*.kml);;"
+ qApp->translate("Data", "LOC files") + " (*.loc);;"
+ qApp->translate("Data", "NMEA files") + " (*.nmea);;"
+ qApp->translate("Data", "OMD files") + " (*.omd);;"
+ qApp->translate("Data", "OV2 files") + " (*.ov2);;"
+ qApp->translate("Data", "OziExplorer files") + " (*.plt *.rte *.wpt);;"
+ qApp->translate("Data", "SLF files") + " (*.slf);;"

175
src/data/omdparser.cpp Normal file
View File

@ -0,0 +1,175 @@
#include <QFileInfo>
#include <QDir>
#include <QtEndian>
#include "omdparser.h"
static quint16 u16(const char *buffer)
{
return qFromLittleEndian<quint16>(buffer);
}
static qint16 s16(const char *buffer)
{
return qFromLittleEndian<qint16>(buffer);
}
static qint32 s32(const char *buffer)
{
return qFromLittleEndian<qint32>(buffer);
}
bool OMDParser::readHeaderFile(const QString &omdPath, Header &hdr)
{
QFileInfo fi(omdPath);
QString path = fi.absoluteDir().filePath(fi.baseName() + ".OMH");
QFile file(path);
char buffer[60];
if (!file.open(QIODevice::ReadOnly)) {
qWarning("%s: %s", qPrintable(path), qPrintable(file.errorString()));
return false;
}
if (file.read(buffer, sizeof(buffer)) != sizeof(buffer)) {
qWarning("%s: invalid OMH file", qPrintable(path));
return false;
}
quint8 Y = buffer[14];
quint8 M = buffer[15];
quint8 D = buffer[16];
quint8 h = buffer[17];
quint8 m = buffer[18];
quint16 ascent = u16(buffer + 22);
quint16 descent = u16(buffer + 24);
quint8 avgHr = buffer[12];
quint8 maxHr = buffer[13];
QDateTime date(QDate(Y + 2000, M, D), QTime(h, m), Qt::UTC);
if (!date.isValid()) {
qWarning("%s: invalid date", qPrintable(path));
return false;
}
hdr.date = date;
hdr.hr = avgHr || maxHr;
hdr.elevation = ascent || descent;
return true;
}
bool OMDParser::readF1(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment)
{
if (seq.cnt > 1) {
_errorString = "invalid chunk sequence";
return false;
}
qint32 lat = s32(chunk);
qint32 lon = s32(chunk + 4);
quint16 sec = u16(chunk + 12);
quint8 fia = chunk[14];
qint16 alt = s16(chunk + 15);
if (fia == 3) {
Trackpoint t(Coordinates(lon / 1000000.0, lat / 1000000.0));
if (!t.coordinates().isValid()) {
_errorString = "invalid coordinates";
return false;
}
t.setTimestamp(QDateTime(hdr.date.date(),
hdr.date.time().addSecs(sec), Qt::UTC));
if (hdr.elevation)
t.setElevation(alt);
seq.idx[seq.cnt] = segment.size();
segment.append(t);
} else
seq.idx[seq.cnt] = -1;
seq.cnt++;
return true;
}
bool OMDParser::readF2(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment)
{
if (!seq.cnt) {
_errorString = "invalid chunk sequence";
return false;
}
quint16 speed1 = u16(chunk + 2);
quint8 hr1 = chunk[6];
quint16 speed2 = u16(chunk + 12);
quint8 hr2 = chunk[16];
if (seq.idx[0] >= 0) {
Trackpoint &p0 = segment[seq.idx[0]];
if (hdr.hr)
p0.setHeartRate(hr1);
p0.setSpeed(speed1 / 360.0);
}
if (seq.idx[1] >= 0) {
Trackpoint &p1 = segment[seq.idx[1]];
if (hdr.hr)
p1.setHeartRate(hr2);
p1.setSpeed(speed2 / 360.0);
}
seq.idx[0] = -1;
seq.idx[1] = -1;
seq.cnt = 0;
return true;
}
bool OMDParser::parse(QFile *file, QList<TrackData> &tracks,
QList<RouteData> &routes, QList<Area> &polygons, QVector<Waypoint> &waypoints)
{
Q_UNUSED(routes);
Q_UNUSED(waypoints);
Q_UNUSED(polygons);
SegmentData segment;
Header hdr;
Sequence seq;
char chunk[20];
qint64 size;
// If no header file is found or it is invalid, continue with the default
// header values. The track will have a fictional date and possibly some
// zero-graphs, but it will be still usable.
readHeaderFile(file->fileName(), hdr);
while ((size = file->read(chunk, sizeof(chunk))) == sizeof(chunk)) {
switch ((quint8)chunk[19]) {
case 0xF1:
if (!readF1(chunk, hdr, seq, segment))
return false;
break;
case 0xF2:
if (!readF2(chunk, hdr, seq, segment))
return false;
break;
default:
_errorString = "invalid chunk type";
return false;
}
}
if (size < 0) {
_errorString = "I/O error";
return false;
} else if (size) {
_errorString = "unexpected end of file";
return false;
}
tracks.append(TrackData());
tracks.last().append(segment);
return true;
}

42
src/data/omdparser.h Normal file
View File

@ -0,0 +1,42 @@
#ifndef OMDPARSER_H
#define OMDPARSER_H
#include "parser.h"
class OMDParser : 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:
struct Header
{
Header() : date(QDateTime(QDate(1970, 1, 1), QTime(0, 0), Qt::UTC)),
elevation(true), hr(true) {}
QDateTime date;
bool elevation;
bool hr;
};
struct Sequence
{
Sequence() : cnt(0), idx{-1, -1} {}
unsigned cnt;
int idx[2];
};
bool readHeaderFile(const QString &omdPath, Header &hdr);
bool readF1(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment);
bool readF2(const char *chunk, const Header &hdr, Sequence &seq,
SegmentData &segment);
QString _errorString;
};
#endif // OMDPARSER_H