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

Added support for IGC routes (C records)

This commit is contained in:
Martin Tůma 2016-11-11 17:57:49 +01:00
parent 818fa11fd3
commit 81a9743064
2 changed files with 89 additions and 39 deletions

View File

@ -17,65 +17,65 @@ static int str2int(const char *str, size_t len)
return res; return res;
} }
static bool readLat(const char *line, qreal &lat) static bool readLat(const char *data, qreal &lat)
{ {
int d = str2int(line + 7, 2); int d = str2int(data, 2);
int mi = str2int(line + 9, 2); int mi = str2int(data + 2, 2);
int mf = str2int(line + 11, 3); int mf = str2int(data + 4, 3);
if (d < 0 || mi < 0 || mf < 0) if (d < 0 || mi < 0 || mf < 0)
return false; return false;
if (!(line[14] == 'N' || line[14] == 'S')) if (!(data[7] == 'N' || data[7] == 'S'))
return false; return false;
lat = d + (((qreal)mi + (qreal)mf/1000) / 60); lat = d + (((qreal)mi + (qreal)mf/1000) / 60);
if (lat > 90) if (lat > 90)
return false; return false;
if (line[14] == 'S') if (data[7] == 'S')
lat = -lat; lat = -lat;
return true; return true;
} }
static bool readLon(const char *line, qreal &lon) static bool readLon(const char *data, qreal &lon)
{ {
int d = str2int(line + 15, 3); int d = str2int(data, 3);
int mi = str2int(line + 18, 2); int mi = str2int(data + 3, 2);
int mf = str2int(line + 20, 3); int mf = str2int(data + 5, 3);
if (d < 0 || mi < 0 || mf < 0) if (d < 0 || mi < 0 || mf < 0)
return false; return false;
if (!(line[23] == 'E' || line[23] == 'W')) if (!(data[8] == 'E' || data[8] == 'W'))
return false; return false;
lon = d + (((qreal)mi + (qreal)mf/1000) / 60); lon = d + (((qreal)mi + (qreal)mf/1000) / 60);
if (lon > 180) if (lon > 180)
return false; return false;
if (line[23] == 'W') if (data[8] == 'W')
lon = -lon; lon = -lon;
return true; return true;
} }
static bool readAltitude(const char *line, qreal &ele) static bool readAltitude(const char *data, qreal &ele)
{ {
int p; int p;
if (!(line[24] == 'A' || line[24] == 'V')) if (!(data[0] == 'A' || data[0] == 'V'))
return false; return false;
if (line[25] == '-') if (data[1] == '-')
p = str2int(line + 26, 4); p = str2int(data + 2, 4);
else else
p = str2int(line + 25, 5); p = str2int(data + 1, 5);
int g = str2int(line + 30, 5); int g = str2int(data + 6, 5);
if (p < 0 || g < 0) if (p < 0 || g < 0)
return false; return false;
if (line[24] == 'A') if (data[0] == 'A')
ele = (qreal)g; ele = (qreal)g;
else else
ele = NAN; ele = NAN;
@ -83,6 +83,20 @@ static bool readAltitude(const char *line, qreal &ele)
return true; 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);
return true;
}
static bool readARecord(const char *line, qint64 len) static bool readARecord(const char *line, qint64 len)
{ {
if (len < 9 || line[0] != 'A') if (len < 9 || line[0] != 'A')
@ -120,60 +134,82 @@ bool IGCParser::readHRecord(const char *line, qint64 len)
bool IGCParser::readBRecord(const char *line, qint64 len) bool IGCParser::readBRecord(const char *line, qint64 len)
{ {
qreal lat, lon, ele; qreal lat, lon, ele;
QDateTime timestamp; QTime time;
if (len < 35) if (len < 35)
return false; return false;
int h = str2int(line + 1, 2); if (!readTimestamp(line + 1, time)) {
int m = str2int(line + 3, 2); _errorString = "Invalid timestamp";
int s = str2int(line + 5, 2);
if (h <0 || m < 0 || s < 0) {
_errorString = "Invalid timestamp";
return false; return false;
} }
QTime time = QTime(h, m, s);
if (time < _time)
_date.addDays(1);
_time = time;
timestamp = QDateTime(_date, _time, Qt::UTC);
if (!readLat(line, lat)) { if (!readLat(line + 7, lat)) {
_errorString = "Invalid latitude"; _errorString = "Invalid latitude";
return false; return false;
} }
if (!readLon(line, lon)) { if (!readLon(line + 15, lon)) {
_errorString = "Invalid longitude"; _errorString = "Invalid longitude";
return false; return false;
} }
if (!readAltitude(line, ele)) { if (!readAltitude(line + 24, ele)) {
_errorString = "Invalid altitude"; _errorString = "Invalid altitude";
return false; return false;
} }
if (time < _time)
_date.addDays(1);
_time = time;
Trackpoint t(Coordinates(lon, lat)); Trackpoint t(Coordinates(lon, lat));
t.setTimestamp(timestamp); t.setTimestamp(QDateTime(_date, _time, Qt::UTC));
t.setElevation(ele); t.setElevation(ele);
_tracks.last().append(t); _tracks.last().append(t);
return true; return true;
} }
bool IGCParser::readCRecord(const char *line, qint64 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()));
_routes.last().append(w);
}
return true;
}
bool IGCParser::loadFile(QFile *file) bool IGCParser::loadFile(QFile *file)
{ {
qint64 len; qint64 len;
char line[76 + 2 + 1 + 1]; char line[76 + 2 + 1 + 1];
bool route = false, track = false;
_errorLine = 1; _errorLine = 1;
_errorString.clear(); _errorString.clear();
_tracks.append(TrackData());
_time = QTime(0, 0);
while ((len = file->readLine(line, sizeof(line))) > 0) { while ((len = file->readLine(line, sizeof(line))) > 0) {
if (len < 0) { if (len < 0) {
_errorString = "I/O error"; _errorString = "I/O error";
@ -192,11 +228,24 @@ bool IGCParser::loadFile(QFile *file)
if (line[0] == 'H') { if (line[0] == 'H') {
if (!readHRecord(line, len)) if (!readHRecord(line, len))
return false; return false;
} else if (line[0] == 'C') {
if (route) {
if (!readCRecord(line, len))
return false;
} else {
route = true;
_routes.append(RouteData());
}
} else if (line[0] == 'B') { } else if (line[0] == 'B') {
if (_date.isNull()) { if (_date.isNull()) {
_errorString = "Missing date header"; _errorString = "Missing date header";
return false; return false;
} }
if (!track) {
_tracks.append(TrackData());
_time = QTime(0, 0);
track = true;
}
if (!readBRecord(line, len)) if (!readBRecord(line, len))
return false; return false;
} }

View File

@ -20,6 +20,7 @@ public:
private: private:
bool readHRecord(const char *line, qint64 len); bool readHRecord(const char *line, qint64 len);
bool readBRecord(const char *line, qint64 len); bool readBRecord(const char *line, qint64 len);
bool readCRecord(const char *line, qint64 len);
int _errorLine; int _errorLine;
QString _errorString; QString _errorString;