mpusz / mp-units

The quantities and units library for C++
https://mpusz.github.io/mp-units/
MIT License
1.07k stars 85 forks source link

feat: implementation of implicit point origins #522

Closed mpusz closed 9 months ago

mpusz commented 9 months ago

Open questions

  1. Should the below be allowed:
static_assert(std::constructible_from<quantity_point<isq::length[m]>, quantity<isq::height[m]>>);
  1. Should the quantity_from_zero() work only with the zeroth_point_origin, or should we allow it to work with every quantity point and it would always return a distance from absolute_point_origin, which is meant to designate 0 for the measurement scale.
JohelEGP commented 9 months ago

static_assert(std::constructible_from<quantity_point<isq::length[m]>, quantity<isq::height[m]>>);

Yes, I think so.


If quantity_from_zero is to only work with zeroth_point_origin, then it shouldn't be a member of quantity_point. It should be a member of zeroth_point_origin's namespace for ADL. I'd expect it to be named from_zero and to require the origin to be a specialization of zeroth_point_origin. It would be an example of a convenience interface that users can write themselves. For example, for a home point origin, I could write a from_home that returns the quantity relative to home. But then, why not just provide quantity_point::from_origin(origin_argument) as a generic version?

mpusz commented 9 months ago

Yes, I think so.

I also thought like that at the beginning, but then I started to wonder if we really should assume that length, height, width, and radius are measured starting from the same point? They mean something different, so they probably should have different origins. If so, such points should not be convertible (even though the quantities are).

mpusz commented 9 months ago

But then, why not just provide quantity_point::from_origin(origin_argument) as a generic version?

We already have quantity_point::quantity_from_origin(PointOrigin). If we assume that quantity_point::quantity_from_zero() could work with any quantity_point then in such cases it would return quantity_point::quantity_from_origin(quantity_point::absolute_point_origin) which simplifies many cases. For example:

-const quantity from_lat = from.lat.quantity_from(equator);
-const quantity from_lon = from.lon.quantity_from(prime_meridian);
+const quantity from_lat = from.lat.quantity_from_zero();
+const quantity from_lon = from.lon.quantity_from_zero();

On the other hand, I am not sure if I would do the same for altitudes above mean_sea_level. Even if mean_sea_level is defined as an absolute_point_origin now, it might not be tomorrow.

JohelEGP commented 9 months ago

It should be fine to have a time point for "waiting time in a line" be defined from a period (the fixed time an event takes to reoccur) of "time it takes for light to reach Earth from the Sun".

mpusz commented 9 months ago

Sure, and no one prevents it. I just don't think it is a good choice for a default implicit point origin behavior.

I already have tests for:

inline constexpr struct zeroth_length : absolute_point_origin<zeroth_length, isq::length> {} zeroth_length;

static_assert(std::constructible_from<quantity_point<isq::length[m], zeroth_length>,
                                      quantity_point<isq::height[m], zeroth_length>>);

but I would prefer such a point to be provided explicitly.

JohelEGP commented 9 months ago

static_assert(std::constructible_from<quantity_point<isq::length[m]>, quantity<isq::height[m]>>);

I thought this was about constructing a quantity point from "zero" with a quantity vector.

mpusz commented 9 months ago

Stating otherwise, I think that the below could be fine:

static_assert(std::constructible_from<quantity_point<isq::length[m], implicit_zeroth_point_origin<isq::length>>,
                                      quantity_point<isq::height[m], implicit_zeroth_point_origin<isq::length>>>);

However, this is not what the below provides:

static_assert(std::constructible_from<quantity_point<isq::length[m]>, quantity<isq::height[m]>>);

As this one is equivalent to:

static_assert(std::constructible_from<quantity_point<isq::length[m], implicit_zeroth_point_origin<isq::length>>,
                                      quantity_point<isq::height[m], implicit_zeroth_point_origin<isq::height>>>);

and I do not think it is good to assume that implicit_zeroth_point_origin<isq::length> and implicit_zeroth_point_origin<isq::height> are the same points.