On 9 October 2015 at 06:24, Adam Wulkiewicz <adam.wulkiewicz@gmail.com> wrote:
Hi Jeremy,

Jeremy Murphy wrote:
Hi,

I recently tried using Boost.Units' SI length as the coordinate type for geometry and, well, it didn't work: specifically, the BG algorithms didn't compile. I'm not that familiar with Boost.Units so maybe I'm using the wrong unit.
Should it be possible to do this (use an SI unit as the coordinate type)?

Boost.Geometry wasn't tested with Boost.Units' coordinates so it's probable that they aren't supported. Using length units as cartesian coordinates seems to be ok. Though I can imagine that something may easily go wrong in places where e.g. coordinate type is used to store the result of multiplication of coordinates, so basically in the whole library. AFAIU the unit of a product should be squared unit of coordinate. I'm not familiar with Boost.Unit neither but I guess that Boost.Unit requires to use a different type of it. Is that correct? If that's true, supporting Boost.Unit may be out of our reach, at while Boost.Geometry supports C++03.

 Yeah, multiplication and division of a unit results in a different unit and thus a different type. 

 
What errors are reported exactly?

I have contracted the boost::units::quantity template parameters for ease of reading as I assume their omission doesn't actually detract from understanding.

(1) construction:

.../boost/geometry/util/normalize_spheroidal_coordinates.hpp:76:16: error: no matching conversion for functional-style cast from 'double' to 'boost::units::quantity<...>'

which is for code like:

    template <typename CoordinateType>
    struct constants_on_spheroid<CoordinateType, degree>
    {
        static inline CoordinateType period()
        {
            return CoordinateType(360.0); // Construction.
        }

Construction requires specifying units, e.g.: (360.0 * degree::plane_angle) or (2.5 * si::metres).

 
(2) conversion:

.../boost/geometry/extensions/gis/projections/impl/pj_fwd.hpp:63:12: error: no viable conversion from 'typename fp_coordinate_type<point<degree, quantity<...>, cs::geographic, 2> >::type' (aka 'boost::units::quantity<...>') to 'double'

on:

    template <typename Prj, typename LL, typename XY, typename P>
    inline void pj_fwd(Prj const& prj, P const& par, LL const& ll, XY& xy)
    {
        using namespace detail;

        double lp_lon = geometry::get_as_radian<0>(ll); // Conversion.

There is no implicit conversion (except from dimensionless units) so usually this would require calling .value() to extract the raw value.


(3) mixing double with quantity in expressions:

.../boost/geometry/extensions/gis/projections/impl/pj_inv.hpp:63:56: error: invalid operands to binary expression ('typename multiply_typeof_helper<quantity<...>, double>::type' (aka 'quantity<unit_type, value_type>') and 'double')


(4) no matching function call, presumably because of no implicit conversion:

.../boost/geometry/extensions/gis/projections/impl/pj_inv.hpp:73:5: error: no matching function for call to 'set_from_radian'


(5) other

.../boost/lexical_cast/detail/converter_lexical.hpp:243:13: error: static_assert failed "Target type is neither std::istream`able nor std::wistream`able"

on:

            BOOST_STATIC_ASSERT_MSG((result_t::value || boost::has_right_shift<std::basic_istream<wchar_t>, T >::value), 
                "Target type is neither std::istream`able nor std::wistream`able");

even though I included <boost/units/io.hpp>


So apart from (5) I think the errors are all quite predictable failures to implicitly construct or convert. Would it be reasonable to try to include support for Boost.Units explicitly in Boost.Geometry? I'm guessing some template metaprogramming could generalize construction and conversion but would it be worth the effort?

I'm thinking, off the top of my head, a construct function or class template that constructs everything except quantities as per usual but is specialized for Boost.Unit quantities and constructs them appropriately.

Cheers.

Jeremy