[PROJ] Migrating to proj API 6+ without forcing crs input

Even Rouault even.rouault at spatialys.com
Thu Apr 14 10:31:07 PDT 2022


Le 14/04/2022 à 18:55, Johannes Schauer Marin Rodrigues a écrit :
> Hi Even,
>
> Quoting Even Rouault (2022-04-14 17:41:05)
>> I already answered (I admit I more and more terse with years) in
>> https://github.com/OSGeo/PROJ/issues/3161#issuecomment-1094238124
>>
>> So for your case where you don't have a CRS but a pipeline, and assuming
>> it serves the role of the source, you'd need an alternate code path that
>> would do
>>
>> PJ* P = proj_create(ctxt, "+proj=pipeline " +
>> your_pipeline_without_proj_equal_pipeline_and_with_steps_in_reverse_order_and_with_+inv_qualifier_added_when_absent_or_removed_when_present
>> + " +step " + proj_string_of_target )
>>
>> proj_trans(P, PJ_FWD, ...);
>>
>> so yes, there's a bunch of PROJ string manipulation to do.
> thanks for your reply! So you suggest that projects that are upgrading to proj
> API 6+ and want to continue supporting non-CRS user-supplied strings should
> resort to implementing their own proj string parser and transformation code?

Well, tinshift support was added after PROJ 6, so there's no real 
backward compatibility issue here.

Most of the past users of pj_transform() used it with PROJ strings that 
were CRS definitions, so we're a bit in the category of unanticipated / 
marginal use cases.

The reason for PROJ 6 to differenciate CRS from 
transformations/pipelines is that in past version PROJ strings that were 
meant to be CRS definitions used PROJ operation methods that can also be 
used to do transformations, hence it was a bit like a CRS was a 
transformation from something (some 'base' CRS not always well defined) 
to the CRS of interest. Stopping here my confusing digging into past 
design decisions :-), but basically there are good reasons of separating 
CRS and transformation/pipelines and not lightly mixing them together.

>   Is
> there not something that can be provided by proj itself to make this easier?
> If proj would add some code to support this, then this would also prevent a
> number of differently buggy proj parsing and transformation codebases to be
> implemented by every project that cares about non-CRS input. It seems odd to me
> that with upgrading to a new API version, the use-case of using proj for
> non-CRS input is now so hard where before it just worked out-of-the box.

Obviously it is messy to do that outside of PROJ . It's not immediate to 
my mind which reasonable and well-defined C API PROJ could offer for 
what you need.

But there's definitely in the PROJ C++ code things to ingest a PROJ 
string, invert it (including reverting order and direction of pipeline 
steps), concatenate it, in a hopefully not-too-buggy way, as that's used 
internally by it.

Particularly the PROJStringFormatter class: 
https://github.com/OSGeo/PROJ/blob/master/include/proj/io.hpp#L376

with the ingestPROJString(), startInversion(), stopInversion(), 
addStep(), addParam() and toString() methods

In pseudo code, your below proposal would be something like

osgeo::proj::io::PROJStringFormatter formatter;

formatter.startInversion();

formatter.ingestPROJString(source_pipeline);

formatter.stopInversion();

formatter.ingestPROJString(target_pipeline)

P = proj_create(ctx, formatter.toString().c_str() )

>
> If there are no plans to add some helper function for this use-case, can you
> confirm that the right solution would be something like (some error checking
> omitted for brevity):
>
>      PJ *P;
>      PJ *source = proj_create(ctx, source_string);
>      PJ *target = proj_create(ctx, target_string);
>      if(proj_is_crs(source) && proj_is_crs(target)) {
>          P = proj_create_crs_to_crs_from_pj(ctx, source, target, NULL, NULL);
>          // continue with proj_normalize_for_visualization according to the migration guide
>      } else {
>          /* 1. if source is a pipeline:
>                   1.1. parse the pipeline string and remove
>                   1.2. reverse steps
>                   1.3. invert +inv
>             2. if target is a pipeline, keep the order and +inv as is
>           */
>          P = proj_create(ctx, "+proj=pipeline +step " +
>                /* result of (1.) without leading +proj=pipeline */
>                + " +step " +
>                /* result of (2.) without leading +proj=pipeline */
>          );
>      }
Looks good
>
> What to do if source or target is not a CRS and also not a pipeline?

What kind of objects are you thinking too ? If it is a single 
transformation step, then it is semantically a pipeline with one step.

You can't do anything useful with other types of objects (datums , 
ellipsoids, etc.)

Mixing a CRS with a pipeline/transformation can also be a bit tricky 
because of unit and axis order adjustments that you may need to insert.


>
> Thanks again!
>
> cheers, josch
>
> _______________________________________________
> PROJ mailing list
> PROJ at lists.osgeo.org
> https://lists.osgeo.org/mailman/listinfo/proj

-- 
http://www.spatialys.com
My software is free, but my time generally not.



More information about the PROJ mailing list