From 81a974306444e316b0768c6af9736a15a5ffb70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20T=C5=AFma?= Date: Fri, 11 Nov 2016 17:57:49 +0100 Subject: [PATCH] Added support for IGC routes (C records) --- src/igcparser.cpp | 127 ++++++++++++++++++++++++++++++++-------------- src/igcparser.h | 1 + 2 files changed, 89 insertions(+), 39 deletions(-) diff --git a/src/igcparser.cpp b/src/igcparser.cpp index 7689970f..6e47cac5 100644 --- a/src/igcparser.cpp +++ b/src/igcparser.cpp @@ -17,65 +17,65 @@ static int str2int(const char *str, size_t len) 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 mi = str2int(line + 9, 2); - int mf = str2int(line + 11, 3); + int d = str2int(data, 2); + int mi = str2int(data + 2, 2); + int mf = str2int(data + 4, 3); if (d < 0 || mi < 0 || mf < 0) return false; - if (!(line[14] == 'N' || line[14] == 'S')) + if (!(data[7] == 'N' || data[7] == 'S')) return false; lat = d + (((qreal)mi + (qreal)mf/1000) / 60); if (lat > 90) return false; - if (line[14] == 'S') + if (data[7] == 'S') lat = -lat; 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 mi = str2int(line + 18, 2); - int mf = str2int(line + 20, 3); + int d = str2int(data, 3); + int mi = str2int(data + 3, 2); + int mf = str2int(data + 5, 3); if (d < 0 || mi < 0 || mf < 0) return false; - if (!(line[23] == 'E' || line[23] == 'W')) + if (!(data[8] == 'E' || data[8] == 'W')) return false; lon = d + (((qreal)mi + (qreal)mf/1000) / 60); if (lon > 180) return false; - if (line[23] == 'W') + if (data[8] == 'W') lon = -lon; return true; } -static bool readAltitude(const char *line, qreal &ele) +static bool readAltitude(const char *data, qreal &ele) { int p; - if (!(line[24] == 'A' || line[24] == 'V')) + if (!(data[0] == 'A' || data[0] == 'V')) return false; - if (line[25] == '-') - p = str2int(line + 26, 4); + if (data[1] == '-') + p = str2int(data + 2, 4); 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) return false; - if (line[24] == 'A') + if (data[0] == 'A') ele = (qreal)g; else ele = NAN; @@ -83,6 +83,20 @@ static bool readAltitude(const char *line, qreal &ele) 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) { 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) { qreal lat, lon, ele; - QDateTime timestamp; + QTime time; if (len < 35) return false; - int h = str2int(line + 1, 2); - int m = str2int(line + 3, 2); - int s = str2int(line + 5, 2); - - if (h <0 || m < 0 || s < 0) { - _errorString = "Invalid timestamp"; + if (!readTimestamp(line + 1, time)) { + _errorString = "Invalid timestamp"; 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"; return false; } - if (!readLon(line, lon)) { + if (!readLon(line + 15, lon)) { _errorString = "Invalid longitude"; return false; } - if (!readAltitude(line, ele)) { + if (!readAltitude(line + 24, ele)) { _errorString = "Invalid altitude"; return false; } + + if (time < _time) + _date.addDays(1); + _time = time; + Trackpoint t(Coordinates(lon, lat)); - t.setTimestamp(timestamp); + t.setTimestamp(QDateTime(_date, _time, Qt::UTC)); t.setElevation(ele); _tracks.last().append(t); 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) { qint64 len; char line[76 + 2 + 1 + 1]; + bool route = false, track = false; + _errorLine = 1; _errorString.clear(); - _tracks.append(TrackData()); - _time = QTime(0, 0); - - while ((len = file->readLine(line, sizeof(line))) > 0) { if (len < 0) { _errorString = "I/O error"; @@ -192,11 +228,24 @@ bool IGCParser::loadFile(QFile *file) if (line[0] == 'H') { if (!readHRecord(line, len)) 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') { if (_date.isNull()) { _errorString = "Missing date header"; return false; } + if (!track) { + _tracks.append(TrackData()); + _time = QTime(0, 0); + track = true; + } if (!readBRecord(line, len)) return false; } diff --git a/src/igcparser.h b/src/igcparser.h index 433f2a93..41af6683 100644 --- a/src/igcparser.h +++ b/src/igcparser.h @@ -20,6 +20,7 @@ public: private: bool readHRecord(const char *line, qint64 len); bool readBRecord(const char *line, qint64 len); + bool readCRecord(const char *line, qint64 len); int _errorLine; QString _errorString;