Boost logo

Boost Users :

Subject: Re: [Boost-users] [units][geometry] subtract_typeof_helper<> help!
From: Barend Gehrels (barend_at_[hidden])
Date: 2011-01-04 04:22:02


Hi Alfredo,

> as I told you, my implementation is a total mock up and I am not sure
> I am doing it with the right philosophy.
> I added the code of boost_geometry_units.hpp file at the end of this
> post. I guess it works for me because I specialised the class
> model::point<double, 3, cs::units_cartesian<...> > and its
> constructor.

Thanks for this code.

> The logic is that once you introduce units, the types of the
> coordinates are not uniform types, for example, a real space vector
> can have its cartesian coordinates in meters, but in spherical
> coordinates, only the radial part is in meters, (the others are
> angles).

I see, good point.

> But maybe you are right the coordinates should be double upon
> constructions and the metric and units is only contained in the type.
>
> I understand that integrations with Boost.Units is not planned and
> even not desirable.
> But making the implicit assumption that
> typeof(sqrt(s)) == typeof(s) or that typeof(s*s)==type(s)
> makes it incompatible with Boost.units. Those assumptions are good as
> defaults but there should be a way to tell Boost.Geometry that
> sometimes it is not the case.

I see what you mean. Yesterday in other answer I already referred to
this. This would mean a total rework of all calculations, which is
impossible, at least with respect to the time available for it. Look
e.g. here:
http://bit.ly/gOT5Yk
and try to give them a physical meaning with quantities etc...

Besides the amount of work, with many calculations such as the dot
product and the determinant, the physical meaning is there but normally
not used in this context. Dot product and determinant just returns a
value, AFAIK normally not expressed in square meters. Determinant (and
"side" which is similar) are e.g. used in segment intersection; those
calculations are just steps in between; the end product are coordinates
again. Having units applied there would be a burden nobody expects there
(I think)...

>> So Boost.Geometry is not dependant on Boost.Units. I think the way to go
>> is define a point type using a coordinate system using Boost.Units, like
>> you did, and also add quantities there.
> yes. Even at the interface level I am not sure for example if
> constructors should carry units or not. I added the units to my
> constructors to make it more dimensionally type safe. Maybe the
> boost.units people will have clearer idea.

OK, I'm curious.
>
>> boost::geometry::units::area(a) -> returns a quantity e.g. in
>> square_meters from a polygon
>>
>> So I added two of these functions as well, giving:
>>
>> std::cout<< units::get<0>(p2)<< std::endl;
>> quantity<si::length> d = units::distance(p1, p2);
>> std::cout<< d<< std::endl;
>>
>> reporting all quantities including units. It required some small
>> additional metafunctions as well.
>
> yes, I the same thing in my first implementation, with a namespace
> boost::geometry::units that have all the overloaded functions but then
> I though it would have a lot a repeated code.

Yes, it would, but on the other hand, it makes a lot of things much and
much simpler. Besides that, there are not so many functions like this:
area, length, perimeter, distance are quantified values, but many others
as intersection, union, simplify; and boolean predicates as within,
intersects, all can do without any overload.

>> I just committed it, for the moment as a new example (including
>> definitions), here:http://bit.ly/dEip8s
> (...) below the "mock up" code for boost_geometry_units.hpp. It is not good
> code, it is just barely enough to make it work with
> (...)
>
> template<class T, std::size_t Dimension, class Unit>
> boost::units::quantity<Unit, T> distance(
> model::point<T, Dimension, cs::units_cartesian<Unit> > const& p1,
> model::point<T, Dimension, cs::units_cartesian<Unit> > const& p2
> ){
> return boost::units::quantity<Unit, T>::from_value(
> boost::geometry::distance(
> (model::point<T, Dimension, cs::cartesian> const&)p1,
> (model::point<T, Dimension, cs::cartesian> const&)p2
> )
> );
> }

I understand how you got this working now. It is similar to my solution
(forwarding to distance) but here you have the need to many casts, and
many additional metafunctions and specializations implemented...

> namespace strategy{namespace distance{namespace services{
>
> template<class Unit> struct
> return_type<boost::geometry::units_cartesian_tag<Unit> >{
> typedef boost::units::quantity<Unit> type;
> };
> (...)

This, and the other code, is necessary here, but not in the proposal I
sent...

So there are more than one approaches, you can write an own distance
strategy, correctly handling x*x and sqrt(x) w.r.t. Boost.Units. This
might be doable for distance, but for huge algorithms as intersections,
where you actually do not have any profit from units (input =
coordinates, output = coordinates), I personally think it is way too much.

I'm actually curious to know, is does the solution (that example) work
for you?

Regards, Barend


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net