Skip to content

BUG: Honour PROJ spherification parameters in Geod (issue #1157)#1610

Open
HugoFara wants to merge 1 commit into
pyproj4:mainfrom
HugoFara:BUG_geod-honour-spherical-radius-params
Open

BUG: Honour PROJ spherification parameters in Geod (issue #1157)#1610
HugoFara wants to merge 1 commit into
pyproj4:mainfrom
HugoFara:BUG_geod-honour-spherical-radius-params

Conversation

@HugoFara

Copy link
Copy Markdown
Contributor

Geod parses the ellipsoid out of its init string in Python rather than handing the string to PROJ, and that parser dropped every parameter without a value:

# We can ignore safely any parameter that doesn't have a value
if kvpair.find("=") == -1:
    continue

+R_A and the rest of the spherification family went through there. The result was silently wrong rather than unsupported — Geod('+ellps=WGS84 +R_A') returned ellipsoidal answers with no error and no warning, while PROJ's own geod CLI honoured the flag.

This collects those parameters before valueless ones are discarded and applies the formulas from PROJ src/ell_set.cpp (ellps_spherification), including its mutual-exclusion order and the collapse to a sphere afterwards.

Semi-major axis for +ellps=WGS84, against PROJ_DEBUG=3 geod ...:

parameter before after PROJ
+R_A 6378137.000 6371007.181 6371007.181
+R_V 6378137.000 6371000.790 6371000.790
+R_a 6378137.000 6367444.657 6367444.657
+R_g 6378137.000 6367435.680 6367435.680
+R_h 6378137.000 6367426.702 6367426.702
+R_lat_a=45 6378137.000 6378110.053 6378110.053
+R_lat_g=45 6378137.000 6378101.030 6378101.030
+R_C 6378137.000 6356752.314 6356752.314

Geod.fwd now reproduces the geod CLI to 7 decimal places on all of them. The +R_A radius also matches the published WGS84 authalic sphere radius (6371007.1809 m) to 0.2 mm, so the expected values do not rest on PROJ alone.

Two deliberate limits:

  • PROJ parses the +R_lat_a/+R_lat_g latitude with proj_dmstor and so accepts DMS; this accepts decimal degrees only and raises GeodError otherwise.
  • CRS('+ellps=WGS84 +R_A').get_geod() is unchanged. +R_A has no representation in a CRS, and PROJ drops it there too, so honouring it would diverge from PROJ rather than match it.

Verification: 14 new tests, all failing before the change and passing after. Full suite 1047 passed, mypy clean, pre-commit clean. Built against PROJ 9.8.1.

Geod does not hand its init string to PROJ; it parses the ellipsoid out
in Python. That parser discarded every parameter without a value:

    # We can ignore safely any parameter that doesn't have a value
    if kvpair.find("=") == -1:
        continue

which is where +R_A and the rest of the spherification family went. The
result was silently wrong rather than unsupported: Geod('+ellps=WGS84
+R_A') returned ellipsoidal answers to a question asked about a sphere,
with no error and no warning, while PROJ's own geod CLI honoured the
flag.

Collect the spherification parameters before valueless parameters are
discarded, and apply PROJ's formulas from src/ell_set.cpp, including the
mutual exclusion order and the collapse to a sphere afterwards. All eight
now agree with PROJ to the millimetre; the +R_A radius also matches the
published WGS84 authalic sphere radius of 6371007.1809 m.

Unlike PROJ, the latitude of +R_lat_a/+R_lat_g is accepted only as
decimal degrees, not DMS. CRS('+ellps=WGS84 +R_A').get_geod() is
unchanged: +R_A has no representation in a CRS, so PROJ drops it there
too.
@snowman2 snowman2 added the bug label Jul 26, 2026
@snowman2 snowman2 added this to the 3.8.0 milestone Jul 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

+R_A appears to have no effect in Geod() and CRS()

2 participants