PRIMARY QUESTION: Given a previously imported/converted image file
with a proj4 string from GDAL ca. version 2.3.1 or earlier
embedded in it, what is the "best" way to create an appropriately
compatible transformation object with new PROJ versions like 9.8.1?
- Most of the rest of the questions below are trying to expand
on the nuances of this primary question...
- (I provide more background about my application near the bottom,
but hopefully it is mostly not needed?)
Based on recommendations in documentation, for new
files/imports/etc I plan to switch to WKT1 strings instead
of proj strings, but that doesn't help with previously-imported
compatibility.
QUESTION: What are the potential difference(s) between
tranformations created via different strategies? (Other
question's answers may influence this answer, and/or this answer may
render some of the other questions irrelevant.)
* Plain proj_create() supplied with the from-old-GDAL proj4 string
as-is?
- Currently usually radians, barring pipelines with unit
conversions.
- Like the "Version 4 to 5 API Migration" example.
- One archived email suggests this also might change to degrees
eventually in some future version?
https://lists.osgeo.org/pipermail/proj/2019-April/008427.html
- QUESTION: Are there corner cases that this will not work
as expected? Perhaps non-WGS84 datums?
- See also my speculation about very old pj_fwd()/pj_inv()
approach in application background section below.
* Sequence: proj_create() with black box old string,
proj_crs_get_geodetic_crs() from that,
and proj_create_crs_to_crs_from_pj() from the two?
- Currently usually degrees, I think.
- Like the second of the two quick start for C examples?
- Does this work without "+type=crs"? Documentation suggests
not (not a CRS).
* proj_create_crs_to_crs() with both:
- Currently usually degrees, I think.
- Like the "Version 4 to 6 API Migration" example.
- This seems most similar to what I was doing with PROJ.4,
but abuses(?) the arguments with non-CRSs, and does angular
units differently.
- Presumably: Use a hard-coded argument (something like
"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs",
except maybe with "+type=crs", and/or "something" to do
units conversion steps.)
- And the from-old-GDAL proj4 string?
* Start with from=projCreate("EPSG:4326") or similar,
maybe update it with proj_normalize_for_visualization()
and/or proj_crs_alter_cs_angular_unit(),
and finally combine it with something like
proj_create_ctx_to_ctx_with_pj(ctx,from,proj_create(oldProj4)).
- (Or more likely maybe proj_normalize_for_visualization()
should be applied last to the combination, since it normalizes
both input and output.)
- QUESTION: Given that
https://proj.org/en/stable/operations/operations_computation.html
includes mentions of PROJ looking up special case conversions
between pairs of CRS's in a database, would that be confused
by tweaking the CRS (axes and/or units) before combining
it with the old proj4 string?
- See additional questions about how proj4 strings don't
seem to "actually" be CRS's, units, etc. below.
QUESTION (angular units): What is the "best" way to get radians
for geographic lat/lon coordinates, similar to earlier versions
of PROJ?
* QUESTION: A variation of this question also applies to new
"based on WKT string" option I'm working on. I still want
radians for interacting with existing infrastructure in this
case.
* "Best": Ideally avoid converting back and forth repeatedly,
and also hopefully "simple" to code.
* I originally combined a hard-coded proj4 PJ
"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
with the GDAL-supplied proj4 PJ in pj_transform(),
which then usually used radians.
- Now with the new API proj_create_crs_to_crs(), it
usually expects degrees.
* Difficulty: There's a special nuance for cases when
old GDAL OGRSpatialReference::IsGeographic() returned true.
- In these cases, my GDAL plugin would adjust image's
affine (aka world or 6 parameter) linear transform for
radians, since the original affine usually output degrees
in this case.
- QUESTION: What's the bsst way to detect "IsGeographic()"
to account for how that was compensated by the affine part,
ideally without GDAL?
- MAYBE: However, depending on overall strategy above, maybe
I won't need to dig into this?
- MAYBE copy and simplify GDAL IsGeographic() function?
But it seems a tad involved.
- QUESTION: What is a "PJ_TYPE_BOUND_CRS", which seems
relevant to how the new "IsGeographic()" function is
implemented? The documentation lists this enum option,
but doesn't describe it at all. Or is it irrelevant if
the proj4 string came from old GDAL?
* MAYBE just convert angular units myself outside of PROJ?
- But converting back and forth definitely seems a bit
inefficient and ugly.
- And I need to know exactly when to do such conversion...
- QUESTION: Under this option, should I just assume proj
is using degrees? It looks like there are ways it could
(sometimes) be doing something else, although unusual.
- QUESTION: Or should use functions like
proj_angular_input(), proj_angular_output(),
proj_degree_input(), and/or proj_degree_output() to determine
if I should deal with it externally? Any gotchas with
this? What if a CRS is using really unusual angular units
(neither degrees nor radians)?
* MAYBE use proj_create() with the persisted old proj4 string,
instead of proj_create_crs_to_crs()?
- See also question about different ways to create PJ object,
above.
* MAYBE somehow add a units conversion step (pipeline) to the
hard-coded "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
I previously used with pj_transform()?
- See more "projinfo"-based analysis below...
* MAYBE add on an extra units conversion step "later".
- Vaguely like proj_normalize_for_visualization(), except
for units instead of axis order.
- QUESTION: Is there any robust way compose transforms
on objects (instead of blindly playing modification games with
black-box strings, or fully understanding and reproducing
big chunks of the string parser)?
- MAYBE: It looks like proj_crs_alter_cs_angular_unit() sort of
does this.
- Only works with a CRS, not a constructed transform.
- See also above mention, especially the question about
looking up best conversions in the database.
QUESTION: What does proj_create_crs_to_crs() do with non-CRS proj4
args (and similar "expects crs" functions if given a non-CRS)?
* The documentation and examples says it accepts proj4 strings
(without a "+type=crs" qualifier), but doesn't say what it does
with them in this case.
* Testing with the "Version 4 to 6 API Migration example" suggests
non-CRS "works" in the sense it does not error out (returns
non-NULL, no warnings), but testing with "projinfo" suggests
the PJ transform is in a state that projinfo can't tell me
anything about. See also below.
QUESTION: Clarify how additional parameters affect "+proj=latlon"
(especially "+ellps" and "+datum").
* https://proj4.org/en/stable/operations/conversions/latlon.html
* The documentation is good about "on it's own", with:
"No parameters will affect the output of the operation if used
on it's own."
* But I'm not sure what "used in a declaritive manner" means in
"However, the parameters below can be used in a declarative
manner when used with cs2cs or in a transformation pipeline."
- It seems like latlon's "+datum" might alter results if
combined with a projection with a different "+datum" via the
proj_create_crs_to_crs() function?
------------------
Things I have been looking into:
------------------
I'm trying to play with "projinfo" to attempt to learn how things
work. Attempting to summarize (although it is hard):
* In the single proj4 argument case:
- If doing a pipeline or similar non-CRS cases, the WKT
basically just seems to wrap the proj4 args (with
"CONVERSION" and "METHOD", rather than "really" being
native WKT).
- With "+proj=latlon", if I try to use pipeline to convert
input from rad to deg, and/or output from deg to rad, it
errors out with "Mismatched units between step ...".
With or without "+type=crs", and even though in a CRS
context (or two-arg form below) "+proj=latlong" would
appear to use degrees (WKT).
- If I add "no-op" unit conversions to the pipeline
(like "+step +proj=unitconvert +xy_in=rad +xy_out=rad"),
it doesn't seem to optimize them out (the non-CRS thing above).
* In the "-s/-t" two-CRS form, if either or both proj4 strings
lack "+type=CRS" (which they will with old GDAL, at least):
- "projinfo" errors out complaining that it isn't a CRS.
- But proj_create_crs_to_crs() seems to do something
(return non-NULL) even though they aren't CRS's. But
it isn't documented what it does with this non-CRS form,
nor does "projinfo" help.
- QUESTION: Would appending "+type=CRS" to an old GDAL proj4
string be generically valid in all cases? (I would prefer
to treat proj4 as a black box, avoid modifying the
string "blindly", and any manipulation is "as an object" instead
of "as a string".)
- Hard-coded
"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs +type=CRS"
works. But I haven't been able to enhance that to use a
pipeline to do units conversion.
- QUESTION: I haven't figured out a syntax to make
"+type=CRS" work in a pipeline. Is it possible?
- I've tried starting with the EPSG:4326 WKT string as
one of the arguments, except I modify its CS ANGLEUNITS.
- Depending on the main projection arg, two-CRS "projinfo"
shows a two step process in WKT, but a
simplified "main" single-arg proj4 string. Maybe this
is reasonable? Or does multi-setp WKIT imply it is
slower?
- QUESTION: What if the black-box-from-old-GDAL string happens
to be IsGeographic()? One way to handle that (if
detected - see above) is to convert both input AND output
to radians within PROJ, somehow. (Although there may be
other ways with tweaking old affine...)
- I notice that output from the following
mentions rough "ballback" transformations.
- projinfo -s EPSG:4326 \
-t "+proj=merc +ellps=WGS84 +lat_ts=33 +type=crs"
- Similar for other variations of the 4 to 6 migration
example, including trying to mix its' clrk66 ellipsoid
with WGS84. (I'm not even sure which combinations make
any sense.)
- Adding "+datum=WGS84" to the proj4 string seems to help.
But a "+datum=clrk66" isn't recognized.
- See also documentation bugs in this example below
(mixing up datum vs ellps)?
- I haven't checked: Does old GDAL always (or usually)
include a datum in proj4 strings?
- There is similar confusion trying to mix
---
I tried searching old github issues and mailing list archives, although
it isn't easy, I've been far from thorough, and even if there are
interesting nuggets in there, they are buried under a lot of stuff.
But a few I stumbled over:
https://github.com/OSGeo/PROJ/issues/3546
- Seemed to result in the quick start example
involving proj_crs_get_geodetic_crs().
- https://github.com/OSGeo/PROJ/pull/3515
- https://github.com/OSGeo/PROJ/issues/3508
https://github.com/OSGeo/PROJ/issues/4283
- An angular units issue in cct command line.
https://github.com/OSGeo/PROJ/issues/3597
- Unexpected unit conversion in pipeline, workaround to
explicitly convert to desired units, and apparently proj
has an "optimizer" to eliminate redundant steps.
https://github.com/OSGeo/PROJ/issues/2027
- Querying input/output angular units. (But only degrees and radians,
not arbitrary.)
https://github.com/OSGeo/PROJ/issues/1662
- Seems somewhat related to my questions, but the answers
don't seem great.
https://github.com/OSGeo/PROJ/issues/1178
- Early discussion about axis swapping issues.
- Also mentions units issues, but doesn't really go anywhere
with it.
https://lists.osgeo.org/pipermail/proj/2019-April/008414.html
- The first message in a thread asking about angular units.
----------
DOCUMENTATION BUGS:
----------
Tangent: Things that looked like bugs to me (not just "incomplete")
when reading the documentation:
- BUG https://proj.org/en/stable/operations/conversions/unitconvert.html
Typo: "z_in" is described as "Vertical output units", not input.
- BUG https://proj.org/en/stable/operations/projections/eqc.html
EPSG:1028 and EPSG:1029 are mentioned on this page, but projinfo
doesn't recognize them.
- BUG https://proj.org/en/stable/operations/transformations/deformation.html
The sentence "Both grids GDAL both reads and writes both file formats"
probably needs some editing.
- BUGS: https://proj.org/en/stable/operations/transformations/helmert.html
and various others: Various pages will (sometimes) report
"Erroneous nesting of equation structures" instead of showing a
mathematical expression. (Unless I turn off javascript. But I
don't know TeX or its partial javascript port(s) well enough to
debug these without a lot more effort.)
- BUGS: Examples for version 4 migrations need to include
stdio.h (scanf/printf) and math.h (HUGE_VAL). Also, main()'s
return type should be specified as int rather than implied.
- BUG (or at least confusing): In the "Version 4 to 6 Migration"
section, the original proj4 example program uses a different
proj string than the PROJ6 version of the same program.
- Specifically, datum is changed to ellpse in
"+proj=merc +datum=clrk66 +lat_ts=33" vs
"+proj=merc +ellps=clrk66 +lat_ts=33".
- PROJ 9.8.1 doesn't like the "+datum=clrk66". PROJ 4.9.3's "proj"
program doesn't seem to like it either. Has it ever been valid?
- QUESTION: If this is actually "correct", then how would a
programmer know when/how to change the string like this?
----------
APPLICATION BACKGROUND:
----------
20 years ago I wrote some code for handling background image and
projection code on the Earth for a proprietary application.
The application draws the Earth as a WGS-84 shaped ellipsoid, with
heights of vertices adjusted based on terrain, and images texture
mapped onto it. Then it draws other things in the same coordinate
system, using Earth to provide context.
- The application has "native" support for this that doesn't
involve GDAL or PROJ at all. Most of this support thinks in
either ECEF or (lat,lon,alt) in *radians* and meters.
- GDAL and PROJ are isolated in plugins and custom abstractions
to support a lot more "standard" image file formats and
the projections specified in those files, assuming the
plugins are available.
- Known bug: Currently it treats "MSL altitude" from various sources
as exactly the same thing as "height above the ellipsoid", without
handling even a low-precision geoid (vertical datum) as appropriate.
Roughly up to a 100 meter vertical error in some cases.
This has been open in our issue tracker for nearly a decade, and
I've known about it for far longer. (Despite the decade delay,
this is probably higher priority than a couple of meters from
things like continental drift.)
The application includes an ability to "import" imagery into a
application-native format, with generated pyramid / RRDs to
handle any eye point / zoom level.
- I'm glossing over lots of image stack composition,
multiresolution pyramid / RRD data structures, and eyepoint logic.
- Currently the projection in such an imported image is based
on proj4 strings as generated by GDAL ca. 2.3.1
OGRSpatialReference::exportToProj4(), plus the
affine (aka world or 6 parameter) transform that most ground
images use.
- Actually, I adjust the affine values slightly very early
for "normalized" resolution-independent image coordinates
(range 0 to 1 for opposite sides of the image) and
sometimes radians vs degrees difficulty (next bullet).
- Slight difficulty: My GDAL plugin had some additional
logic to test OGRSpatialReference::IsGeographic(), and
if true adjust the returned affine transform values for
degrees vs radians, since in this case the original affine
values are generally referenced against degrees instead of
radians.
- To convert between geographic lat/lon and (normalized) image
coordinates, the plugin used pj_transform() between the
"black box" proj4 string originally from GDAL, and a hard-coded
"+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs",
along with my own code for the affine transform (or its
inverse). (ECEF conversion happens elsewhere.)
- During development 20 years ago, I initially used pj_fwd()
and pj_inv(), but within a few days changed to pj_transform()
under the unconfirmed speculative theory that pj_transform()
might have a chance of handling datum changes?
- QUESTION: Is there any truth to this theory? I haven't seen
hard evidence either way...
---------
Matthew Ogilvie
---------
_______________________________________________
PROJ mailing list
[email protected]
https://lists.osgeo.org/mailman/listinfo/proj