mirror of
https://github.com/mpusz/mp-units.git
synced 2025-08-02 20:04:27 +02:00
feat: quantity_point
construction from quantity
made private + make_quantity_point
added
This commit is contained in:
@@ -67,8 +67,8 @@ auto get_waypoints()
|
||||
using namespace geographic::literals;
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
static const std::array waypoints = {
|
||||
waypoint{"EPPR", {54.24772_N, 18.6745_E}, msl_altitude{16. * ft}}, // N54°14'51.8" E18°40'28.2"
|
||||
waypoint{"EPGI", {53.52442_N, 18.84947_E}, msl_altitude{115. * ft}} // N53°31'27.9" E18°50'58.1"
|
||||
waypoint{"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft}, // N54°14'51.8" E18°40'28.2"
|
||||
waypoint{"EPGI", {53.52442_N, 18.84947_E}, mean_sea_level + 115. * ft} // N53°31'27.9" E18°50'58.1"
|
||||
};
|
||||
return waypoints;
|
||||
}
|
||||
|
@@ -98,7 +98,7 @@ hae_altitude<M> to_hae(msl_altitude msl, position<long double> pos)
|
||||
{
|
||||
const auto geoid_undulation =
|
||||
isq::height(GeographicLibWhatsMyOffset(pos.lat.number_in(si::degree), pos.lon.number_in(si::degree)) * si::metre);
|
||||
return hae_altitude<M>{msl.absolute() - geoid_undulation};
|
||||
return height_above_ellipsoid<M> + (msl.absolute() - geoid_undulation);
|
||||
}
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ struct MP_UNITS_STD_FMT::formatter<hal_altitude> : formatter<hal_altitude::quant
|
||||
// **** UAV ****
|
||||
|
||||
class unmanned_aerial_vehicle {
|
||||
msl_altitude current_{0 * si::metre};
|
||||
msl_altitude current_ = mean_sea_level + 0 * si::metre;
|
||||
msl_altitude launch_ = current_;
|
||||
public:
|
||||
void take_off(msl_altitude alt) { launch_ = alt; }
|
||||
@@ -139,7 +139,7 @@ public:
|
||||
void current(msl_altitude alt) { current_ = alt; }
|
||||
msl_altitude current() const { return current_; }
|
||||
|
||||
hal_altitude hal() const { return hal_altitude{current_ - launch_}; }
|
||||
hal_altitude hal() const { return height_above_launch + (current_ - launch_); }
|
||||
};
|
||||
|
||||
|
||||
@@ -149,11 +149,11 @@ int main()
|
||||
using namespace mp_units::international::unit_symbols;
|
||||
|
||||
unmanned_aerial_vehicle uav;
|
||||
uav.take_off(msl_altitude{6'000 * ft});
|
||||
uav.current(msl_altitude{10'000 * ft});
|
||||
uav.take_off(mean_sea_level + 6'000 * ft);
|
||||
uav.current(mean_sea_level + 10'000 * ft);
|
||||
std::cout << MP_UNITS_STD_FMT::format("hal = {}\n", uav.hal());
|
||||
|
||||
msl_altitude ground_level{123 * m};
|
||||
msl_altitude ground_level = mean_sea_level + 123 * m;
|
||||
std::cout << MP_UNITS_STD_FMT::format("agl = {}\n", uav.current() - ground_level);
|
||||
|
||||
struct waypoint {
|
||||
@@ -162,7 +162,7 @@ int main()
|
||||
msl_altitude msl_alt;
|
||||
};
|
||||
|
||||
waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, msl_altitude{16. * ft}};
|
||||
waypoint wpt = {"EPPR", {54.24772_N, 18.6745_E}, mean_sea_level + 16. * ft};
|
||||
std::cout << MP_UNITS_STD_FMT::format("{}: {} {}, {:%.2Q %q}, {:%.2Q %q}\n", wpt.name, wpt.pos.lat, wpt.pos.lon,
|
||||
wpt.msl_alt, to_hae<earth_gravity_model::egm2008_1>(wpt.msl_alt, wpt.pos));
|
||||
}
|
||||
|
@@ -179,10 +179,12 @@ concept QuantityPointLike = requires(T qp) {
|
||||
requires RepresentationOf<typename quantity_point_like_traits<T>::rep,
|
||||
get_quantity_spec(quantity_point_like_traits<T>::reference).character>;
|
||||
requires Quantity<std::remove_cvref_t<decltype(quantity_point_like_traits<T>::quantity_from_origin(qp))>>;
|
||||
requires std::constructible_from<
|
||||
quantity_point<quantity_point_like_traits<T>::reference, quantity_point_like_traits<T>::point_origin,
|
||||
typename quantity_point_like_traits<T>::rep>,
|
||||
decltype(quantity_point_like_traits<T>::quantity_from_origin(qp))>;
|
||||
{
|
||||
make_quantity_point<quantity_point_like_traits<T>::point_origin>(
|
||||
quantity_point_like_traits<T>::quantity_from_origin(qp))
|
||||
}
|
||||
-> std::same_as<quantity_point<quantity_point_like_traits<T>::reference, quantity_point_like_traits<T>::point_origin,
|
||||
typename quantity_point_like_traits<T>::rep>>;
|
||||
};
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -29,6 +29,10 @@
|
||||
|
||||
namespace mp_units {
|
||||
|
||||
template<PointOrigin auto PO, Quantity Q>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
||||
[[nodiscard]] constexpr quantity_point<Q::reference, PO, typename Q::rep> make_quantity_point(Q&& q);
|
||||
|
||||
template<QuantitySpec auto QS>
|
||||
struct absolute_point_origin {
|
||||
static constexpr QuantitySpec auto quantity_spec = QS;
|
||||
@@ -57,11 +61,6 @@ namespace detail {
|
||||
return po;
|
||||
}
|
||||
|
||||
template<QuantityPointLike QP>
|
||||
using quantity_point_like_type =
|
||||
quantity_point<quantity_point_like_traits<QP>::reference, quantity_point_like_traits<QP>::point_origin,
|
||||
typename quantity_point_like_traits<QP>::rep>;
|
||||
|
||||
} // namespace detail
|
||||
|
||||
/**
|
||||
@@ -113,13 +112,6 @@ public:
|
||||
quantity_point(const quantity_point&) = default;
|
||||
quantity_point(quantity_point&&) = default;
|
||||
|
||||
template<Quantity Q>
|
||||
requires std::constructible_from<quantity_type, Q> &&
|
||||
ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
||||
constexpr explicit quantity_point(Q&& q, decltype(point_origin) = point_origin) : q_(std::forward<Q>(q))
|
||||
{
|
||||
}
|
||||
|
||||
template<QuantityPointOf<absolute_point_origin> QP>
|
||||
requires std::constructible_from<quantity_type, typename QP::quantity_type>
|
||||
// TODO add perfect forwarding
|
||||
@@ -141,10 +133,10 @@ public:
|
||||
template<QuantityPointLike QP>
|
||||
requires std::same_as<std::remove_const_t<decltype(quantity_point_like_traits<QP>::point_origin)>,
|
||||
std::remove_const_t<decltype(point_origin)>> &&
|
||||
std::convertible_to<typename detail::quantity_point_like_type<QP>::quantity_type, quantity_type>
|
||||
constexpr explicit quantity_point(const QP& qp) :
|
||||
q_(typename detail::quantity_point_like_type<QP>::quantity_type{
|
||||
quantity_point_like_traits<QP>::quantity_from_origin(qp)})
|
||||
std::convertible_to<
|
||||
quantity<quantity_point_like_traits<QP>::reference, typename quantity_point_like_traits<QP>::rep>,
|
||||
quantity_type>
|
||||
constexpr explicit quantity_point(const QP& qp) : q_(quantity_point_like_traits<QP>::quantity_from_origin(qp))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -154,15 +146,12 @@ public:
|
||||
template<PointOriginFor<quantity_spec> NewPO>
|
||||
[[nodiscard]] constexpr QuantityPointOf<NewPO{}> auto point_from(NewPO origin) const
|
||||
{
|
||||
if constexpr (is_same_v<NewPO, std::remove_const_t<decltype(point_origin)>>) {
|
||||
if constexpr (is_same_v<NewPO, std::remove_const_t<decltype(point_origin)>>)
|
||||
return *this;
|
||||
} else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<NewPO>) {
|
||||
auto q = absolute();
|
||||
return quantity_point<reference, NewPO{}, typename decltype(q)::rep>(std::move(q));
|
||||
} else {
|
||||
auto q = absolute() - origin.quantity_point.absolute();
|
||||
return quantity_point<reference, NewPO{}, typename decltype(q)::rep>(std::move(q));
|
||||
}
|
||||
else if constexpr (detail::is_derived_from_specialization_of_absolute_point_origin<NewPO>)
|
||||
return make_quantity_point<NewPO{}>(absolute());
|
||||
else
|
||||
return make_quantity_point<NewPO{}>(absolute() - origin.quantity_point.absolute());
|
||||
}
|
||||
|
||||
// data access
|
||||
@@ -192,7 +181,7 @@ public:
|
||||
requires detail::QuantityConvertibleTo<quantity_type, quantity<::mp_units::reference<quantity_spec, U{}>{}, Rep>>
|
||||
[[nodiscard]] constexpr quantity_point<::mp_units::reference<quantity_spec, U{}>{}, PO, Rep> operator[](U) const
|
||||
{
|
||||
return quantity_point<quantity_spec[U{}], PO, Rep>{*this};
|
||||
return make_quantity_point<PO>(quantity_from_origin()[U{}]);
|
||||
}
|
||||
|
||||
// member unary operators
|
||||
@@ -235,6 +224,18 @@ public:
|
||||
q_ -= q;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
template<PointOrigin auto PO2, Quantity Q>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO2.quantity_spec>
|
||||
friend constexpr quantity_point<Q::reference, PO2, typename Q::rep> make_quantity_point(Q&&);
|
||||
|
||||
template<Quantity Q>
|
||||
requires std::constructible_from<quantity_type, Q> &&
|
||||
ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
||||
constexpr explicit quantity_point(Q&& q) : q_(std::forward<Q>(q))
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
// CTAD
|
||||
@@ -250,9 +251,7 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
||||
const quantity<R2, Rep2>& q)
|
||||
requires requires { qp.quantity_from_origin() + q; }
|
||||
{
|
||||
auto temp = qp.quantity_from_origin() + q;
|
||||
using q_type = decltype(temp);
|
||||
return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp));
|
||||
return make_quantity_point<PO1>(qp.quantity_from_origin() + q);
|
||||
}
|
||||
|
||||
template<auto R1, typename Rep1, auto R2, auto PO2, typename Rep2>
|
||||
@@ -269,7 +268,7 @@ template<PointOrigin PO, Quantity Q>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO::quantity_spec>
|
||||
[[nodiscard]] constexpr quantity_point<Q::reference, PO{}, typename Q::rep> operator+(PO, Q&& q)
|
||||
{
|
||||
return quantity_point<Q::reference, PO{}, typename Q::rep>(std::forward<Q>(q));
|
||||
return make_quantity_point<PO{}>(std::forward<Q>(q));
|
||||
}
|
||||
|
||||
template<Quantity Q, PointOrigin PO>
|
||||
@@ -286,9 +285,7 @@ template<auto R1, auto PO1, typename Rep1, auto R2, typename Rep2>
|
||||
const quantity<R2, Rep2>& q)
|
||||
requires requires { qp.quantity_from_origin() - q; }
|
||||
{
|
||||
const auto temp = qp.quantity_from_origin() - q;
|
||||
using q_type = decltype(temp);
|
||||
return quantity_point<q_type::reference, PO1, typename q_type::rep>(std::move(temp));
|
||||
return make_quantity_point<PO1>(qp.quantity_from_origin() - q);
|
||||
}
|
||||
|
||||
template<PointOrigin PO, Quantity Q>
|
||||
@@ -371,4 +368,12 @@ template<QuantityPoint QP1, QuantityPointOf<QP1::absolute_point_origin> QP2>
|
||||
return lhs.absolute() == rhs.absolute();
|
||||
}
|
||||
|
||||
// make_quantity_point
|
||||
template<PointOrigin auto PO, Quantity Q>
|
||||
requires ReferenceOf<std::remove_const_t<decltype(Q::reference)>, PO.quantity_spec>
|
||||
[[nodiscard]] constexpr quantity_point<Q::reference, PO, typename Q::rep> make_quantity_point(Q&& q)
|
||||
{
|
||||
return quantity_point<Q::reference, PO, typename Q::rep>(std::forward<Q>(q));
|
||||
}
|
||||
|
||||
} // namespace mp_units
|
||||
|
@@ -40,7 +40,14 @@ template<Unit auto U, typename C, typename Rep = double>
|
||||
using time_point = quantity_point<U, chrono_point_origin<C>, Rep>;
|
||||
|
||||
static_assert(QuantityLike<std::chrono::seconds>);
|
||||
static_assert(!Quantity<std::chrono::seconds>);
|
||||
static_assert(!QuantityPoint<std::chrono::seconds>);
|
||||
static_assert(!QuantityPointLike<std::chrono::seconds>);
|
||||
|
||||
static_assert(QuantityPointLike<sys_seconds>);
|
||||
static_assert(!Quantity<sys_seconds>);
|
||||
static_assert(!QuantityLike<sys_seconds>);
|
||||
static_assert(!QuantityPoint<sys_seconds>);
|
||||
|
||||
// construction - same rep type
|
||||
static_assert(
|
||||
@@ -108,10 +115,8 @@ static_assert(quantity{std::chrono::years{1}} == 31556952 * s);
|
||||
static_assert(quantity{1s} + 1 * s == 2 * s);
|
||||
static_assert(quantity{1s} + 1 * min == 61 * s);
|
||||
static_assert(10 * m / quantity{2s} == 5 * (m / s));
|
||||
static_assert(quantity_point{sys_seconds{1s}} + 1 * s ==
|
||||
time_point<si::second, std::chrono::system_clock, sys_seconds::rep>{2 * s});
|
||||
static_assert(quantity_point{sys_seconds{1s}} + 1 * min ==
|
||||
time_point<si::second, std::chrono::system_clock, sys_seconds::rep>{61 * s});
|
||||
static_assert(quantity_point{sys_seconds{1s}} + 1 * s == chrono_point_origin<std::chrono::system_clock> + 2 * s);
|
||||
static_assert(quantity_point{sys_seconds{1s}} + 1 * min == chrono_point_origin<std::chrono::system_clock> + 61 * s);
|
||||
|
||||
// to_chrono_duration
|
||||
static_assert(to_chrono_duration(1 * s) == 1s);
|
||||
|
@@ -45,8 +45,7 @@ inline constexpr struct ground_level : relative_point_origin<mean_sea_level + 42
|
||||
inline constexpr struct tower_peak : relative_point_origin<ground_level + 42 * isq::height[m]> {
|
||||
} tower_peak;
|
||||
|
||||
inline constexpr struct other_ground_level :
|
||||
relative_point_origin<mean_sea_level + 123 * isq::height[m]> {
|
||||
inline constexpr struct other_ground_level : relative_point_origin<mean_sea_level + 123 * isq::height[m]> {
|
||||
} other_ground_level;
|
||||
|
||||
inline constexpr struct other_absolute_level : absolute_point_origin<isq::height> {
|
||||
@@ -281,22 +280,22 @@ static_assert(!std::convertible_to<int, quantity_point<dimensionless[one], zero,
|
||||
// construction from a quantity
|
||||
/////////////////////////////////
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<si::metre, mean_sea_level>, quantity<si::metre>>);
|
||||
static_assert(!std::constructible_from<quantity_point<si::metre, mean_sea_level>, quantity<si::metre>>);
|
||||
static_assert(!std::convertible_to<quantity<si::metre>, quantity_point<si::metre, mean_sea_level>>);
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<isq::height[m]>>);
|
||||
static_assert(!std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<isq::height[m]>>);
|
||||
static_assert(!std::convertible_to<quantity<isq::height[m]>, quantity_point<isq::height[m], mean_sea_level>>);
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<si::metre>>);
|
||||
static_assert(!std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<si::metre>>);
|
||||
static_assert(!std::convertible_to<quantity<si::metre>, quantity_point<isq::height[m], mean_sea_level>>);
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<si::metre, mean_sea_level>, quantity<isq::height[m]>>);
|
||||
static_assert(!std::constructible_from<quantity_point<si::metre, mean_sea_level>, quantity<isq::height[m]>>);
|
||||
static_assert(!std::convertible_to<quantity<isq::height[m]>, quantity_point<si::metre, mean_sea_level>>);
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<special_height[m]>>);
|
||||
static_assert(!std::constructible_from<quantity_point<isq::height[m], mean_sea_level>, quantity<special_height[m]>>);
|
||||
static_assert(!std::convertible_to<quantity<special_height[m]>, quantity_point<isq::height[m], mean_sea_level>>);
|
||||
|
||||
static_assert(std::constructible_from<quantity_point<dimensionless[one], zero>, quantity<dimensionless[one]>>);
|
||||
static_assert(!std::constructible_from<quantity_point<dimensionless[one], zero>, quantity<dimensionless[one]>>);
|
||||
static_assert(!std::convertible_to<quantity<dimensionless[one]>, quantity_point<dimensionless[one], zero>>);
|
||||
|
||||
// different dimensions
|
||||
|
Reference in New Issue
Block a user