// The MIT License (MIT) // // Copyright (c) 2018 Mateusz Pusz // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. #pragma once #include #include #include #include #include // IWYU pragma: begin_exports #include // IWYU pragma: end_exports namespace geographic { template struct coordinate { using value_type = Rep; constexpr explicit coordinate(value_type v) : value_(v) {} constexpr value_type value() const { return value_; } auto operator<=>(const coordinate&) const = default; private: value_type value_; }; struct latitude : coordinate { using coordinate::coordinate; }; struct longitude : coordinate { using coordinate::coordinate; }; template std::basic_ostream& operator<<(std::basic_ostream& os, const latitude& lat) { if (lat.value() > 0) return os << "N" << lat.value(); else return os << "S" << -lat.value(); } template std::basic_ostream& operator<<(std::basic_ostream& os, const longitude& lon) { if (lon.value() > 0) return os << "E" << lon.value(); else return os << "W" << -lon.value(); } inline namespace literals { constexpr auto operator"" _N(unsigned long long v) { return latitude(static_cast(v)); } constexpr auto operator"" _N(long double v) { return latitude(static_cast(v)); } constexpr auto operator"" _S(unsigned long long v) { return latitude(-static_cast(v)); } constexpr auto operator"" _S(long double v) { return latitude(-static_cast(v)); } constexpr auto operator"" _E(unsigned long long v) { return longitude(static_cast(v)); } constexpr auto operator"" _E(long double v) { return longitude(static_cast(v)); } constexpr auto operator"" _W(unsigned long long v) { return longitude(-static_cast(v)); } constexpr auto operator"" _W(long double v) { return longitude(-static_cast(v)); } } // namespace literals } // namespace geographic template<> class std::numeric_limits : public numeric_limits { static constexpr auto min() noexcept { return geographic::latitude(-90); } static constexpr auto lowest() noexcept { return geographic::latitude(-90); } static constexpr auto max() noexcept { return geographic::latitude(90); } }; template<> class std::numeric_limits : public numeric_limits { static constexpr auto min() noexcept { return geographic::longitude(-180); } static constexpr auto lowest() noexcept { return geographic::longitude(-180); } static constexpr auto max() noexcept { return geographic::longitude(180); } }; template<> struct STD_FMT::formatter : formatter { template auto format(geographic::latitude lat, FormatContext& ctx) { STD_FMT::vformat_to(ctx.out(), lat.value() > 0 ? "N" : "S", {}); return formatter::format(lat.value() > 0 ? lat.value() : -lat.value(), ctx); } }; template<> struct STD_FMT::formatter : formatter { template auto format(geographic::longitude lon, FormatContext& ctx) { STD_FMT::vformat_to(ctx.out(), lon.value() > 0 ? "E" : "W", {}); return formatter::format(lon.value() > 0 ? lon.value() : -lon.value(), ctx); } }; namespace geographic { struct horizontal_kind : units::kind {}; using distance = units::quantity_kind; struct position { latitude lat; longitude lon; }; distance spherical_distance(position from, position to); } // namespace geographic