1
0
mirror of https://github.com/tumic0/GPXSee.git synced 2024-10-07 07:13:21 +02:00
GPXSee/src/data/igcparser.cpp

256 lines
4.7 KiB
C++
Raw Normal View History

2016-11-10 00:08:11 +01:00
#include <cstring>
2018-10-11 18:19:35 +02:00
#include "common/util.h"
2016-11-10 00:08:11 +01:00
#include "igcparser.h"
static bool readLat(const char *data, qreal &lat)
2016-11-10 00:08:11 +01:00
{
int d = str2int(data, 2);
int mi = str2int(data + 2, 2);
int mf = str2int(data + 4, 3);
2016-11-10 00:08:11 +01:00
if (d < 0 || mi < 0 || mf < 0)
return false;
if (!(data[7] == 'N' || data[7] == 'S'))
2016-11-10 00:08:11 +01:00
return false;
lat = d + (((qreal)mi + (qreal)mf/1000) / 60);
if (lat > 90)
return false;
if (data[7] == 'S')
2016-11-10 00:08:11 +01:00
lat = -lat;
return true;
}
static bool readLon(const char *data, qreal &lon)
2016-11-10 00:08:11 +01:00
{
int d = str2int(data, 3);
int mi = str2int(data + 3, 2);
int mf = str2int(data + 5, 3);
2016-11-10 00:08:11 +01:00
if (d < 0 || mi < 0 || mf < 0)
return false;
if (!(data[8] == 'E' || data[8] == 'W'))
2016-11-10 00:08:11 +01:00
return false;
lon = d + (((qreal)mi + (qreal)mf/1000) / 60);
if (lon > 180)
return false;
if (data[8] == 'W')
2016-11-10 00:08:11 +01:00
lon = -lon;
return true;
}
static bool readAltitude(const char *data, qreal &ele)
2016-11-10 00:08:11 +01:00
{
int ga;
2016-11-10 00:08:11 +01:00
if (!(data[0] == 'A' || data[0] == 'V'))
2016-11-10 00:08:11 +01:00
return false;
if (data[6] == '-') {
if ((ga = str2int(data + 7, 4)) < 0)
return false;
ga = -ga;
} else {
if ((ga = str2int(data + 6, 5)) < 0)
return false;
}
2016-11-10 00:08:11 +01:00
if (data[0] == 'A')
ele = (qreal)ga;
2016-11-10 00:08:11 +01:00
else
ele = NAN;
return true;
}
static bool readTimestamp(const char *data, QTime &time)
{
int h = str2int(data, 2);
int m = str2int(data + 2, 2);
int s = str2int(data + 4, 2);
if (h < 0 || m < 0 || s < 0)
return false;
time = QTime(h, m, s);
2016-11-16 23:54:15 +01:00
if (!time.isValid())
return false;
return true;
}
2016-11-10 08:46:59 +01:00
static bool readARecord(const char *line, qint64 len)
2016-11-10 00:08:11 +01:00
{
2018-01-04 17:36:22 +01:00
if (len < 7 || line[0] != 'A')
2016-11-10 08:46:59 +01:00
return false;
for (int i = 1; i < 7; i++)
if (!::isprint(line[i]))
return false;
return true;
}
2016-11-16 23:54:15 +01:00
bool IGCParser::readHRecord(const char *line, int len)
2016-11-10 08:46:59 +01:00
{
if (len < 11 || ::strncmp(line, "HFDTE", 5))
2016-11-10 08:46:59 +01:00
return true;
int offset = (len < 16 || ::strncmp(line + 5, "DATE:", 5)) ? 5 : 10;
int d = str2int(line + offset, 2);
int m = str2int(line + offset + 2, 2);
int y = str2int(line + offset + 4, 2);
2016-11-10 00:08:11 +01:00
if (y < 0 || m < 0 || d < 0) {
2016-11-10 08:46:59 +01:00
_errorString = "Invalid date header format";
2016-11-10 00:08:11 +01:00
return false;
}
2016-11-23 18:45:06 +01:00
_date = QDate(y + 2000 < QDate::currentDate().year() ? 2000 + y : 1900 + y,
m, d);
2016-11-10 08:46:59 +01:00
if (!_date.isValid()) {
_errorString = "Invalid date";
return false;
}
2016-11-10 00:08:11 +01:00
return true;
}
2017-07-27 19:47:46 +02:00
bool IGCParser::readBRecord(TrackData &track, const char *line, int len)
2016-11-10 00:08:11 +01:00
{
qreal lat, lon, ele;
QTime time;
2016-11-10 00:08:11 +01:00
2016-11-10 08:46:59 +01:00
if (len < 35)
2016-11-10 00:08:11 +01:00
return false;
if (!readTimestamp(line + 1, time)) {
_errorString = "Invalid timestamp";
2016-11-10 00:08:11 +01:00
return false;
}
if (!readLat(line + 7, lat)) {
2016-11-10 00:08:11 +01:00
_errorString = "Invalid latitude";
return false;
}
if (!readLon(line + 15, lon)) {
2016-11-10 00:08:11 +01:00
_errorString = "Invalid longitude";
return false;
}
if (!readAltitude(line + 24, ele)) {
2016-11-10 00:08:11 +01:00
_errorString = "Invalid altitude";
return false;
}
if (time < _time)
2016-11-21 21:59:21 +01:00
_date = _date.addDays(1);
_time = time;
2016-11-10 00:08:11 +01:00
Trackpoint t(Coordinates(lon, lat));
t.setTimestamp(QDateTime(_date, _time, Qt::UTC));
2016-11-10 00:08:11 +01:00
t.setElevation(ele);
2017-07-27 19:47:46 +02:00
track.append(t);
2016-11-10 00:08:11 +01:00
return true;
}
2017-07-27 19:47:46 +02:00
bool IGCParser::readCRecord(RouteData &route, const char *line, int len)
{
qreal lat, lon;
if (len < 18)
return false;
if (!readLat(line + 1, lat)) {
_errorString = "Invalid latitude";
return false;
}
if (!readLon(line + 9, lon)) {
_errorString = "Invalid longitude";
return false;
}
if (!(lat == 0 && lon == 0)) {
QByteArray ba(line + 18, len - 19);
Waypoint w(Coordinates(lon, lat));
w.setName(QString(ba.trimmed()));
2017-07-27 19:47:46 +02:00
route.append(w);
}
return true;
}
2017-07-27 19:47:46 +02:00
bool IGCParser::parse(QFile *file, QList<TrackData> &tracks,
2019-01-31 01:46:53 +01:00
QList<RouteData> &routes, QList<Area> &polygons,
QVector<Waypoint> &waypoints)
2016-11-10 00:08:11 +01:00
{
2017-07-27 19:47:46 +02:00
Q_UNUSED(waypoints);
2019-01-31 01:46:53 +01:00
Q_UNUSED(polygons);
2016-11-10 00:08:11 +01:00
qint64 len;
char line[76 + 2 + 1 + 1];
bool route = false, track = false;
2016-11-10 00:08:11 +01:00
_errorLine = 1;
_errorString.clear();
2016-11-11 21:53:23 +01:00
while (!file->atEnd()) {
len = file->readLine(line, sizeof(line));
2016-11-10 00:08:11 +01:00
if (len < 0) {
_errorString = "I/O error";
return false;
2016-11-10 08:46:59 +01:00
} else if (len > (qint64)sizeof(line) - 1) {
2016-11-10 00:08:11 +01:00
_errorString = "Line limit exceeded";
return false;
}
2016-11-10 08:46:59 +01:00
if (_errorLine == 1) {
if (!readARecord(line, len)) {
_errorString = "Invalid/missing A record";
return false;
}
} else {
if (line[0] == 'H') {
if (!readHRecord(line, len))
return false;
} else if (line[0] == 'C') {
if (route) {
2017-07-27 19:47:46 +02:00
if (!readCRecord(routes.last() ,line, len))
return false;
} else {
route = true;
2017-07-27 19:47:46 +02:00
routes.append(RouteData());
}
2016-11-10 08:46:59 +01:00
} else if (line[0] == 'B') {
if (_date.isNull()) {
_errorString = "Missing date header";
2016-11-10 00:08:11 +01:00
return false;
2016-11-10 08:46:59 +01:00
}
if (!track) {
2017-07-27 19:47:46 +02:00
tracks.append(TrackData());
_time = QTime(0, 0);
track = true;
}
2017-07-27 19:47:46 +02:00
if (!readBRecord(tracks.last(), line, len))
2016-11-10 00:08:11 +01:00
return false;
2016-11-10 08:46:59 +01:00
}
2016-11-10 00:08:11 +01:00
}
_errorLine++;
}
return true;
}