From 5873a08197abc39168ca9e70eae1b2b732aa7779 Mon Sep 17 00:00:00 2001 From: Dirk Hohndel Date: Thu, 12 Nov 2015 14:57:27 -0800 Subject: [PATCH] Location service: add member to apply the gps locations to dives This is a direct conversion of the existing code in subsurfacewebservices to the different data structures in use here. I did not try to abstract this out to have both share a common helper because I assume that the Subsurface web service will pretty quickly become obsolete (together with the companion app). Right now this is not hooked up anywhere. Signed-off-by: Dirk Hohndel --- qt-mobile/gpslocation.cpp | 129 ++++++++++++++++++++++++++++++++++++++ qt-mobile/gpslocation.h | 1 + 2 files changed, 130 insertions(+) diff --git a/qt-mobile/gpslocation.cpp b/qt-mobile/gpslocation.cpp index 82d7ed0c1..2459aeefd 100644 --- a/qt-mobile/gpslocation.cpp +++ b/qt-mobile/gpslocation.cpp @@ -2,6 +2,7 @@ #include "qt-mobile/qmlmanager.h" #include "pref.h" #include "dive.h" +#include "helpers.h" #include #include #include @@ -72,3 +73,131 @@ void GpsLocation::status(QString msg) qDebug() << msg; qmlUiShowMessage(qPrintable(msg)); } + +struct gpsTracker { + degrees_t latitude; + degrees_t longitude; + time_t when; +}; + +static void copy_gps_location(struct gpsTracker *gps, struct dive *d) +{ + struct dive_site *ds = get_dive_site_by_uuid(d->dive_site_uuid); + ds->latitude = gps->latitude; + ds->longitude = gps->longitude; +} + +#define SAME_GROUP 6 * 3600 /* six hours */ +bool GpsLocation::applyLocations() +{ + int i; + bool changed = false; + int last = 0; + int cnt = geoSettings.value("count", 0).toInt(); + if (cnt == 0) + return false; + + // create a table with the GPS information + struct gpsTracker *gpsTable = (struct gpsTracker *)calloc(cnt, sizeof(struct gpsTracker)); + for (int i = 0; i < cnt; i++) { + gpsTable[i].latitude.udeg = geoSettings.value(QString("gpsFix%1_lat").arg(i)).toInt(); + gpsTable[i].longitude.udeg = geoSettings.value(QString("gpsFix%1_lon").arg(i)).toInt(); + gpsTable[i].when = geoSettings.value(QString("gpsFix%1_time").arg(i)).toULongLong(); + } + + // now walk the dive table and see if we can fill in missing gps data + struct dive *d; + for_each_dive(i, d) { + if (dive_has_gps_location(d)) + continue; + for (int j = last; j < cnt; j++) { + if (time_during_dive_with_offset(d, gpsTable[j].when, SAME_GROUP)) { + if (verbose) + qDebug() << "processing gpsfix @" << get_dive_date_string(gpsTable[j].when) << + "which is withing six hours of dive from" << + get_dive_date_string(d->when) << "until" << + get_dive_date_string(d->when + d->duration.seconds); + /* + * If position is fixed during dive. This is the good one. + * Asign and mark position, and end gps_location loop + */ + if (time_during_dive_with_offset(d, gpsTable[j].when, 0)) { + if (verbose) + qDebug() << "gpsfix is during the dive, pick that one"; + copy_gps_location(gpsTable + j, d); + changed = true; + last = j; + break; + } else { + /* + * If it is not, check if there are more position fixes in SAME_GROUP range + */ + if (j + 1 < cnt && time_during_dive_with_offset(d, gpsTable[j+1].when, SAME_GROUP)) { + if (verbose) + qDebug() << "look at the next gps fix @" << get_dive_date_string(gpsTable[j+1].when); + /* first let's test if this one is during the dive */ + if (time_during_dive_with_offset(d, gpsTable[j+1].when, 0)) { + if (verbose) + qDebug() << "which is during the dive, pick that one"; + copy_gps_location(gpsTable + j + 1, d); + changed = true; + last = j + 1; + break; + } + /* we know the gps fixes are sorted; if they are both before the dive, ignore the first, + * if theay are both after the dive, take the first, + * if the first is before and the second is after, take the closer one */ + if (gpsTable[j+1].when < d->when) { + if (verbose) + qDebug() << "which is closer to the start of the dive, do continue with that"; + continue; + } else if (gpsTable[j].when > d->when + d->duration.seconds) { + if (verbose) + qDebug() << "which is even later after the end of the dive, so pick the previous one"; + copy_gps_location(gpsTable + j, d); + changed = true; + last = j; + break; + } else { + /* ok, gpsfix is before, nextgpsfix is after */ + if (d->when - gpsTable[j].when <= gpsTable[j+1].when - (d->when + d->duration.seconds)) { + if (verbose) + qDebug() << "pick the one before as it's closer to the start"; + copy_gps_location(gpsTable + j, d); + changed = true; + last = j; + break; + } else { + if (verbose) + qDebug() << "pick the one after as it's closer to the start"; + copy_gps_location(gpsTable + j + 1, d); + changed = true; + last = j + 1; + break; + } + } + /* + * If no more positions in range, the actual is the one. Asign, mark and end loop. + */ + } else { + if (verbose) + qDebug() << "which seems to be the best one for this dive, so pick it"; + copy_gps_location(gpsTable + j, d); + changed = true; + last = j; + break; + } + } + } else { + /* If position is out of SAME_GROUP range and in the future, mark position for + * next dive iteration and end the gps_location loop + */ + if (gpsTable[j].when >= d->when + d->duration.seconds + SAME_GROUP) { + last = j; + break; + } + } + + } + } +} diff --git a/qt-mobile/gpslocation.h b/qt-mobile/gpslocation.h index f4a2fc737..9310875d8 100644 --- a/qt-mobile/gpslocation.h +++ b/qt-mobile/gpslocation.h @@ -13,6 +13,7 @@ class GpsLocation : QObject Q_OBJECT public: GpsLocation(QObject *parent); + bool applyLocations(); private: QGeoPositionInfo lastPos;