diff --git a/core/divesite.cpp b/core/divesite.cpp index 20ca1adea..ee76e58b1 100644 --- a/core/divesite.cpp +++ b/core/divesite.cpp @@ -50,32 +50,14 @@ dive_site *dive_site_table::get_by_gps_and_name(const std::string &name, const l ds->name == name; }); } -// Calculate the distance in meters between two coordinates. -unsigned int get_distance(const location_t *loc1, const location_t *loc2) -{ - double lat1_r = udeg_to_radians(loc1->lat.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(lat1_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2); - if (a < 0.0) a = 0.0; - if (a > 1.0) a = 1.0; - double c = 2 * atan2(sqrt(a), sqrt(1.0 - a)); - - // Earth radius in metres - return lrint(6371000 * c); -} - /* find the closest one, no more than distance meters away - if more than one at same distance, pick the first */ -dive_site *dive_site_table::get_by_gps_proximity(const location_t *loc, int distance) const +dive_site *dive_site_table::get_by_gps_proximity(location_t loc, int distance) const { struct dive_site *res = nullptr; unsigned int cur_distance, min_distance = distance; for (const auto &ds: *this) { if (dive_site_has_gps_location(ds.get()) && - (cur_distance = get_distance(&ds->location, loc)) < min_distance) { + (cur_distance = get_distance(ds->location, loc)) < min_distance) { min_distance = cur_distance; res = ds.get(); } diff --git a/core/divesite.h b/core/divesite.h index 3814a3508..d4c21894e 100644 --- a/core/divesite.h +++ b/core/divesite.h @@ -51,11 +51,10 @@ public: dive_site *get_by_name(const std::string &name) const; dive_site *get_by_gps(const location_t *) const; dive_site *get_by_gps_and_name(const std::string &name, const location_t *) const; - dive_site *get_by_gps_proximity(const location_t *, int distance) const; + dive_site *get_by_gps_proximity(location_t, int distance) const; void purge_empty(); }; -unsigned int get_distance(const location_t *loc1, const location_t *loc2); struct dive_site *unregister_dive_from_dive_site(struct dive *d); struct dive_site *get_same_dive_site(const struct dive_site &); // accesses global dive list std::string constructLocationTags(const taxonomy_data &taxonomy, bool for_maintab); diff --git a/core/parse-xml.cpp b/core/parse-xml.cpp index a00da8367..6cbb88350 100644 --- a/core/parse-xml.cpp +++ b/core/parse-xml.cpp @@ -1197,7 +1197,7 @@ static void gps_in_dive(const char *buffer, struct dive *dive, struct parser_sta parse_location(buffer, &location); if (!ds) { // check if we have a dive site within 20 meters of that gps fix - ds = state->log->sites->get_by_gps_proximity(&location, 20); + ds = state->log->sites->get_by_gps_proximity(location, 20); if (ds) { // found a site nearby; in case it turns out this one had a different name let's diff --git a/core/units.cpp b/core/units.cpp index a589c3ca4..64c244483 100644 --- a/core/units.cpp +++ b/core/units.cpp @@ -180,3 +180,22 @@ const struct units *get_units() { return &prefs.units; } + +// Calculate the distance in meters between two coordinates. +unsigned int get_distance(location_t loc1, location_t loc2) +{ + double lat1_r = udeg_to_radians(loc1.lat.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(lat1_r) * cos(lat2_r) * sin(lon_d_r/2) * sin(lon_d_r/2); + if (a < 0.0) a = 0.0; + if (a > 1.0) a = 1.0; + double c = 2 * atan2(sqrt(a), sqrt(1.0 - a)); + + // Earth radius in metres + return lrint(6371000 * c); +} + diff --git a/core/units.h b/core/units.h index 1b176f455..ec681b996 100644 --- a/core/units.h +++ b/core/units.h @@ -132,6 +132,7 @@ typedef struct pos { } location_t; extern void parse_location(const char *, location_t *); +extern unsigned int get_distance(location_t loc1, location_t loc2); static inline bool has_location(const location_t *loc) { diff --git a/desktop-widgets/locationinformation.cpp b/desktop-widgets/locationinformation.cpp index 473baba74..93ea7e950 100644 --- a/desktop-widgets/locationinformation.cpp +++ b/desktop-widgets/locationinformation.cpp @@ -390,7 +390,7 @@ bool DiveLocationFilterProxyModel::lessThan(const QModelIndex &source_left, cons // The dive sites are -2 because of the first two items. auto loc1 = (*divelog.sites)[source_left.row() - 2]->location; auto loc2 = (*divelog.sites)[source_right.row() - 2]->location; - return get_distance(&loc1, ¤tLocation) < get_distance(&loc2, ¤tLocation); + return get_distance(loc1, currentLocation) < get_distance(loc2, currentLocation); } return source_left.data().toString().compare(source_right.data().toString(), Qt::CaseInsensitive) < 0; } diff --git a/desktop-widgets/modeldelegates.cpp b/desktop-widgets/modeldelegates.cpp index 60a37c5be..0346a9a3e 100644 --- a/desktop-widgets/modeldelegates.cpp +++ b/desktop-widgets/modeldelegates.cpp @@ -478,7 +478,7 @@ void LocationFilterDelegate::paint(QPainter *painter, const QStyleOptionViewItem if (ds->location == currentLocation) { bottomText += tr(" (same GPS fix)"); } else { - int distanceMeters = get_distance(&ds->location, ¤tLocation); + int distanceMeters = get_distance(ds->location, currentLocation); QString distance = distance_string(distanceMeters); size_t nr = ds->nr_of_dives(); bottomText += tr(" (~%1 away").arg(distance); diff --git a/qt-models/divelocationmodel.cpp b/qt-models/divelocationmodel.cpp index 712e15e37..45a528fab 100644 --- a/qt-models/divelocationmodel.cpp +++ b/qt-models/divelocationmodel.cpp @@ -298,7 +298,7 @@ bool GPSLocationInformationModel::filterAcceptsRow(int sourceRow, const QModelIn return false; return distance <= 0 ? ds->location == location - : (int64_t)get_distance(&ds->location, &location) * 1000 <= distance; // We need 64 bit to represent distances in mm + : (int64_t)get_distance(ds->location, location) * 1000 <= distance; // We need 64 bit to represent distances in mm } GPSLocationInformationModel::GPSLocationInformationModel(QObject *parent) : QSortFilterProxyModel(parent), diff --git a/qt-models/divesiteimportmodel.cpp b/qt-models/divesiteimportmodel.cpp index 112b27d7d..731f6bf47 100644 --- a/qt-models/divesiteimportmodel.cpp +++ b/qt-models/divesiteimportmodel.cpp @@ -67,7 +67,7 @@ QVariant DivesiteImportedModel::data(const QModelIndex &index, int role) const case NEAREST: { // 40075000 is circumference of the earth in meters struct dive_site *nearest_ds = - divelog.sites->get_by_gps_proximity(&ds->location, 40075000); + divelog.sites->get_by_gps_proximity(ds->location, 40075000); if (nearest_ds) return QString::fromStdString(nearest_ds->name); else @@ -76,10 +76,9 @@ QVariant DivesiteImportedModel::data(const QModelIndex &index, int role) const case DISTANCE: { unsigned int distance = 0; struct dive_site *nearest_ds = - divelog.sites->get_by_gps_proximity(&ds->location, 40075000); + divelog.sites->get_by_gps_proximity(ds->location, 40075000); if (nearest_ds) - distance = get_distance(&ds->location, - &nearest_ds->location); + distance = get_distance(ds->location, nearest_ds->location); return distance_string(distance); } case SELECTED: