-
Notifications
You must be signed in to change notification settings - Fork 23
1342 make geographic location available to all of MEmilio #1346
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
kilianvolmer
merged 46 commits into
main
from
1342-Make-GeographicLocation-available-to-all-of-MEmilio
Oct 29, 2025
Merged
Changes from all commits
Commits
Show all changes
46 commits
Select commit
Hold shift + click to select a range
2af6d2c
CHG: Move geographical location to location file in memilio/geography
kilianvolmer 02d6a37
CHG: multiplications instead of divisions
kilianvolmer abdb2f9
CHG: Add tests for GeographicalLocation
kilianvolmer 7888062
CHG: Add data_types entry for GeographicLocation
kilianvolmer 2905b84
NEW: add r-Tree to mio::geo
kilianvolmer ca6646f
CHG: unnecessary changes for CI
kilianvolmer ad9afc5
CHG: Make latitude and longitude privat
kilianvolmer c5edf45
CHG: use ifndefs
kilianvolmer 3ce4001
CHG: try fix CI as CI compiler does not support our c++ language stan…
kilianvolmer 5a213de
CHG: Try fix CI
kilianvolmer 91b066d
CHG: switch names of Location and geography tests
kilianvolmer 07aeafe
CHG: update inlcludes and use numbers constants
kilianvolmer 298e62e
CHG: Update includes
kilianvolmer 38e6d4c
CHG: explicitly denote pi for memilio.simulation to work
kilianvolmer 9de2584
CHG: add inrange query
kilianvolmer cdbbec5
CHG: reserve space for return indices
kilianvolmer 09f9520
Merge branch 'main' into 1342-Make-GeographicLocation-available-to-al…
kilianvolmer 1bd9696
Apply suggestions from code review
kilianvolmer 7acba95
CHG: Include feedback from code review
kilianvolmer 55f675d
CHG: Apply demands of code review
kilianvolmer 24fcf00
CHG: Improve doxygen
kilianvolmer 4c675c5
CHG: Update rtree tests
kilianvolmer b1056e2
Merge branch 'main' into 1342-Make-GeographicLocation-available-to-al…
kilianvolmer 1686d75
Appply changes from code review
kilianvolmer 7cc8b37
CHG: use boring numbers in tests
kilianvolmer 94ee62c
CHG: improve test comments
kilianvolmer 3215f65
CHG: Apply suggestions from code review
kilianvolmer ddc021f
CHG: Add new headers to CMakeLists
kilianvolmer 0220670
Apply suggestions from code review
kilianvolmer 5e3e274
Merge branch '1342-Make-GeographicLocation-available-to-all-of-MEmili…
kilianvolmer c3d98c9
Merge branch 'main' into 1342-Make-GeographicLocation-available-to-al…
kilianvolmer 9592d9f
CHG: Use ScalarTypes
kilianvolmer 267ca7e
CHG: Apply suggestions from code review
kilianvolmer 99df960
NEW: Add mio::geo::Distance
kilianvolmer 66dbcc2
FIX: use scalar type internally, make constructors constexpr
kilianvolmer 5bb6a6c
CHG: Use distance everywhere
kilianvolmer 137c5df
CHG: rename inrange to in_range
kilianvolmer 30e52a2
Remove iterator constructor based on Review comments
kilianvolmer 914ba91
Apply suggestions from code review
kilianvolmer 6417d4e
CHG: Add some clarifying comments.
kilianvolmer 6ce3b08
Merge branch '1342-Make-GeographicLocation-available-to-all-of-MEmili…
kilianvolmer a2d040e
CHG: Add back_inserter_second_element to CMakeLists
kilianvolmer 351b2b0
CHG: Add another clarifying comment
kilianvolmer 2bcdcf0
Apply suggestions from code review
kilianvolmer 9f0d916
CHG: Add distance to data_types
kilianvolmer 89f0cc4
FIX: corrected docstrings
kilianvolmer File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,153 @@ | ||
| /* | ||
| * Copyright (C) 2020-2025 MEmilio | ||
| * | ||
| * Authors: Kilian Volmer, Rene Schmiedling | ||
| * | ||
| * Contact: Martin J. Kuehn <[email protected]> | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| #ifndef MIO_DISTANCE_H | ||
| #define MIO_DISTANCE_H | ||
|
|
||
| #include "memilio/config.h" | ||
| #include "memilio/io/default_serialize.h" | ||
|
|
||
| namespace mio | ||
| { | ||
|
|
||
| namespace geo | ||
| { | ||
|
|
||
| /** | ||
| * @brief Represents a distance. | ||
| * Internally, all distances are stored in meters. | ||
| */ | ||
| class Distance | ||
| { | ||
| public: | ||
| /** | ||
| * @brief Default ctor, unitinialized. | ||
| */ | ||
| Distance() = default; | ||
| /** | ||
| * @brief Creates a Distance from a specified distance in meters. | ||
| * @param[in] meters The distance in meters. | ||
| */ | ||
| explicit constexpr Distance(ScalarType meters) | ||
| : m_meters(meters) | ||
| { | ||
| } | ||
|
|
||
| /** | ||
| * @brief return distance in kilometers. | ||
| */ | ||
| ScalarType kilometers() const | ||
| { | ||
| return ScalarType(m_meters) / 1000; | ||
| } | ||
|
|
||
| /** | ||
| * @brief return distance in meters. | ||
| */ | ||
| ScalarType meters() const | ||
| { | ||
| return m_meters; | ||
| } | ||
|
|
||
| /** | ||
| * @name Comparison operators. | ||
| * @{ | ||
| */ | ||
| bool operator==(const Distance& other) const | ||
| { | ||
| return m_meters == other.m_meters; | ||
| } | ||
| bool operator!=(const Distance& other) const | ||
| { | ||
| return !(*this == other); | ||
| } | ||
| bool operator<(const Distance& other) const | ||
| { | ||
| return m_meters < other.m_meters; | ||
| } | ||
| bool operator<=(const Distance& other) const | ||
| { | ||
| return m_meters <= other.m_meters; | ||
| } | ||
| bool operator>(const Distance& other) const | ||
| { | ||
| return m_meters > other.m_meters; | ||
| } | ||
| bool operator>=(const Distance& other) const | ||
| { | ||
| return m_meters >= other.m_meters; | ||
| } | ||
| /**@}*/ | ||
|
|
||
| /** | ||
| * @brief Add or subtract a Distance. | ||
| * @{ | ||
| */ | ||
| Distance operator+(const Distance& m) const | ||
| { | ||
| return Distance{m_meters + m.meters()}; | ||
| } | ||
| Distance& operator+=(const Distance& m) | ||
| { | ||
| m_meters += m.meters(); | ||
| return *this; | ||
| } | ||
| Distance operator-(const Distance& m) const | ||
| { | ||
| return Distance{m_meters - m.meters()}; | ||
| } | ||
| Distance& operator-=(const Distance& m) | ||
| { | ||
| m_meters -= m.meters(); | ||
| return *this; | ||
| } | ||
| /**@}*/ | ||
|
|
||
| /// This method is used by the default serialization feature. | ||
| auto default_serialize() | ||
| { | ||
| return Members("Distance").add("meters", m_meters); | ||
| } | ||
|
|
||
| private: | ||
| ScalarType m_meters; ///< The distance in meters. | ||
| }; | ||
|
|
||
| /** | ||
| * @brief Create a Distance of a specified number of meters. | ||
| * @param[in] meters distance in meters. | ||
| */ | ||
| constexpr inline Distance meters(ScalarType meters) | ||
| { | ||
| return Distance(meters); | ||
| } | ||
|
|
||
| /** | ||
| * @brief Create a Distance of a specified number of kilometers. | ||
| * @param[in] kilometers distance in kilometers. | ||
| */ | ||
| constexpr inline Distance kilometers(ScalarType kilometers) | ||
| { | ||
| return Distance(kilometers * 1000); | ||
| } | ||
|
|
||
| } // namespace geo | ||
| } // namespace mio | ||
|
|
||
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,195 @@ | ||
| /* | ||
| * Copyright (C) 2020-2025 MEmilio | ||
| * | ||
| * Authors: Kilian Volmer, Sascha Korf, Carlotta Gerstein, Daniel Abele, Elisabeth Kluth, Khoa Nguyen, David Kerkmann | ||
| * | ||
| * Contact: Martin J. Kuehn <[email protected]> | ||
| * | ||
| * Licensed under the Apache License, Version 2.0 (the "License"); | ||
| * you may not use this file except in compliance with the License. | ||
| * You may obtain a copy of the License at | ||
| * | ||
| * http://www.apache.org/licenses/LICENSE-2.0 | ||
| * | ||
| * Unless required by applicable law or agreed to in writing, software | ||
| * distributed under the License is distributed on an "AS IS" BASIS, | ||
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
| * See the License for the specific language governing permissions and | ||
| * limitations under the License. | ||
| */ | ||
| #ifndef MIO_GEOGRAPHY_LOCATIONS_H | ||
|
kilianvolmer marked this conversation as resolved.
|
||
| #define MIO_GEOGRAPHY_LOCATIONS_H | ||
|
|
||
| #include "distance.h" | ||
| #include "memilio/io/default_serialize.h" | ||
| #include "memilio/geography/distance.h" | ||
| #include "memilio/config.h" | ||
| #include "memilio/utils/logging.h" | ||
| #include <cassert> | ||
| #include <cmath> | ||
| #include <numbers> | ||
| namespace mio | ||
| { | ||
| namespace geo | ||
| { | ||
| /** | ||
| * @brief Class representing a geographical location on the Earth's surface. | ||
| * | ||
| * Provides latitude and longitude in degrees and a method to calculate the distance to another location. | ||
| */ | ||
| class GeographicalLocation | ||
| { | ||
|
|
||
| public: | ||
| /** | ||
| * @brief Construct a new Geographical Location object. | ||
| * | ||
| * @param lat Latitude in degrees. | ||
| * @param lon Longitude in degrees. | ||
| */ | ||
| GeographicalLocation(ScalarType lat, ScalarType lon) | ||
| : m_latitude(lat) | ||
| , m_longitude(lon) | ||
| { | ||
| check_input(); | ||
| } | ||
| /** | ||
| * @brief Construct a new Geographical Location object. | ||
| * | ||
| * @param coordinates Pair of latitude and longitude in degrees as ScalarTypes. | ||
| */ | ||
| GeographicalLocation(std::pair<ScalarType, ScalarType> coordinates) | ||
| : m_latitude(coordinates.first) | ||
| , m_longitude(coordinates.second) | ||
| { | ||
| check_input(); | ||
|
kilianvolmer marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** | ||
| * @brief Construct a new Geographical Location object using the default constructor to keep compatibility with ABM code. | ||
| * | ||
| */ | ||
| GeographicalLocation() = default; | ||
|
|
||
| /** | ||
| * @brief Compare two GeographicalLocation%s for equality | ||
| */ | ||
| bool operator==(const GeographicalLocation& other) const | ||
| { | ||
| return (m_latitude == other.m_latitude && m_longitude == other.m_longitude); | ||
|
kilianvolmer marked this conversation as resolved.
|
||
| } | ||
|
|
||
| /** | ||
| * @brief Compare two GeographicalLocation%s for inequality | ||
| */ | ||
| bool operator!=(const GeographicalLocation& other) const | ||
| { | ||
| return !(*this == other); | ||
| } | ||
|
|
||
|
kilianvolmer marked this conversation as resolved.
|
||
| /** | ||
| * @brief Check that this location is within a (small) distance of another. | ||
| * @param[in] other Any location. | ||
| * @param[in] tol The Absolute tolerance for considering two locations close. | ||
| */ | ||
| bool is_close(const GeographicalLocation& other, | ||
| Distance tol = Distance(10 * Limits<ScalarType>::zero_tolerance())) const | ||
| { | ||
| return distance(other) < tol; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Default serialize the GeographicalLocation object. | ||
| * | ||
| * This method is used by the default serialization feature. | ||
| */ | ||
| auto default_serialize() | ||
| { | ||
| return Members("GeographicalLocation").add("latitude", m_latitude).add("longitude", m_longitude); | ||
| } | ||
|
|
||
| /* | ||
| * @brief Calculate the distance between two GeographicalLocation%s. | ||
| * @param other The other GeographicalLocation. | ||
| * @return The distance between the two locations as @ref mio::geo::Distance . | ||
| * | ||
| * Uses the haversine formula (https://en.wikipedia.org/wiki/Haversine_formula) to calculate the distance between | ||
| * two geographical locations. Uses an earth radius of 6371 km (https://en.wikipedia.org/wiki/Earth_radius). | ||
| * The math functions use radians, whereas coordinates are given in degrees. | ||
| */ | ||
| Distance distance(const GeographicalLocation& other) const | ||
| { | ||
| const ScalarType delta_latitude = (m_latitude - other.m_latitude) * radians; | ||
| const ScalarType delta_longitude = (m_longitude - other.m_longitude) * radians; | ||
| const ScalarType sin_delta_latitude_half = sin(delta_latitude * 0.5); | ||
| const ScalarType sin_delta_longitude_half = sin(delta_longitude * 0.5); | ||
| const ScalarType first_part = sin_delta_latitude_half * sin_delta_latitude_half; | ||
| const ScalarType second_part = cos(m_latitude * radians) * cos(other.m_latitude * radians) * | ||
| sin_delta_longitude_half * sin_delta_longitude_half; | ||
| const ScalarType distance = 2.0 * earth_radius.kilometers() * asin(sqrt(first_part + second_part)); | ||
| return kilometers(distance); | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get the latitude object | ||
| * | ||
| * @return ScalarType latitude in degrees | ||
| */ | ||
| ScalarType get_latitude() const | ||
| { | ||
| return m_latitude; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Get the longitude object | ||
| * | ||
| * @return ScalarType longitude in degrees | ||
| */ | ||
| ScalarType get_longitude() const | ||
| { | ||
| return m_longitude; | ||
| } | ||
|
|
||
| /** | ||
| * @brief Set the latitude object | ||
| * | ||
| * @param lat Latitude in degrees. | ||
| */ | ||
| void set_latitude(ScalarType lat) | ||
| { | ||
| m_latitude = lat; | ||
| check_input(); | ||
| } | ||
|
|
||
| /** | ||
| * @brief Set the longitude object | ||
| * | ||
| * @param lon Longitude in degrees. | ||
| */ | ||
| void set_longitude(ScalarType lon) | ||
| { | ||
| m_longitude = lon; | ||
| check_input(); | ||
| } | ||
|
|
||
| private: | ||
| /** | ||
| * @brief Assert that the latitude and longitude are within valid ranges. | ||
| */ | ||
| void check_input() const | ||
| { | ||
| assert(m_latitude <= 90. && m_latitude >= -90. && "Latitude must be in [-90, 90]"); | ||
| assert(m_longitude <= 180. && m_longitude >= -180. && "Longitude must be in [-180, 180]"); | ||
| } | ||
|
|
||
| ScalarType m_latitude; | ||
| ScalarType m_longitude; | ||
| constexpr static mio::geo::Distance earth_radius = mio::geo::kilometers(6371.); | ||
| constexpr static ScalarType radians = std::numbers::pi / 180.0; | ||
| }; | ||
|
|
||
| } // namespace geo | ||
|
|
||
| } // namespace mio | ||
|
|
||
| #endif // MIO_GEOGRAPHY_LOCATIONS_H | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.