Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Plumbing for pipelines #453

Merged
merged 8 commits into from Nov 20, 2016
Merged

Plumbing for pipelines #453

merged 8 commits into from Nov 20, 2016

Conversation

busstoptaktik
Copy link
Member

This is a much improved reimplementation of the ideas behind PR #388 "Transformation Pipelines".

This PR implements the library code only. An upcomming PR will reintroduce the TRAN command line interface, and a handful of elementary transformations typically used in geodetic transformation pipelines.

Thomas Knudsen added 5 commits November 14, 2016 16:26
The pipeline interface is now internally based on the pj_obs_api, which
simplifies the implementation significantly.

This is the first mock up - it compiles fine, but is currently untested
The pipeline code is now based on the PJ_OBS api (although you can still
invoke a pipeline through pj_fwd/pj_inv and their 3D brethren).

This has made it possible to eliminate scores of funky casts and
convoluted workarounds. The code is now way more straightforward and
mostly conforming with common C idioms..

Also, the proj.h / obs_api interface to the logging system has been
streamlined through the introduction of the pj_log_error, pj_log_debug,
and pj_log_trace functions.
First proj.h style interface to Charles Karney's geodesics code:
pj_lp_dist.
Also, renamed pj_apply -> pj_trans
Second eccentricity, second and third flattening etc.
... and add self test code for PJ_pipeline
@busstoptaktik busstoptaktik self-assigned this Nov 18, 2016
@busstoptaktik busstoptaktik modified the milestones: 4.10.0, 4.9.4 Nov 18, 2016
Copy link
Member

@kbevers kbevers left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I actually haven't got very many comments to the code. It seems quite well thought-out to me. Good job, Thomas.

The pipeline concept is very powerful, but also rather complicated compared to what has been possible in PROJ.4 up until now. This needs to be documented thoroughly. I suggest a new section on the webpage, "Coordinate transformation" where the concept of pipelines can be introduced. It will also be a nice place to document the geodetic transformations that are coming from you soon. Additionally the new proj.h/pj_obs_api.c API should be documented in the "Development" section. This doesn't have to be a part of this PR, but should be written at least before the next release and preferably a lot sooner so first-movers has a chance to try things out.


************************************************************************

**The Problem**
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're not using these three headings. Might as well remove them.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added the description, the headings were hinting at instead :-)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works for me too. Most of the text can be used as a general introduction in the docs as well.

if (0==strcmp ("step", argv[i])) {
if (-1==i_pipeline) {
pj_log_error (P, "Pipeline: +step before +proj=pipeline");
return pipeline_freeup (P, 51);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are setting the error number på 51 here. It seems like an arbitrary number to me. How about defining a constant? Like EPIPELINE or something in the PJ_ namespace. The same error could be used below (instead of 50 and 52). I think having one error-type for everything pipeline related is good enough.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This part is definitely a bug - thanks for spotting it. The pj_strerrno values must be negative. They are, however, mostly used by proj, geod, and cs2cs, so I'm not sure it's worth the effort to introduce symbolic constants. I'll consider whether it makes sense to open an enhancement proposal to implement this.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Corrected by introducing element 50 in pj_strerrno, and replacing all error message numbers in PJ_pipeline to -50.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They are, however, mostly used by proj, geod, and cs2cs, so I'm not sure it's worth the effort to introduce symbolic constants. I'll consider whether it makes sense to open an enhancement proposal to implement this.

Me neither. Usually though, I have no idea what a given error number means and I'll have to look it up. Could just as well be solved by comments in the code. Labelling the error numbers with good names fixes that and makes the code more readable. But that is outside the scope of this PR i think :)

@busstoptaktik busstoptaktik merged commit fab2015 into OSGeo:master Nov 20, 2016
@busstoptaktik busstoptaktik deleted the plumbing-for-pipelines branch November 20, 2016 05:04
Copy link
Contributor

@QuLogic QuLogic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alas, this was merged before I finished reading it, but I think the parsing could perhaps have been simplified a bit.

last_step = P->opaque->steps + 1;
incr = 1;

for (i = first_step; i != last_step; i += incr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the increment actually change? Why not just i++?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again for (mostly) historical reasons - the code came from a function that combined the forward and inverse implementations.

Will be cleaned up in connection with the 0-offset stuff

static PJ_OBS pipeline_forward_obs (PJ_OBS point, PJ *P) {
int i, first_step, last_step, incr;

first_step = 1;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this not the conventional 0-based access for a reason?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's actually mostly for historical reasons (in the previous version of the pipeline stuff, P[0] was the pipeline driver itself, and a sentinel was needed in the far end of the pipeline, because P was an array of PJs, not of PJ *.

I intend to clean this up at a later date, but I need to go on with some material actually using the pipeline functionality in order to stress test the implementation

return 0;

argc = argc_params (P->params);
argv = argv_params (P->params);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass argc to argv_params to avoid an extra iteration through P->params? Alternatively, argv = argv_params(P->params, &argc);?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks - implementing this improvement as part of comming PR


/* The elements of current_argv are not used - we just use argv_params */
/* as allocator for a "large enough" container needed later */
current_argv = argv_params (P->params);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's two extra iterations through P->params when you already have argc and can just calloc it, no?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks again - have implemented it for next PR

return pipeline_freeup (P, ENOMEM);

/* Do some syntactic sanity checking */
for (i = 0; i < argc; i++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calculation of argc or argv could have been folded into here.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree it could be done, but I'm not sure how to do it without reducing code clarity.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should be possible in just two iterations to do everything; I can open a PR for it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, in two iterations. I think I misunderstood: Thought you wanted to fold everything info the syntax check loop - which can be done, but not very elegantly. And as this part is not at all a speed concern, I preferred to just implement the first two suggestions, eliminating two trips through the stack, and Still keeping the code clean.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, definitely not just one loop, as that would require assuming some maximum size of each step or some messy reallocing.

Two loops should work though, first loop counts nstep and maximum args-per-step, and second loop populates argv for parsing each step's arguments.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See https://github.com/busstoptaktik/proj.4/blob/Horner-and-Helmert/src/PJ_pipeline.c#L359-L388 for the current implementation, which I think captures most of your intentions

@busstoptaktik
Copy link
Member Author

Sorry for fat-fingering a merge (due to a momentarily sluggish mouse response), while you were reviewing. I appreciate your comments and will implement most of them in comming PRs

@kbevers kbevers modified the milestones: 5.0.0-b, 5.0.0 Feb 1, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants