Browse Source

define the geographic library

Sven Czarnian 3 years ago
parent
commit
969f448bf4
2 changed files with 180 additions and 0 deletions
  1. 91 0
      include/aman/types/GeoCoordinate.h
  2. 89 0
      src/types/GeoCoordinate.cpp

+ 91 - 0
include/aman/types/GeoCoordinate.h

@@ -0,0 +1,91 @@
+/*
+ * @brief Defines a geo-referenced coordinate
+ * @file types/GeoCoordinate.h
+ * @author Sven Czarnian <devel@svcz.de>
+ * @copyright Copyright 2020-2021 Sven Czarnian
+ * @license This project is published under the GNU General Public License v3 (GPLv3)
+ */
+
+#pragma once
+
+#include <string>
+
+#include <aman/types/Quantity.hpp>
+
+namespace aman {
+    /**
+     * @brief Describes a geo-reference coordinate with longitude and latitude
+     * @ingroup types
+     */
+    class GeoCoordinate {
+    private:
+        Angle m_longitude;
+        Angle m_latitude;
+
+    public:
+        /**
+         * @brief Creates a coordinate with zero-values
+         */
+        GeoCoordinate() noexcept;
+        /**
+         * @brief Creates a coordinate with initial values
+         * @param[in] longitude The initial longitudinal value
+         * @param[in] latitude The initial latitudinal value
+         */
+        GeoCoordinate(const Angle& longitude, const Angle& latitude) noexcept;
+
+        /**
+         * @brief Checks if two positions are equal
+         * @param[in] other The other coordinate instance
+         * @return True if this instance is equal to the other instance, else false
+         */
+        bool operator==(const GeoCoordinate& other) const;
+        /**
+         * @brief Checks if two positions are not equal
+         * @param[in] other The other coordinate instance
+         * @return True if this instance is not equal to the other instance, else false
+         */
+        bool operator!=(const GeoCoordinate& other) const;
+
+        /**
+         * @brief Returns the longitudinal component
+         * @return The constant reference to the longitudinal component
+         */
+        const Angle& longitude() const noexcept;
+        /**
+         * @brief Returns the longitudinal component
+         * @return The reference to the longitudinal component
+         */
+        Angle& longitude() noexcept;
+        /**
+         * @brief Returns the latitudinal component
+         * @return The constant reference to the latitudinal component
+         */
+        const Angle& latitude() const noexcept;
+        /**
+         * @brief Returns the latitudinal component
+         * @return The reference to the latitudinal component
+         */
+        Angle& latitude() noexcept;
+        /**
+         * @brief Calculates the coordinate from this coordinate and based on a heading and a distance
+         * The function uses the haversine-formular and calculates the coordinate based on the great circle distance
+         * @param[in] heading The heading from this coordinate to the next one
+         * @param[in] distance The distance from this coordinate to the next one
+         * @return The resulting coordinate which is based on the heading and the distance
+         */
+        GeoCoordinate projection(const Angle& heading, const Length& distance) const;
+        /**
+         * @brief Calculates the great circle distance between this coordinate and the other
+         * @param[in] other The other coordinate
+         * @return The great circle distance between this coordinate and the other
+         */
+        Length distanceTo(const GeoCoordinate& other) const;
+        /**
+         * @brief Calculates the bearing between this coordinate and the other
+         * @param[in] other The other coordinate
+         * @return The bearing between this coordinate and the other
+         */
+        Angle bearingTo(const GeoCoordinate& other) const;
+    };
+}

+ 89 - 0
src/types/GeoCoordinate.cpp

@@ -0,0 +1,89 @@
+/*
+ * Author:
+ *   Sven Czarnian <devel@svcz.de>
+ * Brief:
+ *   Implements the coordinate to abstract global coordinates
+ * Copyright:
+ *   2020-2021 Sven Czarnian
+ * License:
+ *   GNU General Public License v3 (GPLv3)
+ */
+
+#include <algorithm>
+
+#include <GeographicLib/Geodesic.hpp>
+#include <gsl/gsl>
+
+#include <aman/helper/Math.h>
+#include <aman/helper/String.h>
+#include <aman/types/GeoCoordinate.h>
+
+using namespace aman;
+
+static constexpr float MinutesToHours = 60.0f;
+static constexpr float SecondsToHours = 3600.0f;
+static constexpr float MillisecondsToHours = 3600000.0f;
+static constexpr float MaxAngle = 360.0f;
+
+GeoCoordinate::GeoCoordinate() noexcept :
+        m_longitude(0.0f),
+        m_latitude(0.0f) { }
+
+GeoCoordinate::GeoCoordinate(const Angle& longitude, const Angle& latitude) noexcept :
+        m_longitude(longitude),
+        m_latitude(latitude) { }
+
+bool GeoCoordinate::operator==(const GeoCoordinate& other) const {
+    return this->m_longitude == other.m_longitude && this->m_latitude == other.m_latitude;
+}
+
+bool GeoCoordinate::operator!=(const GeoCoordinate& other) const {
+    return false == this->operator==(other);
+}
+
+const Angle& GeoCoordinate::longitude() const noexcept {
+    return this->m_longitude;
+}
+
+Angle& GeoCoordinate::longitude() noexcept {
+    return this->m_longitude;
+}
+
+const Angle& GeoCoordinate::latitude() const noexcept {
+    return this->m_latitude;
+}
+
+Angle& GeoCoordinate::latitude() noexcept {
+    return this->m_latitude;
+}
+
+GeoCoordinate GeoCoordinate::projection(const Angle& heading, const Length& distance) const {
+    float lat = 0.0f, lon = 0.0f;
+    GeographicLib::Geodesic::WGS84().Direct(this->latitude().convert(degree), this->longitude().convert(degree),
+                                            heading.convert(degree), distance.convert(metre), lat, lon);
+    return GeoCoordinate(lon * degree, lat * degree);
+}
+
+Length GeoCoordinate::distanceTo(const GeoCoordinate& other) const {
+    float distance = 0.0f;
+    GeographicLib::Geodesic::WGS84().Inverse(this->latitude().convert(degree), this->longitude().convert(degree),
+                                             other.latitude().convert(degree), other.longitude().convert(degree),
+                                             distance);
+    return distance * metre;
+}
+
+Angle GeoCoordinate::bearingTo(const GeoCoordinate& other) const {
+    float azimuth0 = 0.0f, azimuth1 = 0.0f;
+    GeographicLib::Geodesic::WGS84().Inverse(this->latitude().convert(degree), this->longitude().convert(degree),
+                                             other.latitude().convert(degree), other.longitude().convert(degree),
+                                             azimuth0, azimuth1);
+
+    std::ignore = azimuth1;
+
+    while (0.0f > azimuth0)
+        azimuth0 += MaxAngle;
+    while (MaxAngle < azimuth0)
+        azimuth0 += MaxAngle;
+
+    return azimuth0 * degree;
+}