diff --git a/example/include/geographic.h b/example/include/geographic.h index 574b08656..07ce60f43 100644 --- a/example/include/geographic.h +++ b/example/include/geographic.h @@ -63,46 +63,53 @@ struct MP_UNITS_STD_FMT::formatter : formatter { +} equator; +inline constexpr struct prime_meridian : mp_units::absolute_point_origin { +} prime_meridian; + + template -using latitude = - mp_units::quantity>; +using latitude = mp_units::quantity_point>; template -using longitude = - mp_units::quantity>; +using longitude = mp_units::quantity_point>; template std::basic_ostream& operator<<(std::basic_ostream& os, const latitude& lat) { - if (lat.numerical_value() > 0) - return os << "N" << lat.numerical_value(); + if (lat > latitude::zero()) + return os << lat.quantity_from_origin() << " N"; else - return os << "S" << -lat.numerical_value(); + return os << -lat.quantity_from_origin() << " S"; } template std::basic_ostream& operator<<(std::basic_ostream& os, const longitude& lon) { - if (lon.numerical_value() > 0) - return os << "E" << lon.numerical_value(); + if (lon > longitude::zero()) + return os << lon.quantity_from_origin() << " E"; else - return os << "W" << -lon.numerical_value(); + return os << -lon.quantity_from_origin() << " W"; } inline namespace literals { -constexpr latitude operator"" _N(long double v) { return latitude{v * mp_units::si::degree}; } +constexpr latitude operator"" _N(long double v) +{ + return equator + ranged_representation{v} * mp_units::si::degree; +} constexpr latitude operator"" _S(long double v) { - return latitude{-v * mp_units::si::degree}; + return equator - ranged_representation{v} * mp_units::si::degree; } constexpr longitude operator"" _E(long double v) { - return longitude{v * mp_units::si::degree}; + return prime_meridian + ranged_representation{v} * mp_units::si::degree; } constexpr longitude operator"" _W(long double v) { - return longitude{-v * mp_units::si::degree}; + return prime_meridian - ranged_representation{v} * mp_units::si::degree; } } // namespace literals @@ -124,24 +131,28 @@ class std::numeric_limits> : public numeric_limits { }; template -struct MP_UNITS_STD_FMT::formatter> : formatter { +struct MP_UNITS_STD_FMT::formatter> : + formatter::quantity_type> { template auto format(geographic::latitude lat, FormatContext& ctx) { - MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", lat > geographic::latitude::zero() ? 'N' : 'S'); - return formatter::format(lat > geographic::latitude::zero() ? lat.numerical_value() : -lat.numerical_value(), - ctx); + formatter::quantity_type>::format( + lat > geographic::latitude::zero() ? lat.quantity_from_origin() : -lat.quantity_from_origin(), ctx); + MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", lat > geographic::latitude::zero() ? " N" : "S"); + return ctx.out(); } }; template -struct MP_UNITS_STD_FMT::formatter> : formatter { +struct MP_UNITS_STD_FMT::formatter> : + formatter::quantity_type> { template auto format(geographic::longitude lon, FormatContext& ctx) { - MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", lon > geographic::longitude::zero() ? 'E' : 'W'); - return formatter::format(lon > geographic::longitude::zero() ? lon.numerical_value() : -lon.numerical_value(), - ctx); + formatter::quantity_type>::format( + lon > geographic::longitude::zero() ? lon.quantity_from_origin() : -lon.quantity_from_origin(), ctx); + MP_UNITS_STD_FMT::format_to(ctx.out(), "{}", lon > geographic::longitude::zero() ? " E" : " W"); + return ctx.out(); } }; @@ -163,19 +174,24 @@ distance spherical_distance(position from, position to) using isq::sin, isq::cos, isq::asin, isq::acos; + const auto& from_lat = from.lat.quantity_from_origin(); + const auto& from_lon = from.lon.quantity_from_origin(); + const auto& to_lat = to.lat.quantity_from_origin(); + const auto& to_lon = to.lon.quantity_from_origin(); + // https://en.wikipedia.org/wiki/Great-circle_distance#Formulae if constexpr (sizeof(T) >= 8) { // spherical law of cosines - const auto central_angle = acos(sin(from.lat) * sin(to.lat) + cos(from.lat) * cos(to.lat) * cos(to.lon - from.lon)); - // const auto central_angle = 2 * asin(sqrt(0.5 - cos(to.lat - from.lat) / 2 + cos(from.lat) * cos(to.lat) * (1 - // - cos(lon2_rad - from.lon)) / 2)); + const auto central_angle = acos(sin(from_lat) * sin(to_lat) + cos(from_lat) * cos(to_lat) * cos(to_lon - from_lon)); + // const auto central_angle = 2 * asin(sqrt(0.5 - cos(to_lat - from_lat) / 2 + cos(from_lat) * cos(to_lat) * (1 + // - cos(lon2_rad - from_lon)) / 2)); return quantity_cast(earth_radius * central_angle); } else { // the haversine formula - const auto sin_lat = sin((to.lat - from.lat) / 2); - const auto sin_lon = sin((to.lon - from.lon) / 2); - const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from.lat) * cos(to.lat) * sin_lon * sin_lon)); + const auto sin_lat = sin((to_lat - from_lat) / 2); + const auto sin_lon = sin((to_lon - from_lon) / 2); + const auto central_angle = 2 * asin(sqrt(sin_lat * sin_lat + cos(from_lat) * cos(to_lat) * sin_lon * sin_lon)); return quantity_cast(earth_radius * central_angle); } diff --git a/example/unmanned_aerial_vehicle.cpp b/example/unmanned_aerial_vehicle.cpp index 56ecd8285..0aca9c832 100644 --- a/example/unmanned_aerial_vehicle.cpp +++ b/example/unmanned_aerial_vehicle.cpp @@ -96,9 +96,10 @@ double GeographicLibWhatsMyOffset(long double /* lat */, long double /* lon */) template hae_altitude to_hae(msl_altitude msl, position pos) { - const auto geoid_undulation = isq::height( - GeographicLibWhatsMyOffset(pos.lat.numerical_value_in(si::degree), pos.lon.numerical_value_in(si::degree)) * - si::metre); + const auto geoid_undulation = + isq::height(GeographicLibWhatsMyOffset(pos.lat.quantity_from_origin().numerical_value_in(si::degree), + pos.lon.quantity_from_origin().numerical_value_in(si::degree)) * + si::metre); return height_above_ellipsoid + (msl - mean_sea_level - geoid_undulation); }