Op 22-6-2016 om 18:39 schreef Adam Wulkiewicz:
Barend Gehrels wrote:<snip>Op 20-6-2016 om 17:59 schreef Adam Wulkiewicz:
So in general I propose to hide as much as we can and expose only crucial parts of the API.
For run-time projections use PIMPL idiom and wrap the pointer inside.
Require only to define CalculationType for projection and use double as default.
In transform strategy take projection as template parameter and use run-time projection as default.
// compile-time
projections::robin_spheroid<> prj("+ellps=WGS84 +units=m");
projections::robin_spheroid<> prj(srs::spheroid<>());
projections::forward(pt_ll, pt_xy, prj);
// run-time
projections::projection<> prj("+proj=robin +ellps=WGS84 +units=m");
projections::projection<> prj(epsg);
projections::forward(pt_ll, pt_xy, prj);
// also runtime
projections::project_transformer<> projection("+proj=robin +ellps=WGS84 +units=m");
transform(pt_ll, pt_xy, projection);
This looks indeed simpler. And probably it is possible. This should be changed in the generation.
I was also thinking about an alternative API, based on projection tags:
// run-time
projections::projection<> prj("+proj=robin +ellps=WGS84 +units=m");
// compile-time
projections::projection<robin> prj("+ellps=WGS84 +units=m");
So robin (or robin_tag) would be a tag passed into projection<> as template parameter. For a default tag the projection would be runtime and for non-default tag the projection would be compile-time.
This looks also good. The _tag suffix is mainly used internally, but it is actually exposed to the user when registering new types, so I think it could be used indeed. But without is also fine and more conform with the initialization string.
And then it would be possible to pass only tag to transform strategy, so no need to pass the whole projection type.
// run-time
projections::project_transformer<> projection("+proj=robin +ellps=WGS84 +units=m");
transform(pt_ll, pt_xy, projection); // compile-time projections::project_transformer<robin> projection("+ellps=WGS84 +units=m"); transform(pt_ll, pt_xy, projection);This could simplify the generic implementation. E.g. the constructors taking all of those possible input parameters directly in projection (mentioned below) could be implemented only once. Otherwise we'd be forced to implement all constructors in every static projection.
On the other hand it could be harder to understand when projection is dynamic and when static.
What do you think?
It looks very good. I think the difference between static (specify in source code) and dynamic (in initialization string) is clear enough.
Note that also possible should be:
typedef boost::geometry::linestring<any point type> ls;
ls line_ll, line_xy; // fill line_ll
projections::forward(line_ls, line_xy, prj);
So the line is automatically projected, where, if necessary, extra points are added because straight lines will usually become curved and vv is also possible. Same for most other geometry types (multi_point excepted).
This does not need to be implemented in the first release, but we need to take this into account.
Wouldn't it be the transform() function's purpose?
Yes, that is true.
Another way could be project_transformer automatically figuring out the projection direction and explicit project_forward_transformer, project_inverse_transformer strategies.
It is by the generation. I have to look this up, but if the proj4 source supports an ellipsoid for it (even if it does not make sense), it is generated too. We can always adapt the generation.
I'm also confused about the names of projections. AFAIU the ones marked as xxx_ellipsoid map from ellipsoid of revolution or spheroid and the ones marked as xxx_spheroid map from a sphere. There is also e.g. cass_spheroid which AFAIU can work with ellipsoid of revolution. Are these simple inaccuracies or am I missing something?
Currently the names are directly derived from Proj4 parameter names but in WKT they're different (PROJECTION["Transverse_Mercator"]) so users which doesn't know Proj4 could be confused.
What do you think about naming projections using full names, e.g.:
projections::aea_ellipsoid -> projections::albers_equal_area
projections::cass_spheroid -> projections::cassini
projections::tmerc_ellipsoid -> projections::transverse_mercator
I kept all the proj4 names and I think that is more convenient than adding another translation table. For users, who usually know proj4 (it is quite well-known), it is also more convenient.
Having said that, I agree that cassini looks better than just cass, and if WKT has a complete map of all translations, we could consider that too.
And by "proj4 names" do you mean the names of functions used in the Proj4 sources?
Because the projection parameters has different names in Proj4 string format. I'd expect the users are more familiar with these names, not function names.
E.g. for aea_ellipsoid (e.g. http://spatialreference.org/ref/epsg/2964/) I see that there are basically 3 formats/names:
OGC WKT: PROJECTION["Albers_Conic_Equal_Area"]
Proj4: +proj=aea
ESRI WKT: PROJECTION["Albers"]
OK
project_transformer<cea> projection(proj4("+ellps=WGS84 +units=m"));
project_transformer<cylindrical_equal_area> projection(proj4("+ellps=WGS84 +units=m"));
This would again be more clear and general. And wouldn't be confusing if we had tri-axial ellipsoid projections in the future.
Thanks for your input.
I'd like to do the necessary work now if you're still ok with that.
Sure I am, it would be great to make new progress here. Do you also want to update the conversion program?