diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2018-10-20 14:12:15 -0400 |
---|---|---|
committer | Lubomir I. Ivanov <neolit123@gmail.com> | 2018-10-21 19:55:09 +0300 |
commit | 28e3413ff66552f392fecee25068d634cdfe59fc (patch) | |
tree | 5fe303d1e7dc1c371e13b534b85c232e29aea884 | |
parent | c9869406301ff72f76b399097f0845fc1102ced1 (diff) | |
download | subsurface-28e3413ff66552f392fecee25068d634cdfe59fc.tar.gz |
Add 'location_t' data structure
Instead of having people treat latitude and longitude as separate
things, just add a 'location_t' data structure that contains both.
Almost all cases want to always act on them together.
This is really just prep-work for adding a few more locations that we
track: I want to add a entry/exit location to each dive (independent of
the dive site) because of how the Garmin Descent gives us the
information (and hopefully, some day, other dive computers too).
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
40 files changed, 251 insertions, 264 deletions
diff --git a/core/dive.c b/core/dive.c index 08ef5b6bd..e486d1a9a 100644 --- a/core/dive.c +++ b/core/dive.c @@ -4048,8 +4048,7 @@ void dive_create_picture(struct dive *dive, const char *filename, int shift_time struct picture *picture = alloc_picture(); picture->filename = strdup(filename); picture->offset.seconds = metadata.timestamp - dive->when + shift_time; - picture->longitude = metadata.longitude; - picture->latitude = metadata.latitude; + picture->location = metadata.location; dive_add_picture(dive, picture); dive_set_geodata_from_picture(dive, picture); @@ -4078,12 +4077,11 @@ unsigned int dive_get_picture_count(struct dive *dive) void dive_set_geodata_from_picture(struct dive *dive, struct picture *picture) { struct dive_site *ds = get_dive_site_by_uuid(dive->dive_site_uuid); - if (!dive_site_has_gps_location(ds) && (picture->latitude.udeg || picture->longitude.udeg)) { + if (!dive_site_has_gps_location(ds) && has_location(&picture->location)) { if (ds) { - ds->latitude = picture->latitude; - ds->longitude = picture->longitude; + ds->location = picture->location; } else { - dive->dive_site_uuid = create_dive_site_with_gps("", picture->latitude, picture->longitude, dive->when); + dive->dive_site_uuid = create_dive_site_with_gps("", &picture->location, dive->when); invalidate_dive_cache(dive); } } @@ -4428,7 +4426,7 @@ int get_idx_by_uniq_id(int id) bool dive_site_has_gps_location(const struct dive_site *ds) { - return ds && (ds->latitude.udeg || ds->longitude.udeg); + return ds && has_location(&ds->location); } int dive_has_gps_location(const struct dive *dive) diff --git a/core/dive.h b/core/dive.h index 659def142..e9ad1f502 100644 --- a/core/dive.h +++ b/core/dive.h @@ -363,8 +363,7 @@ extern enum divemode_t get_divemode_at_time(const struct divecomputer *dc, int d struct picture { char *filename; offset_t offset; - degrees_t latitude; - degrees_t longitude; + location_t location; struct picture *next; }; diff --git a/core/divesite.c b/core/divesite.c index c41b18220..ea9a3ed58 100644 --- a/core/divesite.c +++ b/core/divesite.c @@ -26,12 +26,12 @@ uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp) } /* there could be multiple sites at the same GPS fix - return the first one */ -uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp) +uint32_t get_dive_site_uuid_by_gps(const location_t *loc, struct dive_site **dsp) { int i; struct dive_site *ds; for_each_dive_site (i, ds) { - if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg) { + if (same_location(loc, &ds->location)) { if (dsp) *dsp = ds; return ds->uuid; @@ -43,23 +43,23 @@ uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, stru /* to avoid a bug where we have two dive sites with different name and the same GPS coordinates * and first get the gps coordinates (reading a V2 file) and happen to get back "the other" name, * this function allows us to verify if a very specific name/GPS combination already exists */ -uint32_t get_dive_site_uuid_by_gps_and_name(char *name, degrees_t latitude, degrees_t longitude) +uint32_t get_dive_site_uuid_by_gps_and_name(char *name, const location_t *loc) { int i; struct dive_site *ds; for_each_dive_site (i, ds) { - if (ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg && same_string(ds->name, name)) + if (same_location(loc, &ds->location) && same_string(ds->name, name)) return ds->uuid; } return 0; } // Calculate the distance in meters between two coordinates. -unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2) +unsigned int get_distance(const location_t *loc1, const location_t *loc2) { - double lat2_r = udeg_to_radians(lat2.udeg); - double lat_d_r = udeg_to_radians(lat2.udeg-lat1.udeg); - double lon_d_r = udeg_to_radians(lon2.udeg-lon1.udeg); + double lat2_r = udeg_to_radians(loc2->lat.udeg); + double lat_d_r = udeg_to_radians(loc2->lat.udeg - loc1->lat.udeg); + double lon_d_r = udeg_to_radians(loc2->lon.udeg - loc1->lon.udeg); double a = sin(lat_d_r/2) * sin(lat_d_r/2) + cos(lat2_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2); @@ -70,7 +70,7 @@ unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degree } /* find the closest one, no more than distance meters away - if more than one at same distance, pick the first */ -uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longitude, int distance, struct dive_site **dsp) +uint32_t get_dive_site_uuid_by_gps_proximity(const location_t *loc, int distance, struct dive_site **dsp) { int i; int uuid = 0; @@ -78,7 +78,7 @@ uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longi unsigned int cur_distance, min_distance = distance; for_each_dive_site (i, ds) { if (dive_site_has_gps_location(ds) && - (cur_distance = get_distance(ds->latitude, ds->longitude, latitude, longitude)) < min_distance) { + (cur_distance = get_distance(&ds->location, loc)) < min_distance) { min_distance = cur_distance; uuid = ds->uuid; if (dsp) @@ -232,13 +232,12 @@ uint32_t create_dive_site_from_current_dive(const char *name) } /* same as before, but with GPS data */ -uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude, timestamp_t divetime) +uint32_t create_dive_site_with_gps(const char *name, const location_t *loc, timestamp_t divetime) { uint32_t uuid = create_divesite_uuid(name, divetime); struct dive_site *ds = alloc_or_get_dive_site(uuid); ds->name = copy_string(name); - ds->latitude = latitude; - ds->longitude = longitude; + ds->location = *loc; return ds->uuid; } @@ -250,8 +249,7 @@ bool dive_site_is_empty(struct dive_site *ds) (empty_string(ds->name) && empty_string(ds->description) && empty_string(ds->notes) && - ds->latitude.udeg == 0 && - ds->longitude.udeg == 0); + !has_location(&ds->location)); } void copy_dive_site(struct dive_site *orig, struct dive_site *copy) @@ -260,8 +258,7 @@ void copy_dive_site(struct dive_site *orig, struct dive_site *copy) free(copy->notes); free(copy->description); - copy->latitude = orig->latitude; - copy->longitude = orig->longitude; + copy->location = orig->location; copy->name = copy_string(orig->name); copy->notes = copy_string(orig->notes); copy->description = copy_string(orig->description); @@ -290,8 +287,7 @@ static void merge_string(char **a, char **b) void merge_dive_site(struct dive_site *a, struct dive_site *b) { - if (!a->latitude.udeg) a->latitude.udeg = b->latitude.udeg; - if (!a->longitude.udeg) a->longitude.udeg = b->longitude.udeg; + if (!has_location(&a->location)) a->location = b->location; merge_string(&a->name, &b->name); merge_string(&a->notes, &b->notes); merge_string(&a->description, &b->description); @@ -310,8 +306,8 @@ void clear_dive_site(struct dive_site *ds) ds->name = NULL; ds->notes = NULL; ds->description = NULL; - ds->latitude.udeg = 0; - ds->longitude.udeg = 0; + ds->location.lat.udeg = 0; + ds->location.lon.udeg = 0; ds->uuid = 0; ds->taxonomy.nr = 0; free_taxonomy(&ds->taxonomy); diff --git a/core/divesite.h b/core/divesite.h index f5fe1dbd5..d739c4520 100644 --- a/core/divesite.h +++ b/core/divesite.h @@ -18,7 +18,7 @@ struct dive_site { uint32_t uuid; char *name; - degrees_t latitude, longitude; + location_t location; char *description; char *notes; struct taxonomy_data taxonomy; @@ -60,17 +60,17 @@ void free_dive_site(struct dive_site *ds); void delete_dive_site(uint32_t id); uint32_t create_dive_site(const char *name, timestamp_t divetime); uint32_t create_dive_site_from_current_dive(const char *name); -uint32_t create_dive_site_with_gps(const char *name, degrees_t latitude, degrees_t longitude, timestamp_t divetime); +uint32_t create_dive_site_with_gps(const char *name, const location_t *, timestamp_t divetime); uint32_t get_dive_site_uuid_by_name(const char *name, struct dive_site **dsp); -uint32_t get_dive_site_uuid_by_gps(degrees_t latitude, degrees_t longitude, struct dive_site **dsp); -uint32_t get_dive_site_uuid_by_gps_and_name(char *name, degrees_t latitude, degrees_t longitude); -uint32_t get_dive_site_uuid_by_gps_proximity(degrees_t latitude, degrees_t longitude, int distance, struct dive_site **dsp); +uint32_t get_dive_site_uuid_by_gps(const location_t *, struct dive_site **dsp); +uint32_t get_dive_site_uuid_by_gps_and_name(char *name, const location_t *); +uint32_t get_dive_site_uuid_by_gps_proximity(const location_t *, int distance, struct dive_site **dsp); bool dive_site_is_empty(struct dive_site *ds); void copy_dive_site_taxonomy(struct dive_site *orig, struct dive_site *copy); void copy_dive_site(struct dive_site *orig, struct dive_site *copy); void merge_dive_site(struct dive_site *a, struct dive_site *b); void clear_dive_site(struct dive_site *ds); -unsigned int get_distance(degrees_t lat1, degrees_t lon1, degrees_t lat2, degrees_t lon2); +unsigned int get_distance(const location_t *loc1, const location_t *loc2); uint32_t find_or_create_dive_site_with_name(const char *name, timestamp_t divetime); void merge_dive_sites(uint32_t ref, uint32_t *uuids, int count); diff --git a/core/gpslocation.cpp b/core/gpslocation.cpp index 54015837b..485cbac56 100644 --- a/core/gpslocation.cpp +++ b/core/gpslocation.cpp @@ -137,7 +137,7 @@ QString GpsLocation::currentPosition() if (delta < 300) { // we can simply use the last position that we tracked gpsTracker gt = m_trackers.last(); - QString gpsString = printGPSCoords(gt.latitude.udeg, gt.longitude.udeg); + QString gpsString = printGPSCoords(>.location); qDebug() << "returning last position" << gpsString; return gpsString; } else { @@ -159,8 +159,8 @@ void GpsLocation::newPosition(QGeoPositionInfo pos) int nr = m_trackers.count(); if (nr) { gpsTracker gt = m_trackers.last(); - lastCoord.setLatitude(gt.latitude.udeg / 1000000.0); - lastCoord.setLongitude(gt.longitude.udeg / 1000000.0); + lastCoord.setLatitude(gt.location.lat.udeg / 1000000.0); + lastCoord.setLongitude(gt.location.lon.udeg / 1000000.0); lastTime = gt.when; } // if we are waiting for a position update or @@ -176,8 +176,7 @@ void GpsLocation::newPosition(QGeoPositionInfo pos) gpsTracker gt; gt.when = pos.timestamp().toTime_t(); gt.when += gettimezoneoffset(gt.when); - gt.latitude.udeg = lrint(pos.coordinate().latitude() * 1000000); - gt.longitude.udeg = lrint(pos.coordinate().longitude() * 1000000); + gt.location = create_location(pos.coordinate().latitude(), pos.coordinate().longitude()); addFixToStorage(gt); gpsTracker gtNew = m_trackers.last(); qDebug() << "newest fix is now at" << QDateTime().fromMSecsSinceEpoch(gtNew.when - gettimezoneoffset(gtNew.when) * 1000).toString(); @@ -215,8 +214,7 @@ static void copy_gps_location(struct gpsTracker &gps, struct dive *d) d->dive_site_uuid = create_dive_site(qPrintable(gps.name), gps.when); ds = get_dive_site_by_uuid(d->dive_site_uuid); } - ds->latitude = gps.latitude; - ds->longitude = gps.longitude; + ds->location = gps.location; } #define SAME_GROUP 6 * 3600 /* six hours */ @@ -331,8 +329,8 @@ void GpsLocation::loadFromStorage() for (int i = 0; i < nr; i++) { struct gpsTracker gt; gt.when = geoSettings->value(QString("gpsFix%1_time").arg(i)).toLongLong(); - gt.latitude.udeg = geoSettings->value(QString("gpsFix%1_lat").arg(i)).toInt(); - gt.longitude.udeg = geoSettings->value(QString("gpsFix%1_lon").arg(i)).toInt(); + gt.location.lat.udeg = geoSettings->value(QString("gpsFix%1_lat").arg(i)).toInt(); + gt.location.lon.udeg = geoSettings->value(QString("gpsFix%1_lon").arg(i)).toInt(); gt.name = geoSettings->value(QString("gpsFix%1_name").arg(i)).toString(); gt.idx = i; m_trackers.insert(gt.when, gt); @@ -347,11 +345,10 @@ void GpsLocation::replaceFixToStorage(gpsTracker >) } gpsTracker replacedTracker = m_trackers.value(gt.when); geoSettings->setValue(QString("gpsFix%1_time").arg(replacedTracker.idx), gt.when); - geoSettings->setValue(QString("gpsFix%1_lat").arg(replacedTracker.idx), gt.latitude.udeg); - geoSettings->setValue(QString("gpsFix%1_lon").arg(replacedTracker.idx), gt.longitude.udeg); + geoSettings->setValue(QString("gpsFix%1_lat").arg(replacedTracker.idx), gt.location.lat.udeg); + geoSettings->setValue(QString("gpsFix%1_lon").arg(replacedTracker.idx), gt.location.lon.udeg); geoSettings->setValue(QString("gpsFix%1_name").arg(replacedTracker.idx), gt.name); - replacedTracker.latitude = gt.latitude; - replacedTracker.longitude = gt.longitude; + replacedTracker.location = gt.location; replacedTracker.name = gt.name; } @@ -360,8 +357,8 @@ void GpsLocation::addFixToStorage(gpsTracker >) int nr = m_trackers.count(); geoSettings->setValue("count", nr + 1); geoSettings->setValue(QString("gpsFix%1_time").arg(nr), gt.when); - geoSettings->setValue(QString("gpsFix%1_lat").arg(nr), gt.latitude.udeg); - geoSettings->setValue(QString("gpsFix%1_lon").arg(nr), gt.longitude.udeg); + geoSettings->setValue(QString("gpsFix%1_lat").arg(nr), gt.location.lat.udeg); + geoSettings->setValue(QString("gpsFix%1_lon").arg(nr), gt.location.lon.udeg); geoSettings->setValue(QString("gpsFix%1_name").arg(nr), gt.name); gt.idx = nr; geoSettings->sync(); @@ -389,8 +386,8 @@ void GpsLocation::deleteFixFromStorage(gpsTracker >) m_trackers.remove(movedTracker.when); m_trackers.insert(movedTracker.when, movedTracker); geoSettings->setValue(QString("gpsFix%1_time").arg(movedTracker.idx), when); - geoSettings->setValue(QString("gpsFix%1_lat").arg(movedTracker.idx), movedTracker.latitude.udeg); - geoSettings->setValue(QString("gpsFix%1_lon").arg(movedTracker.idx), movedTracker.longitude.udeg); + geoSettings->setValue(QString("gpsFix%1_lat").arg(movedTracker.idx), movedTracker.location.lat.udeg); + geoSettings->setValue(QString("gpsFix%1_lon").arg(movedTracker.idx), movedTracker.location.lon.udeg); geoSettings->setValue(QString("gpsFix%1_name").arg(movedTracker.idx), movedTracker.name); geoSettings->remove(QString("gpsFix%1_lat").arg(cnt - 1)); geoSettings->remove(QString("gpsFix%1_lon").arg(cnt - 1)); diff --git a/core/gpslocation.h b/core/gpslocation.h index 70bb17404..02377bfca 100644 --- a/core/gpslocation.h +++ b/core/gpslocation.h @@ -14,8 +14,7 @@ #define GPS_CURRENT_POS gettextFromC::tr("Waiting to aquire GPS location") struct gpsTracker { - degrees_t latitude; - degrees_t longitude; + location_t location; qint64 when; QString name; int idx; diff --git a/core/libdivecomputer.c b/core/libdivecomputer.c index acc6478b2..a4c21b423 100644 --- a/core/libdivecomputer.c +++ b/core/libdivecomputer.c @@ -569,7 +569,7 @@ static void set_dc_serial(struct divecomputer *dc, const char *serial) dc->deviceid = calculate_string_hash(serial); } -extern degrees_t parse_degrees(char *buf, char **end); +extern void parse_location(char *, location_t *); static void parse_string_field(struct dive *dive, dc_field_string_t *str) { @@ -591,14 +591,12 @@ static void parse_string_field(struct dive *dive, dc_field_string_t *str) /* GPS data? */ if (!strncmp(str->desc, "GPS", 3)) { char *line = (char *) str->value; - degrees_t latitude, longitude; + location_t location; - latitude = parse_degrees(line, &line); - if (*line == ',') line++; - longitude = parse_degrees(line, &line); + parse_location(line, &location); - if (latitude.udeg && longitude.udeg) - dive->dive_site_uuid = create_dive_site_with_gps(str->value, latitude, longitude, time(NULL)); + if (location.lat.udeg && location.lon.udeg) + dive->dive_site_uuid = create_dive_site_with_gps(str->value, &location, time(NULL)); } } #endif diff --git a/core/load-git.c b/core/load-git.c index 0abae4239..2040d2f70 100644 --- a/core/load-git.c +++ b/core/load-git.c @@ -31,7 +31,7 @@ struct keyword_action { }; #define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0])) -extern degrees_t parse_degrees(char *buf, char **end); +extern void parse_location(char *buf, location_t *); git_blob *git_tree_entry_blob(git_repository *repo, const git_tree_entry *entry); static char *get_utf8(struct membuffer *b) @@ -152,25 +152,24 @@ static void parse_dive_gps(char *line, struct membuffer *str, void *_dive) { UNUSED(str); uint32_t uuid; - degrees_t latitude = parse_degrees(line, &line); - degrees_t longitude = parse_degrees(line, &line); + location_t location; struct dive *dive = _dive; struct dive_site *ds = get_dive_site_for_dive(dive); + + parse_location(line, &location); if (!ds) { - uuid = get_dive_site_uuid_by_gps(latitude, longitude, NULL); + uuid = get_dive_site_uuid_by_gps(&location, NULL); if (!uuid) - uuid = create_dive_site_with_gps("", latitude, longitude, dive->when); + uuid = create_dive_site_with_gps("", &location, dive->when); dive->dive_site_uuid = uuid; } else { - if (dive_site_has_gps_location(ds) && - (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { - const char *coords = printGPSCoords(latitude.udeg, longitude.udeg); + if (dive_site_has_gps_location(ds) && !same_location(&ds->location, &location)) { + const char *coords = printGPSCoords(&location); // we have a dive site that already has GPS coordinates ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords); free((void *)coords); } - ds->latitude = latitude; - ds->longitude = longitude; + ds->location = location; } } @@ -274,14 +273,12 @@ static void parse_site_name(char *line, struct membuffer *str, void *_ds) static void parse_site_notes(char *line, struct membuffer *str, void *_ds) { UNUSED(line); struct dive_site *ds = _ds; ds->notes = strdup(mb_cstring(str)); } -extern degrees_t parse_degrees(char *buf, char **end); static void parse_site_gps(char *line, struct membuffer *str, void *_ds) { UNUSED(str); struct dive_site *ds = _ds; - ds->latitude = parse_degrees(line, &line); - ds->longitude = parse_degrees(line, &line); + parse_location(line, &ds->location); } static void parse_site_geo(char *line, struct membuffer *str, void *_ds) @@ -949,8 +946,7 @@ static void parse_picture_gps(char *line, struct membuffer *str, void *_pic) UNUSED(str); struct picture *pic = _pic; - pic->latitude = parse_degrees(line, &line); - pic->longitude = parse_degrees(line, &line); + parse_location(line, &pic->location); } static void parse_picture_hash(char *line, struct membuffer *str, void *_pic) diff --git a/core/membuffer.c b/core/membuffer.c index 1d486b3a6..46cb541f1 100644 --- a/core/membuffer.c +++ b/core/membuffer.c @@ -218,6 +218,14 @@ void put_degrees(struct membuffer *b, degrees_t value, const char *pre, const ch put_format(b, "%s%s%u.%06u%s", pre, sign, FRACTION(udeg, 1000000), post); } +void put_location(struct membuffer *b, location_t *loc, const char *pre, const char *post) +{ + if (has_location(loc)) { + put_degrees(b, loc->lat, pre, " "); + put_degrees(b, loc->lon, "", post); + } +} + void put_quoted(struct membuffer *b, const char *text, int is_attribute, int is_html) { const char *p = text; diff --git a/core/membuffer.h b/core/membuffer.h index 7bcb5b51f..cc441ba24 100644 --- a/core/membuffer.h +++ b/core/membuffer.h @@ -109,6 +109,7 @@ extern void put_duration(struct membuffer *, duration_t, const char *, const cha extern void put_pressure(struct membuffer *, pressure_t, const char *, const char *); extern void put_salinity(struct membuffer *, int, const char *, const char *); extern void put_degrees(struct membuffer *b, degrees_t value, const char *, const char *); +extern void put_location(struct membuffer *b, location_t *, const char *, const char *); #ifdef __cplusplus } diff --git a/core/metadata.cpp b/core/metadata.cpp index b549a5b3b..dae261b93 100644 --- a/core/metadata.cpp +++ b/core/metadata.cpp @@ -97,8 +97,7 @@ static bool parseExif(QFile &f, struct metadata *metadata) easyexif::EXIFInfo exif; if (exif.parseFromEXIFSegment(reinterpret_cast<const unsigned char *>(data.constData()), len) != PARSE_EXIF_SUCCESS) return false; - metadata->longitude.udeg = lrint(1000000.0 * exif.GeoLocation.Longitude); - metadata->latitude.udeg = lrint(1000000.0 * exif.GeoLocation.Latitude); + metadata->location = create_location(exif.GeoLocation.Latitude, exif.GeoLocation.Longitude); metadata->timestamp = exif.epoch(); return true; } @@ -521,8 +520,8 @@ extern "C" mediatype_t get_metadata(const char *filename_in, metadata *data) { data->timestamp = 0; data->duration.seconds = 0; - data->latitude.udeg = 0; - data->longitude.udeg = 0; + data->location.lat.udeg = 0; + data->location.lon.udeg = 0; QString filename = localFilePath(QString(filename_in)); QFile f(filename); diff --git a/core/metadata.h b/core/metadata.h index 4470bdc88..253763ad8 100644 --- a/core/metadata.h +++ b/core/metadata.h @@ -6,8 +6,7 @@ struct metadata { timestamp_t timestamp; duration_t duration; - degrees_t latitude; - degrees_t longitude; + location_t location; }; enum mediatype_t { diff --git a/core/parse-xml.c b/core/parse-xml.c index 6af570739..ccc66f336 100644 --- a/core/parse-xml.c +++ b/core/parse-xml.c @@ -1066,7 +1066,7 @@ static int uddf_dive_match(struct dive *dive, const char *name, char *buf) * We don't do exponentials etc, if somebody does * GPS locations in that format, they are insane. */ -degrees_t parse_degrees(char *buf, char **end) +static degrees_t parse_degrees(char *buf, char **end) { int sign = 1, decimals = 6, value = 0; degrees_t ret; @@ -1112,86 +1112,90 @@ degrees_t parse_degrees(char *buf, char **end) static void gps_lat(char *buffer, struct dive *dive) { char *end; - degrees_t latitude = parse_degrees(buffer, &end); + location_t location = { }; struct dive_site *ds = get_dive_site_for_dive(dive); + + location.lat = parse_degrees(buffer, &end); if (!ds) { - dive->dive_site_uuid = create_dive_site_with_gps(NULL, latitude, (degrees_t){0}, dive->when); + dive->dive_site_uuid = create_dive_site_with_gps(NULL, &location, dive->when); } else { - if (ds->latitude.udeg && ds->latitude.udeg != latitude.udeg) + if (ds->location.lat.udeg && ds->location.lat.udeg != location.lat.udeg) fprintf(stderr, "Oops, changing the latitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); - ds->latitude = latitude; + ds->location.lat = location.lat; } } static void gps_long(char *buffer, struct dive *dive) { char *end; - degrees_t longitude = parse_degrees(buffer, &end); + location_t location = { }; struct dive_site *ds = get_dive_site_for_dive(dive); + + location.lon = parse_degrees(buffer, &end); if (!ds) { - dive->dive_site_uuid = create_dive_site_with_gps(NULL, (degrees_t){0}, longitude, dive->when); + dive->dive_site_uuid = create_dive_site_with_gps(NULL, &location, dive->when); } else { - if (ds->longitude.udeg && ds->longitude.udeg != longitude.udeg) + if (ds->location.lon.udeg && ds->location.lon.udeg != location.lon.udeg) fprintf(stderr, "Oops, changing the longitude of existing dive site id %8x name %s; not good\n", ds->uuid, ds->name ?: "(unknown)"); - ds->longitude = longitude; + ds->location.lon = location.lon; } } -static void gps_location(char *buffer, struct dive_site *ds) +/* We allow either spaces or a comma between the decimal degrees */ +void parse_location(char *buffer, location_t *loc) { char *end; + loc->lat = parse_degrees(buffer, &end); + if (*end == ',') end++; + loc->lon = parse_degrees(end, &end); +} - ds->latitude = parse_degrees(buffer, &end); - ds->longitude = parse_degrees(end, &end); +static void gps_location(char *buffer, struct dive_site *ds) +{ + parse_location(buffer, &ds->location); } static void gps_in_dive(char *buffer, struct dive *dive) { - char *end; struct dive_site *ds = NULL; - degrees_t latitude = parse_degrees(buffer, &end); - degrees_t longitude = parse_degrees(end, &end); + location_t location; uint32_t uuid = dive->dive_site_uuid; + + parse_location(buffer, &location); if (uuid == 0) { // check if we have a dive site within 20 meters of that gps fix - uuid = get_dive_site_uuid_by_gps_proximity(latitude, longitude, 20, &ds); + uuid = get_dive_site_uuid_by_gps_proximity(&location, 20, &ds); if (ds) { // found a site nearby; in case it turns out this one had a different name let's // remember the original coordinates so we can create the correct dive site later - cur_latitude = latitude; - cur_longitude = longitude; + cur_location = location; dive->dive_site_uuid = uuid; } else { - dive->dive_site_uuid = create_dive_site_with_gps("", latitude, longitude, dive->when); + dive->dive_site_uuid = create_dive_site_with_gps("", &location, dive->when); ds = get_dive_site_by_uuid(dive->dive_site_uuid); } } else { ds = get_dive_site_by_uuid(uuid); if (dive_site_has_gps_location(ds) && - (latitude.udeg != 0 || longitude.udeg != 0) && - (ds->latitude.udeg != latitude.udeg || ds->longitude.udeg != longitude.udeg)) { + has_location(&location) && !same_location(&ds->location, &location)) { // Houston, we have a problem fprintf(stderr, "dive site uuid in dive, but gps location (%10.6f/%10.6f) different from dive location (%10.6f/%10.6f)\n", - ds->latitude.udeg / 1000000.0, ds->longitude.udeg / 1000000.0, - latitude.udeg / 1000000.0, longitude.udeg / 1000000.0); - const char *coords = printGPSCoords(latitude.udeg, longitude.udeg); + ds->location.lat.udeg / 1000000.0, ds->location.lon.udeg / 1000000.0, + location.lat.udeg / 1000000.0, location.lon.udeg / 1000000.0); + const char *coords = printGPSCoords(&location); ds->notes = add_to_string(ds->notes, translate("gettextFromC", "multiple GPS locations for this dive site; also %s\n"), coords); free((void *)coords); } else { - ds->latitude = latitude; - ds->longitude = longitude; + ds->location = location; } } } static void gps_picture_location(char *buffer, struct picture *pic) { - char *end; - - pic->latitude = parse_degrees(buffer, &end); - pic->longitude = parse_degrees(end, &end); + parse_location(buffer, &pic->location); } /* We're in the top-level dive xml. Try to convert whatever value to a dive value */ @@ -2100,9 +2104,9 @@ int parse_dlf_buffer(unsigned char *buffer, size_t size, struct dive_table *tabl break; case 4: /* Measure GPS */ - cur_latitude.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0)); - cur_longitude.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0)); - cur_dive->dive_site_uuid = create_dive_site_with_gps("DLF imported", cur_latitude, cur_longitude, cur_dive->when); + cur_location.lat.udeg = (int)((ptr[7] << 24) + (ptr[6] << 16) + (ptr[5] << 8) + (ptr[4] << 0)); + cur_location.lon.udeg = (int)((ptr[11] << 24) + (ptr[10] << 16) + (ptr[9] << 8) + (ptr[8] << 0)); + cur_dive->dive_site_uuid = create_dive_site_with_gps("DLF imported", &cur_location, cur_dive->when); break; default: break; diff --git a/core/parse.c b/core/parse.c index 067008970..76b66733f 100644 --- a/core/parse.c +++ b/core/parse.c @@ -22,7 +22,7 @@ struct parser_settings cur_settings; struct divecomputer *cur_dc = NULL; struct dive *cur_dive = NULL; struct dive_site *cur_dive_site = NULL; -degrees_t cur_latitude, cur_longitude; +location_t cur_location; dive_trip_t *cur_trip = NULL; struct sample *cur_sample = NULL; struct picture *cur_picture = NULL; @@ -258,8 +258,8 @@ void dive_end(void) record_dive_to_table(cur_dive, target_table); cur_dive = NULL; cur_dc = NULL; - cur_latitude.udeg = 0; - cur_longitude.udeg = 0; + cur_location.lat.udeg = 0; + cur_location.lon.udeg = 0; cur_cylinder_index = 0; cur_ws_index = 0; } @@ -442,19 +442,17 @@ void add_dive_site(char *ds_name, struct dive *dive) // but wait, we could have gotten this one based on GPS coords and could // have had two different names for the same site... so let's search the other // way around - uint32_t exact_match_uuid = get_dive_site_uuid_by_gps_and_name(buffer, ds->latitude, ds->longitude); + uint32_t exact_match_uuid = get_dive_site_uuid_by_gps_and_name(buffer, &ds->location); if (exact_match_uuid) { dive->dive_site_uuid = exact_match_uuid; } else { dive->dive_site_uuid = create_dive_site(buffer, dive->when); struct dive_site *newds = get_dive_site_by_uuid(dive->dive_site_uuid); - if (cur_latitude.udeg || cur_longitude.udeg) { + if (has_location(&cur_location)) { // we started this uuid with GPS data, so lets use those - newds->latitude = cur_latitude; - newds->longitude = cur_longitude; + newds->location = cur_location; } else { - newds->latitude = ds->latitude; - newds->longitude = ds->longitude; + newds->location = ds->location; } newds->notes = add_to_string(newds->notes, translate("gettextFromC", "additional name for site: %s\n"), ds->name); } diff --git a/core/parse.h b/core/parse.h index b2c2cbb96..8575fd46a 100644 --- a/core/parse.h +++ b/core/parse.h @@ -18,7 +18,7 @@ extern event_allocation_t event_allocation; extern struct divecomputer *cur_dc; extern struct dive *cur_dive; extern struct dive_site *cur_dive_site; -extern degrees_t cur_latitude, cur_longitude; +extern location_t cur_location; extern dive_trip_t *cur_trip; extern struct sample *cur_sample; extern struct picture *cur_picture; diff --git a/core/qthelper.cpp b/core/qthelper.cpp index fd7934885..23ccbfec0 100644 --- a/core/qthelper.cpp +++ b/core/qthelper.cpp @@ -75,14 +75,16 @@ QString distance_string(int distanceInMeters) return str; } -extern "C" const char *printGPSCoords(int lat, int lon) +extern "C" const char *printGPSCoords(const location_t *loc) { + int lat = loc->lat.udeg; + int lon = loc->lon.udeg; unsigned int latdeg, londeg; unsigned int latmin, lonmin; double latsec, lonsec; QString lath, lonh, result; - if (!lat && !lon) + if (!has_location(loc)) return strdup(""); if (prefs.coordinates_traditional) { @@ -247,30 +249,24 @@ bool parseGpsText(const QString &gps_text, double *latitude, double *longitude) #if 0 // we'll need something like this for the dive site management, eventually bool gpsHasChanged(struct dive *dive, struct dive *master, const QString &gps_text, bool *parsed_out) { - double latitude, longitude; - int latudeg, longudeg; + location_t location; bool ignore; bool *parsed = parsed_out ?: &ignore; *parsed = true; /* if we have a master and the dive's gps address is different from it, * don't change the dive */ - if (master && (master->latitude.udeg != dive->latitude.udeg || - master->longitude.udeg != dive->longitude.udeg)) + if (master && !same_location(&master->location, &dive->location)) return false; - if (!(*parsed = parseGpsText(gps_text, &latitude, &longitude))) + if (!(*parsed = parseGpsText(gps_text, location))) return false; - latudeg = lrint(1000000 * latitude); - longudeg = lrint(1000000 * longitude); - /* if dive gps didn't change, nothing changed */ - if (dive->latitude.udeg == latudeg && dive->longitude.udeg == longudeg) + if (same_location(&dive->location, location)) return false; /* ok, update the dive and mark things changed */ - dive->latitude.udeg = latudeg; - dive->longitude.udeg = longudeg; + dive->location = location; return true; } #endif diff --git a/core/qthelper.h b/core/qthelper.h index fa41fd339..deb893634 100644 --- a/core/qthelper.h +++ b/core/qthelper.h @@ -124,7 +124,7 @@ void moveInVector(Vector &v, int rangeBegin, int rangeEnd, int destination) extern "C" { #endif -const char *printGPSCoords(int lat, int lon); +const char *printGPSCoords(const location_t *loc); bool in_planner(); bool getProxyString(char **buffer); bool canReachCloudServer(); diff --git a/core/save-git.c b/core/save-git.c index 7db47dc94..938b7d3a5 100644 --- a/core/save-git.c +++ b/core/save-git.c @@ -38,14 +38,6 @@ static void cond_put_format(int cond, struct membuffer *b, const char *fmt, ...) #define SAVE(str, x) cond_put_format(dive->x, b, str " %d\n", dive->x) -static void show_gps(struct membuffer *b, degrees_t latitude, degrees_t longitude) -{ - if (latitude.udeg || longitude.udeg) { - put_degrees(b, latitude, "gps ", " "); - put_degrees(b, longitude, "", "\n"); - } -} - static void quote(struct membuffer *b, const char *text) { const char *p = text; @@ -613,7 +605,7 @@ static int save_one_picture(git_repository *repo, struct dir *dir, struct pictur unsigned h; show_utf8(&buf, "filename ", pic->filename, "\n"); - show_gps(&buf, pic->latitude, pic->longitude); + put_location(&buf, &pic->location, "gps ", "\n"); /* Picture loading will load even negative offsets.. */ if (offset < 0) { @@ -921,7 +913,7 @@ static void save_divesites(git_repository *repo, struct dir *tree) show_utf8(&b, "name ", ds->name, "\n"); show_utf8(&b, "description ", ds->description, "\n"); show_utf8(&b, "notes ", ds->notes, "\n"); - show_gps(&b, ds->latitude, ds->longitude); + put_location(&b, &ds->location, "gps ", "\n"); for (int j = 0; j < ds->taxonomy.nr; j++) { struct taxonomy *t = &ds->taxonomy.category[j]; if (t->category != TC_NONE && t->value) { diff --git a/core/save-html.c b/core/save-html.c index 413718692..ea46d49ea 100644 --- a/core/save-html.c +++ b/core/save-html.c @@ -191,8 +191,8 @@ void put_HTML_coordinates(struct membuffer *b, struct dive *dive) struct dive_site *ds = get_dive_site_for_dive(dive); if (!ds) return; - degrees_t latitude = ds->latitude; - degrees_t longitude = ds->longitude; + degrees_t latitude = ds->location.lat; + degrees_t longitude = ds->location.lon; //don't put coordinates if in (0,0) if (!latitude.udeg && !longitude.udeg) diff --git a/core/save-xml.c b/core/save-xml.c index 96932c900..fad5f584a 100644 --- a/core/save-xml.c +++ b/core/save-xml.c @@ -464,10 +464,7 @@ static void save_picture(struct membuffer *b, struct picture *pic) } put_format(b, " offset='%c%u:%02u min'", sign, FRACTION(offset, 60)); } - if (pic->latitude.udeg || pic->longitude.udeg) { - put_degrees(b, pic->latitude, " gps='", " "); - put_degrees(b, pic->longitude, "", "'"); - } + put_location(b, &pic->location, " gps='","'"); put_string(b, "/>\n"); } @@ -630,10 +627,7 @@ void save_dives_buffer(struct membuffer *b, const bool select_only, bool anonymi put_format(b, "<site uuid='%8x'", ds->uuid); show_utf8_blanked(b, ds->name, " name='", "'", 1, anonymize); - if (ds->latitude.udeg || ds->longitude.udeg) { - put_degrees(b, ds->latitude, " gps='", " "); - put_degrees(b, ds->longitude, "", "'"); - } + put_location(b, &ds->location, " gps='", "'"); show_utf8_blanked(b, ds->description, " description='", "'", 1, anonymize); put_format(b, ">\n"); show_utf8_blanked(b, ds->notes, " <notes>", " </notes>\n", 0, anonymize); diff --git a/core/subsurface-qt/DiveObjectHelper.cpp b/core/subsurface-qt/DiveObjectHelper.cpp index a69c73ddc..a4d05f0ca 100644 --- a/core/subsurface-qt/DiveObjectHelper.cpp +++ b/core/subsurface-qt/DiveObjectHelper.cpp @@ -108,7 +108,7 @@ QString DiveObjectHelper::location() const QString DiveObjectHelper::gps() const { struct dive_site *ds = get_dive_site_by_uuid(m_dive->dive_site_uuid); - return ds ? QString(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg)) : QString(); + return ds ? QString(printGPSCoords(&ds->location)) : QString(); } QString DiveObjectHelper::gps_decimal() const diff --git a/core/uemis.c b/core/uemis.c index 33005108b..7595131cf 100644 --- a/core/uemis.c +++ b/core/uemis.c @@ -173,8 +173,7 @@ void uemis_set_divelocation(int divespot, char *text, double longitude, double l struct dive_site *ds = get_dive_site_by_uuid(hp->dive_site_uuid); if (ds) { ds->name = strdup(text); - ds->longitude.udeg = lrint(longitude * 1000000); - ds->latitude.udeg = lrint(latitude * 1000000); + ds->location = create_location(latitude, longitude); } } hp = hp->next; diff --git a/core/units.h b/core/units.h index 6e9fe50d9..0e2c2b2e3 100644 --- a/core/units.h +++ b/core/units.h @@ -134,6 +134,29 @@ typedef struct int udeg; } degrees_t; +typedef struct pos { + degrees_t lat, lon; +} location_t; + +static inline bool has_location(const location_t *loc) +{ + return loc->lat.udeg || loc->lon.udeg; +} + +static inline bool same_location(const location_t *a, const location_t *b) +{ + return (a->lat.udeg == b->lat.udeg) && (a->lon.udeg == b->lon.udeg); +} + +static inline location_t create_location(double lat, double lon) +{ + location_t location = { + { (int) lrint(lat * 1000000) }, + { (int) lrint(lon * 1000000) } + }; + return location; +} + static inline double udeg_to_radians(int udeg) { return (udeg * M_PI) / (1000000.0 * 180.0); diff --git a/core/worldmap-save.c b/core/worldmap-save.c index cbc232bc3..c12d27de2 100644 --- a/core/worldmap-save.c +++ b/core/worldmap-save.c @@ -35,8 +35,8 @@ void writeMarkers(struct membuffer *b, const bool selected_only) struct dive_site *ds = get_dive_site_for_dive(dive); if (!ds || !dive_site_has_gps_location(ds)) continue; - put_degrees(b, ds->latitude, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); - put_degrees(b, ds->longitude, ",", ")});\n"); + put_degrees(b, ds->location.lat, "temp = new google.maps.Marker({position: new google.maps.LatLng(", ""); + put_degrees(b, ds->location.lon, ",", ")});\n"); put_string(b, "markers.push(temp);\ntempinfowindow = new google.maps.InfoWindow({content: '<div id=\"content\">'+'<div id=\"siteNotice\">'+'</div>'+'<div id=\"bodyContent\">"); snprintf(pre, sizeof(pre), "<p>%s ", translate("gettextFromC", "Date:")); put_HTML_date(b, dive, pre, "</p>"); diff --git a/desktop-widgets/divelogexportdialog.cpp b/desktop-widgets/divelogexportdialog.cpp index 747dc5258..928256df4 100644 --- a/desktop-widgets/divelogexportdialog.cpp +++ b/desktop-widgets/divelogexportdialog.cpp @@ -315,8 +315,8 @@ void DiveLogExportDialog::export_TeX(const char *filename, const bool selected_o put_format(&buf, "\\def\\place{%s}\n", site ? site->name : ""); put_format(&buf, "\\def\\spot{}\n"); put_format(&buf, "\\def\\sitename{%s}\n", site ? site->name : ""); - site ? put_format(&buf, "\\def\\gpslat{%f}\n", site->latitude.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslat{}\n"); - site ? put_format(&buf, "\\def\\gpslon{%f}\n", site->longitude.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\n"); + site ? put_format(&buf, "\\def\\gpslat{%f}\n", site->location.lat.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslat{}\n"); + site ? put_format(&buf, "\\def\\gpslon{%f}\n", site->location.lon.udeg / 1000000.0) : put_format(&buf, "\\def\\gpslon{}\n"); put_format(&buf, "\\def\\computer{%s}\n", dive->dc.model); put_format(&buf, "\\def\\country{%s}\n", qPrintable(country)); put_format(&buf, "\\def\\time{%u:%02u}\n", FRACTION(dive->duration.seconds, 60)); diff --git a/desktop-widgets/locationinformation.cpp b/desktop-widgets/locationinformation.cpp index 225e7ed78..9d3eccb02 100644 --- a/desktop-widgets/locationinformation.cpp +++ b/desktop-widgets/locationinformation.cpp @@ -116,8 +116,8 @@ void LocationInformationWidget::updateLabels() ui.diveSiteNotes->setPlainText(diveSite->notes); else ui.diveSiteNotes->clear(); - if (diveSite->latitude.udeg || diveSite->longitude.udeg) { - const char *coords = printGPSCoords(diveSite->latitude.udeg, diveSite->longitude.udeg); + if (has_location(&diveSite->location)) { + const char *coords = printGPSCoords(&diveSite->location); ui.diveSiteCoordinates->setText(coords); free((void *)coords); } else { @@ -137,12 +137,13 @@ void LocationInformationWidget::clearLabels() ui.locationTags->clear(); } -void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees_t longitude) +void LocationInformationWidget::updateGpsCoordinates(const location_t &location) { QString oldText = ui.diveSiteCoordinates->text(); - const char *coords = printGPSCoords(latitude.udeg, longitude.udeg); + + const char *coords = printGPSCoords(&location); ui.diveSiteCoordinates->setText(coords); - enableLocationButtons(latitude.udeg || longitude.udeg); + enableLocationButtons(has_location(&location)); free((void *)coords); if (oldText != ui.diveSiteCoordinates->text()) markChangedWidget(ui.diveSiteCoordinates); @@ -150,12 +151,11 @@ void LocationInformationWidget::updateGpsCoordinates(degrees_t latitude, degrees // Parse GPS text into latitude and longitude. // On error, false is returned and the output parameters are left unmodified. -bool parseGpsText(const QString &text, degrees_t &latitude, degrees_t &longitude) +bool parseGpsText(const QString &text, location_t &location) { double lat, lon; if (parseGpsText(text, &lat, &lon)) { - latitude.udeg = lrint(lat * 1000000.0); - longitude.udeg = lrint(lon * 1000000.0); + location = create_location(lat, lon); return true; } return false; @@ -204,7 +204,7 @@ void LocationInformationWidget::acceptChanges() } if (!ui.diveSiteCoordinates->text().isEmpty()) - parseGpsText(ui.diveSiteCoordinates->text(), diveSite->latitude, diveSite->longitude); + parseGpsText(ui.diveSiteCoordinates->text(), diveSite->location); if (dive_site_is_empty(diveSite)) { LocationInformationModel::instance()->removeRow(get_divesite_idx(diveSite)); displayed_dive.dive_site_uuid = 0; @@ -224,7 +224,7 @@ void LocationInformationWidget::initFields(dive_site *ds) diveSite = ds; if (ds) { copy_taxonomy(&ds->taxonomy, &taxonomy); - filter_model.set(ds->uuid, ds->latitude, ds->longitude); + filter_model.set(ds->uuid, ds->location); updateLabels(); enableLocationButtons(dive_site_has_gps_location(ds)); QSortFilterProxyModel *m = qobject_cast<QSortFilterProxyModel *>(ui.diveSiteListView->model()); @@ -233,7 +233,7 @@ void LocationInformationWidget::initFields(dive_site *ds) m->invalidate(); } else { free_taxonomy(&taxonomy); - filter_model.set(0, degrees_t{ 0 }, degrees_t{ 0 }); + filter_model.set(0, location_t { degrees_t{ 0 }, degrees_t{ 0 } }); clearLabels(); } MapWidget::instance()->prepareForGetDiveCoordinates(ds ? ds->uuid : 0); @@ -276,14 +276,14 @@ void LocationInformationWidget::on_diveSiteCoordinates_textChanged(const QString { if (!diveSite) return; - degrees_t latitude, longitude; - bool ok_old = diveSite->latitude.udeg || diveSite->longitude.udeg; - bool ok = parseGpsText(text, latitude, longitude); - if (ok != ok_old || latitude.udeg != diveSite->latitude.udeg || longitude.udeg != diveSite->longitude.udeg) { + location_t location; + bool ok_old = has_location(&diveSite->location); + bool ok = parseGpsText(text, location); + if (ok != ok_old || !same_location(&location, &diveSite->location)) { if (ok) { markChangedWidget(ui.diveSiteCoordinates); enableLocationButtons(true); - filter_model.setCoordinates(latitude, longitude); + filter_model.setCoordinates(location); } else { enableLocationButtons(false); } @@ -326,10 +326,10 @@ void LocationInformationWidget::resetPallete() void LocationInformationWidget::reverseGeocode() { - degrees_t latitude, longitude; - if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude)) + location_t location; + if (!parseGpsText(ui.diveSiteCoordinates->text(), location)) return; - reverseGeoLookup(latitude, longitude, &taxonomy); + reverseGeoLookup(location.lat, location.lon, &taxonomy); ui.locationTags->setText(constructLocationTags(&taxonomy, false)); } @@ -337,11 +337,11 @@ void LocationInformationWidget::updateLocationOnMap() { if (!diveSite) return; - degrees_t latitude, longitude; - if (!parseGpsText(ui.diveSiteCoordinates->text(), latitude, longitude)) + location_t location; + if (!parseGpsText(ui.diveSiteCoordinates->text(), location)) return; - MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, latitude, longitude); - filter_model.setCoordinates(latitude, longitude); + MapWidget::instance()->updateDiveSiteCoordinates(diveSite->uuid, location); + filter_model.setCoordinates(location); } DiveLocationFilterProxyModel::DiveLocationFilterProxyModel(QObject*) diff --git a/desktop-widgets/locationinformation.h b/desktop-widgets/locationinformation.h index a6141c4fc..a072c4193 100644 --- a/desktop-widgets/locationinformation.h +++ b/desktop-widgets/locationinformation.h @@ -24,7 +24,7 @@ protected: public slots: void acceptChanges(); void rejectChanges(); - void updateGpsCoordinates(degrees_t latitude, degrees_t longitude); + void updateGpsCoordinates(const location_t &); void markChangedWidget(QWidget *w); void enableEdition(); void resetState(); diff --git a/desktop-widgets/mapwidget.cpp b/desktop-widgets/mapwidget.cpp index 945e9fe1c..095565618 100644 --- a/desktop-widgets/mapwidget.cpp +++ b/desktop-widgets/mapwidget.cpp @@ -109,16 +109,16 @@ void MapWidget::selectedDivesChanged(QList<int> list) skipReload = false; } -void MapWidget::coordinatesChangedLocal(degrees_t latitude, degrees_t longitude) +void MapWidget::coordinatesChangedLocal(const location_t &location) { CHECK_IS_READY_RETURN_VOID(); - emit coordinatesChanged(latitude, longitude); + emit coordinatesChanged(location); } -void MapWidget::updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude) +void MapWidget::updateDiveSiteCoordinates(uint32_t uuid, const location_t &location) { CHECK_IS_READY_RETURN_VOID(); - m_mapHelper->updateDiveSiteCoordinates(uuid, latitude, longitude); + m_mapHelper->updateDiveSiteCoordinates(uuid, location); } MapWidget::~MapWidget() diff --git a/desktop-widgets/mapwidget.h b/desktop-widgets/mapwidget.h index eb7d994aa..aaed93218 100644 --- a/desktop-widgets/mapwidget.h +++ b/desktop-widgets/mapwidget.h @@ -25,7 +25,7 @@ public: void reload(); signals: - void coordinatesChanged(degrees_t latitude, degrees_t longitude); + void coordinatesChanged(const location_t &); public slots: void centerOnSelectedDiveSite(); @@ -35,9 +35,9 @@ public slots: void repopulateLabels(); void prepareForGetDiveCoordinates(uint32_t uuid); void selectedDivesChanged(QList<int>); - void coordinatesChangedLocal(degrees_t latitude, degrees_t longitude); + void coordinatesChangedLocal(const location_t &); void doneLoading(QQuickWidget::Status status); - void updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude); + void updateDiveSiteCoordinates(uint32_t uuid, const location_t &); private: static MapWidget *m_instance; diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp index 7b9bd8952..842598467 100644 --- a/desktop-widgets/modeldelegates.cpp +++ b/desktop-widgets/modeldelegates.cpp @@ -479,7 +479,7 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem } if (bottomText.isEmpty()) { - const char *gpsCoords = printGPSCoords(ds->latitude.udeg, ds->longitude.udeg); + const char *gpsCoords = printGPSCoords(&ds->location); bottomText = QString(gpsCoords); free( (void*) gpsCoords); } @@ -487,11 +487,10 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem if (dive_site_has_gps_location(ds) && currentDiveSiteHasGPS) { // so we are showing a completion and both the current dive site and the completion // have a GPS fix... so let's show the distance - if (ds->latitude.udeg == currentDiveSite->latitude.udeg && - ds->longitude.udeg == currentDiveSite->longitude.udeg) { + if (same_location(&ds->location, ¤tDiveSite->location)) { bottomText += tr(" (same GPS fix)"); } else { - int distanceMeters = get_distance(ds->latitude, ds->longitude, currentDiveSite->latitude, currentDiveSite->longitude); + int distanceMeters = get_distance(&ds->location, ¤tDiveSite->location); QString distance = distance_string(distanceMeters); int nr = nr_of_dives_at_dive_site(ds->uuid, false); bottomText += tr(" (~%1 away").arg(distance); diff --git a/desktop-widgets/subsurfacewebservices.cpp b/desktop-widgets/subsurfacewebservices.cpp index db2fece76..7e67366eb 100644 --- a/desktop-widgets/subsurfacewebservices.cpp +++ b/desktop-widgets/subsurfacewebservices.cpp @@ -204,10 +204,7 @@ bool DivelogsDeWebServices::prepare_dives_for_divelogs(const QString &tempfile, put_format(&mb, "<divelog><divesites><site uuid='%8x' name='", dive->dive_site_uuid); put_quoted(&mb, ds->name, 1, 0); put_format(&mb, "'"); - if (ds->latitude.udeg || ds->longitude.udeg) { - put_degrees(&mb, ds->latitude, " gps='", " "); - put_degrees(&mb, ds->longitude, "", "'"); - } + put_location(&mb, &ds->location, " gps='", "'"); put_format(&mb, ">\n"); if (ds->taxonomy.nr) { for (int j = 0; j < ds->taxonomy.nr; j++) { diff --git a/desktop-widgets/tab-widgets/maintab.cpp b/desktop-widgets/tab-widgets/maintab.cpp index bb8f0d904..6f3691d3d 100644 --- a/desktop-widgets/tab-widgets/maintab.cpp +++ b/desktop-widgets/tab-widgets/maintab.cpp @@ -696,9 +696,8 @@ uint32_t MainTab::updateDiveSite(uint32_t pickedUuid, dive *d) newDs->name = copy_qstring(ui.location->text()); newDs->uuid = pickedUuid; qDebug() << "Creating and copying dive site"; - } else if (newDs->latitude.udeg == 0 && newDs->longitude.udeg == 0) { - newDs->latitude.udeg = origDs->latitude.udeg; - newDs->longitude.udeg = origDs->longitude.udeg; + } else if (!has_location(&newDs->location)) { + newDs->location = origDs->location; qDebug() << "Copying GPS information"; } } diff --git a/map-widget/qmlmapwidgethelper.cpp b/map-widget/qmlmapwidgethelper.cpp index 4d4596ab7..dcf57182c 100644 --- a/map-widget/qmlmapwidgethelper.cpp +++ b/map-widget/qmlmapwidgethelper.cpp @@ -28,7 +28,7 @@ QGeoCoordinate MapWidgetHelper::getCoordinatesForUUID(QVariant dive_site_uuid) struct dive_site *ds = get_dive_site_by_uuid(uuid); if (!ds || !dive_site_has_gps_location(ds)) return QGeoCoordinate(0.0, 0.0); - return QGeoCoordinate(ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001); + return QGeoCoordinate(ds->location.lat.udeg * 0.000001, ds->location.lon.udeg * 0.000001); } void MapWidgetHelper::centerOnDiveSiteUUID(QVariant dive_site_uuid) @@ -48,7 +48,7 @@ void MapWidgetHelper::centerOnDiveSite(struct dive_site *ds) } else { // dive site with GPS m_mapLocationModel->setSelectedUuid(ds->uuid, false); - QGeoCoordinate dsCoord (ds->latitude.udeg * 0.000001, ds->longitude.udeg * 0.000001); + QGeoCoordinate dsCoord (ds->location.lat.udeg * 0.000001, ds->location.lon.udeg * 0.000001); QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(dsCoord))); } } @@ -68,8 +68,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite() continue; // only store dive sites with GPS selDS.append(dss); - selGC.append(QGeoCoordinate(dss->latitude.udeg * 0.000001, - dss->longitude.udeg * 0.000001)); + selGC.append(QGeoCoordinate(dss->location.lat.udeg * 0.000001, + dss->location.lon.udeg * 0.000001)); } if (selDS.isEmpty()) { @@ -86,8 +86,8 @@ void MapWidgetHelper::centerOnSelectedDiveSite() qreal minLat = 0.0, minLon = 0.0, maxLat = 0.0, maxLon = 0.0; bool start = true; for(struct dive_site *dss: selDS) { - qreal lat = dss->latitude.udeg * 0.000001; - qreal lon = dss->longitude.udeg * 0.000001; + qreal lat = dss->location.lat.udeg * 0.000001; + qreal lon = dss->location.lon.udeg * 0.000001; if (start) { minLat = maxLat = lat; minLon = maxLon = lon; @@ -133,8 +133,8 @@ void MapWidgetHelper::reloadMapLocations() struct dive_site *ds = get_dive_site_for_dive(dive); if (!dive_site_has_gps_location(ds) || locationUuids.contains(ds->uuid)) continue; - latitude = ds->latitude.udeg * 0.000001; - longitude = ds->longitude.udeg * 0.000001; + latitude = ds->location.lat.udeg * 0.000001; + longitude = ds->location.lon.udeg * 0.000001; QGeoCoordinate dsCoord(latitude, longitude); QString name(ds->name); // don't add dive locations with the same name, unless they are @@ -164,8 +164,8 @@ void MapWidgetHelper::selectedLocationChanged(MapLocation *location) if (!dive_site_has_gps_location(ds)) continue; #ifndef SUBSURFACE_MOBILE - const qreal latitude = ds->latitude.udeg * 0.000001; - const qreal longitude = ds->longitude.udeg * 0.000001; + const qreal latitude = ds->location.lat.udeg * 0.000001; + const qreal longitude = ds->location.lon.udeg * 0.000001; QGeoCoordinate dsCoord(latitude, longitude); if (locationCoord.distanceTo(dsCoord) < m_smallCircleRadius) m_selectedDiveIds.append(idx); @@ -194,8 +194,8 @@ void MapWidgetHelper::selectVisibleLocations() struct dive_site *ds = get_dive_site_for_dive(dive); if (!dive_site_has_gps_location(ds)) continue; - const qreal latitude = ds->latitude.udeg * 0.000001; - const qreal longitude = ds->longitude.udeg * 0.000001; + const qreal latitude = ds->location.lat.udeg * 0.000001; + const qreal longitude = ds->location.lon.udeg * 0.000001; QGeoCoordinate dsCoord(latitude, longitude); QPointF point; QMetaObject::invokeMethod(m_map, "fromCoordinate", Q_RETURN_ARG(QPointF, point), @@ -247,14 +247,17 @@ void MapWidgetHelper::calculateSmallCircleRadius(QGeoCoordinate coord) m_smallCircleRadius = coord2.distanceTo(coord); } +static location_t mk_location(QGeoCoordinate coord) +{ + return create_location(coord.latitude(), coord.longitude()); +} + void MapWidgetHelper::copyToClipboardCoordinates(QGeoCoordinate coord, bool formatTraditional) { bool savep = prefs.coordinates_traditional; prefs.coordinates_traditional = formatTraditional; - - const int lat = lrint(1000000.0 * coord.latitude()); - const int lon = lrint(1000000.0 * coord.longitude()); - const char *coordinates = printGPSCoords(lat, lon); + location_t location = mk_location(coord); + const char *coordinates = printGPSCoords(&location); QApplication::clipboard()->setText(QString(coordinates), QClipboard::Clipboard); free((void *)coordinates); @@ -266,14 +269,14 @@ void MapWidgetHelper::updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeo MapLocation *loc = m_mapLocationModel->getMapLocationForUuid(uuid); if (loc) loc->setCoordinate(coord); - emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) }, - degrees_t { (int)lrint(coord.longitude() * 1000000.0) }); + location_t location = mk_location(coord); + emit coordinatesChanged(location); } -void MapWidgetHelper::updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude) +void MapWidgetHelper::updateDiveSiteCoordinates(uint32_t uuid, const location_t &location) { - const qreal latitude_r = latitude.udeg * 0.000001; - const qreal longitude_r = longitude.udeg * 0.000001; + const qreal latitude_r = location.lat.udeg * 0.000001; + const qreal longitude_r = location.lon.udeg * 0.000001; QGeoCoordinate coord(latitude_r, longitude_r); m_mapLocationModel->updateMapLocationCoordinates(uuid, coord); QMetaObject::invokeMethod(m_map, "centerOnCoordinate", Q_ARG(QVariant, QVariant::fromValue(coord))); @@ -303,8 +306,8 @@ void MapWidgetHelper::enterEditMode(quint32 uuid) coord = exists->coordinate(); } centerOnDiveSiteUUID(uuid); - emit coordinatesChanged(degrees_t { (int)lrint(coord.latitude() * 1000000.0) }, - degrees_t { (int)lrint(coord.longitude() * 1000000.0) }); + location_t location = mk_location(coord); + emit coordinatesChanged(location); emit editModeChanged(); } diff --git a/map-widget/qmlmapwidgethelper.h b/map-widget/qmlmapwidgethelper.h index 99f62ca08..e3d9ee865 100644 --- a/map-widget/qmlmapwidgethelper.h +++ b/map-widget/qmlmapwidgethelper.h @@ -36,7 +36,7 @@ public: Q_INVOKABLE void calculateSmallCircleRadius(QGeoCoordinate coord); Q_INVOKABLE void updateCurrentDiveSiteCoordinatesFromMap(quint32 uuid, QGeoCoordinate coord); Q_INVOKABLE void selectVisibleLocations(); - void updateDiveSiteCoordinates(uint32_t uuid, degrees_t latitude, degrees_t longitude); + void updateDiveSiteCoordinates(uint32_t uuid, const location_t &); void enterEditMode(uint32_t uuid); void exitEditMode(); QString pluginObject(); @@ -55,7 +55,7 @@ signals: void modelChanged(); void editModeChanged(); void selectedDivesChanged(QList<int> list); - void coordinatesChanged(degrees_t latitude, degrees_t longitude); + void coordinatesChanged(const location_t &); void pluginObjectChanged(); }; diff --git a/mobile-widgets/qmlmanager.cpp b/mobile-widgets/qmlmanager.cpp index 22431de30..c5603d434 100644 --- a/mobile-widgets/qmlmanager.cpp +++ b/mobile-widgets/qmlmanager.cpp @@ -754,14 +754,11 @@ void QMLManager::refreshDiveList() static void setupDivesite(struct dive *d, struct dive_site *ds, double lat, double lon, const char *locationtext) { + location_t location = create_location(lat, lon); if (ds) { - ds->latitude.udeg = lrint(lat * 1000000); - ds->longitude.udeg = lrint(lon * 1000000); + ds->location = location; } else { - degrees_t latData, lonData; - latData.udeg = lrint(lat * 1000000); - lonData.udeg = lrint(lon * 1000000); - d->dive_site_uuid = create_dive_site_with_gps(locationtext, latData, lonData, d->when); + d->dive_site_uuid = create_dive_site_with_gps(locationtext, &location, d->when); } } @@ -1481,7 +1478,7 @@ QString QMLManager::getGpsFromSiteName(const QString& siteName) uuid = get_dive_site_uuid_by_name(qPrintable(siteName), NULL); if (uuid) { ds = get_dive_site_by_uuid(uuid); - return QString(printGPSCoords(ds->latitude.udeg, ds->longitude.udeg)); + return QString(printGPSCoords(&ds->location)); } return ""; } diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp index ca803f1cf..5949628b5 100644 --- a/qt-models/divelocationmodel.cpp +++ b/qt-models/divelocationmodel.cpp @@ -43,8 +43,8 @@ QVariant LocationInformationModel::getDiveSiteData(const struct dive_site *ds, i switch(column) { case UUID: return ds->uuid; case NAME: return ds->name; - case LATITUDE: return ds->latitude.udeg; - case LONGITUDE: return ds->longitude.udeg; + case LATITUDE: return ds->location.lat.udeg; + case LONGITUDE: return ds->location.lon.udeg; case COORDS: return "TODO"; case DESCRIPTION: return ds->description; case NOTES: return ds->name; @@ -123,28 +123,25 @@ bool GPSLocationInformationModel::filterAcceptsRow(int sourceRow, const QModelIn return false; struct dive_site *ds = get_dive_site_by_uuid(uuid); - return ds && ds->latitude.udeg == latitude.udeg && ds->longitude.udeg == longitude.udeg; + return ds && same_location(&ds->location, &location); } GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent), ignoreUuid(0), - latitude({ 0 }), - longitude({ 0 }) + location({{0},{0}}) { setSourceModel(LocationInformationModel::instance()); } -void GPSLocationInformationModel::set(uint32_t ignoreUuidIn, degrees_t latitudeIn, degrees_t longitudeIn) +void GPSLocationInformationModel::set(uint32_t ignoreUuidIn, const location_t &locationIn) { ignoreUuid = ignoreUuidIn; - latitude = latitudeIn; - longitude = longitudeIn; + location = locationIn; invalidate(); } -void GPSLocationInformationModel::setCoordinates(degrees_t latitudeIn, degrees_t longitudeIn) +void GPSLocationInformationModel::setCoordinates(const location_t &locationIn) { - latitude = latitudeIn; - longitude = longitudeIn; + location = locationIn; invalidate(); } diff --git a/qt-models/divelocationmodel.h b/qt-models/divelocationmodel.h index fe78854b9..14077609c 100644 --- a/qt-models/divelocationmodel.h +++ b/qt-models/divelocationmodel.h @@ -38,12 +38,12 @@ class GPSLocationInformationModel : public QSortFilterProxyModel { Q_OBJECT private: uint32_t ignoreUuid; - degrees_t latitude, longitude; + location_t location; bool filterAcceptsRow(int sourceRow, const QModelIndex &source_parent) const override; public: GPSLocationInformationModel(QObject *parent = nullptr); - void set(uint32_t ignoreUuid, degrees_t latitude, degrees_t longitude); - void setCoordinates(degrees_t latitude, degrees_t longitude); + void set(uint32_t ignoreUuid, const location_t &); + void setCoordinates(const location_t &); }; class GeoReferencingOptionsModel : public QStringListModel { diff --git a/qt-models/gpslistmodel.cpp b/qt-models/gpslistmodel.cpp index 4a4a8feac..8d874d67b 100644 --- a/qt-models/gpslistmodel.cpp +++ b/qt-models/gpslistmodel.cpp @@ -46,9 +46,9 @@ QVariant GpsListModel::data(const QModelIndex &index, int role) const else if (role == GpsNameRole) return gt.name; else if (role == GpsLatitudeRole) - return QString::number(gt.latitude.udeg / 1000000.0, 'f', 6); + return QString::number(gt.location.lat.udeg / 1000000.0, 'f', 6); else if (role == GpsLongitudeRole) - return QString::number(gt.longitude.udeg / 1000000.0, 'f', 6); + return QString::number(gt.location.lon.udeg / 1000000.0, 'f', 6); return QVariant(); } diff --git a/smtk-import/smartrak.c b/smtk-import/smartrak.c index 20f0d617b..fce89dbae 100644 --- a/smtk-import/smartrak.c +++ b/smtk-import/smartrak.c @@ -323,7 +323,7 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin int i; uint32_t d; struct dive_site *ds; - degrees_t lat, lon; + location_t loc; char *str = NULL, *loc_idx = NULL, *site = NULL, *notes = NULL; const char *site_fields[] = {QT_TRANSLATE_NOOP("gettextFromC", "Altitude"), QT_TRANSLATE_NOOP("gettextFromC", "Depth"), QT_TRANSLATE_NOOP("gettextFromC", "Notes")}; @@ -337,8 +337,7 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin mdb_fetch_row(table); loc_idx = copy_string(col[2]->bind_ptr); site = copy_string(col[1]->bind_ptr); - lat.udeg = lrint(strtod(col[6]->bind_ptr, NULL) * 1000000); - lon.udeg = lrint(strtod(col[7]->bind_ptr, NULL) * 1000000); + loc = create_location(strtod(col[6]->bind_ptr, NULL), strtod(col[7]->bind_ptr, NULL)); for (i = 8; i < 11; i++) { switch (i) { @@ -376,10 +375,10 @@ static void smtk_build_location(MdbHandle *mdb, char *idx, timestamp_t when, uin *location = get_dive_site_uuid_by_name(str, NULL); if (*location == 0) { - if (lat.udeg == 0 && lon.udeg == 0) + if (!has_location(&loc)) *location = create_dive_site(str, when); else - *location = create_dive_site_with_gps(str, lat, lon, when); + *location = create_dive_site_with_gps(str, &loc, when); } smtk_free(bound_values, table->num_cols); diff --git a/tests/testpicture.cpp b/tests/testpicture.cpp index 2209e479f..695c965b0 100644 --- a/tests/testpicture.cpp +++ b/tests/testpicture.cpp @@ -40,8 +40,8 @@ void TestPicture::addPicture() // 1st appearing at time 21:01 // 2nd appearing at time 22:01 QVERIFY(pic1->offset.seconds == 1261); - QVERIFY(pic1->latitude.udeg == 47934500); - QVERIFY(pic1->longitude.udeg == 11334500); + QVERIFY(pic1->location.lat.udeg == 47934500); + QVERIFY(pic1->location.lon.udeg == 11334500); QVERIFY(pic2->offset.seconds == 1321); learnPictureFilename(pic1->filename, PIC1_NAME); |