Hi Mats,


On 29-7-2013 19:41, Mats Taraldsvik wrote:
Hi Barend,

On 07/28/2013 07:59 PM, Barend Gehrels wrote:
Hi Mats,

On 28-7-2013 12:23, Mats Taraldsvik wrote:
Hi,

On 07/26/2013 11:54 PM, Michael Winkelmann wrote:

It would be very useful to expand on the for_each algorithms. However, as I understand the boost.geometry documentation and your proposal, there is a subtle but important difference: the current for_each_point algorithm work on a point _concept_, while your for_each<point> algorithm work on a concrete point type (in this case bg::model::d2::point_xy<double>.

I don't see why this would not work for concepts?



What if I used e.g. std::pair to represent points? I'd have to remember the exact type used for points in the polygon/ring/linestring/segment... I might have two polygons that represents points in differents ways, and then I'd have to implement the algorithm twice (for_each<bgm::d2::point_xy<double>> and for_each<std::pair<double,double>>.

I'm not sure if this is solvable in the generic case until we get proper Concepts (lite), which, combined with generic lambdas would make a concepts-based interface.

OK now I see what you mean. The proposal has probably to be read as:

size_t a = num<ring_tag>(myPolygon); // Returns number of rings in polygon
size_t b = num<segment_tag>(myRing); // Returns number of segments in ring
size_t c = num<polygon_tag>(myPolygon); // Should return 1


The tag's are mostly used internally, if used externally, they could (maybe) be namespaced e.g.

size_t a = num<geometry_type::ring>(myPolygon); // Returns number of rings in polygon

(don't know if this name is appropriate, just an idea)

I'm sorry, I could have been more clear (and I might simply be wrong :) ). I think the num-part of the proposal is fine with *_tag as template arguments. As long as the actual algorithm is written with the operations required by the point concept, it should work for every type that satisfies the point concept. And it is very useful indeed! :)

Sorry if I come across as negative with my (hopefully constructive) criticism, I'm trying not to be. :)


No problem, no worries, thanks for your reaction - it certainly helped to make things clear. So it was constructive :-)
Thanks for your new mail too.



What I'm concerned with is the lambda argument to the for_each<*_tag> algorithms. I'm not aware of a way to write a lamdba in terms of a (geometry) concept, so they will be type-specific instead of concept-specific. Which means they have to be tailored to the type of the point/linestring/polygon etc. -- not the concept (which is ideal).

Consider a Polygon that has four points of different types:

bgm::d2::point_xy<double> point1
std::pair<double, double> point2
bgm::d2::point_xy<double> point3
std::pair<double, double> point4

How do you write the for_each<point_tag> where the lambda is able to capture all four points? One could use a boost::variant or similar structure to account for all point types, but it isn't ideal, is it? (However, this might be the best solution for current C++(?))


Good point. Lambda's are written in a context, so the program or function or class-method or whatever. So if you have a main program, you use the point-type you define. Because the lambda is programmed and used only once you specify the type you need. These lambda's are never reused for other type. If you are in a template function or class, you can simply use the template-argument (which can be of any point-type, as long as it follows the context). So it all follows normal rules, only the lambda-function itself is not templated but does not need to be. This all is not really related to Boost.Geometry and also applies for std::for_each.

So it is possible; variants are not necessary.

I attached two programs (based on something I already had) to show these both uses. So it (the template version) works for any Concept. In the non-template version, it is simply not relevant to tailor it for many types (and not possible indeed).



Also, what if we decided to have some pre-defined lambdas/functions that one could use with for_each<*_tag>? They'd have to be generic (i.e. concepts-based) to be truly useful and universally applicable...

What do you mean by Concept (lite)?

Concept[s] lite is the current proposal for constraining templates, and, by extension, generic lambdas (c++14). It is planned as a TS in the C++14 timeframe, as far as I know. The latest version is N3701, look at the summer standards papers mailing [1] -- I think it is really interesting, I think it is worth a look if you are not familiar with it already.

I was not aware of the "lite" addition. OK, so this looks like the Concepts, postponed in C++11.
Boost.Geometry uses concepts and checks it by Boost Concept Check Library (BCCL).



I think this would allow the behaviour I am seeking:

for_each<point_tag>( aPolygon, [](PointConcept point)
{
    ...
});

Here, you can make use of the type of the aPolygon parameter (either a concrete type or a template), and then use (as soon as for_each is tagged, for now: for_each_point):
    boost::geometry::for_each<point_tag>
        (
            aPolygon,
            [](boost::geometry::point_type<polygon>::type const& p)
                {
                    ...
                }
        );




or, a pre-defined function

auto point_to_wgs84(PointConcept point)
{
  ...
}

...

for_each<point_tag>(anotherPolygon, point_to_wgs84);

This is also already possible (with for_each_point, without point_tag). You have to specify the template argument explicitly in the call (and note you are missing template <typename PointConcept> in your function definition). But that is no problem - it might even be a template/concept (like with lambdas). This variant is listed in the help:
http://www.boost.org/doc/libs/1_54_0/libs/geometry/doc/html/geometry/reference/algorithms/for_each/for_each_point.html (list_coordinates)


Regards, Barend