Skip to content

Alternative fix for Proj 9.8#2654

Draft
dopplershift wants to merge 3 commits into
SciTools:mainfrom
dopplershift:proj98-alt
Draft

Alternative fix for Proj 9.8#2654
dopplershift wants to merge 3 commits into
SciTools:mainfrom
dopplershift:proj98-alt

Conversation

@dopplershift

Copy link
Copy Markdown
Contributor

Alternative to #2653. Here I've forced the use of a spherical datum with the equidistant cyindrical projection, which causes our scaling to work properly again.

This does result in one test failure, caused by the fact that the forced R parameter means the datum for the projection is always spherical, which flows downstream into all calls of PlateCarree.to_geodetic().

While this is a smaller change, my personal opinion is in favor of #2653 because we finally get rid of all the hacks we have been doing to try to make PlateCarree work using the eqc projection.

This eliminates a warning from shapely deprecating the geos submodule.
The scaling we do with to_meter only works when the underlying eqc
projection is operating on a sphere, not an ellipsoid.
@dopplershift dopplershift changed the title Proj98 alt Alternative fix for Proj 9.8 Mar 27, 2026
@QuLogic QuLogic closed this Jul 14, 2026
@QuLogic QuLogic reopened this Jul 14, 2026
@QuLogic

QuLogic commented Jul 14, 2026

Copy link
Copy Markdown
Member

This does result in one test failure, caused by the fact that the forced R parameter means the datum for the projection is always spherical, which flows downstream into all calls of PlateCarree.to_geodetic().

We could override to_geodetic to return the ellipsoidal datum when no globe is specified. This is just more of a hack, but would be a smaller change.

Something hard-coded like this works, but I did not test all Globes outside of what tests normally do:

diff --git a/lib/cartopy/crs.py b/lib/cartopy/crs.py
index 05ea62b1..cfae83b2 100644
--- a/lib/cartopy/crs.py
+++ b/lib/cartopy/crs.py
@@ -1361,6 +1361,7 @@ def _ellipse_boundary(semimajor=2, semiminor=1, easting=0, northing=0, n=201):
 
 class PlateCarree(_CylindricalProjection):
     def __init__(self, central_longitude=0.0, globe=None):
+        self._default_globe = globe is None
         globe = globe or Globe(semimajor_axis=WGS84_SEMIMAJOR_AXIS)
         proj4_params = [('proj', 'eqc'), ('lon_0', central_longitude),
                         ('to_meter', math.radians(1) * WGS84_SEMIMAJOR_AXIS),
@@ -1371,6 +1372,35 @@ class PlateCarree(_CylindricalProjection):
         self.threshold = x_max / 360
         super().__init__(proj4_params, x_max, y_max, globe=globe)
 
+    _default_globe_srs = (
+        'GEOGCRS["unknown",'
+        'DATUM["Unknown based on WGS 84 ellipsoid",'
+        'ELLIPSOID["WGS 84",{major},{inverse_flattening},'
+        'LENGTHUNIT["metre",1,ID["EPSG",9001]]]],'
+        'PRIMEM["Greenwich",0,ANGLEUNIT["degree",{degree}],ID["EPSG",8901]],'
+        'CS[ellipsoidal,3],'
+        'AXIS["longitude",east,ORDER[1],ANGLEUNIT["degree",{degree},ID["EPSG",9122]]],'
+        'AXIS["latitude",north,ORDER[2],ANGLEUNIT["degree",{degree},ID["EPSG",9122]]],'
+        'AXIS["ellipsoidal height (h)",up,ORDER[3],'
+        'LENGTHUNIT["metre",1,ID["EPSG",9001]]]]'
+    )
+
+    def as_geodetic(self):
+        """
+        Return a new Geodetic CRS with the same ellipse/datum as this
+        CRS.
+
+        """
+        return CRS(
+            self._default_globe_srs.format(
+                degree=math.radians(1),
+                major=WGS84_SEMIMAJOR_AXIS,
+                inverse_flattening=(WGS84_SEMIMAJOR_AXIS /
+                                    (WGS84_SEMIMAJOR_AXIS - WGS84_SEMIMINOR_AXIS)),
+            )
+            if self._default_globe else
+            self.geodetic_crs.srs)
+
     def _bbox_and_offset(self, other_plate_carree):
         """
         Return a pair of (xmin, xmax) pairs and an offset which can be used

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants