7070CARTOPY_USER_BACKGROUNDS environment variable.
7171"""
7272
73+ # A list of projections that can have wrapped coordinates.
74+ _WRAP_PROJECTIONS = (ccrs ._RectangularProjection ,
75+ ccrs ._WarpedRectangularProjection ,
76+ ccrs .InterruptedGoodeHomolosine ,
77+ ccrs .Mercator ,
78+ ccrs .LambertAzimuthalEqualArea ,
79+ ccrs .AzimuthalEquidistant ,
80+ ccrs .TransverseMercator ,
81+ ccrs .Stereographic )
82+
7383
7484# XXX call this InterCRSTransform
7585class InterProjectionTransform (mtransforms .Transform ):
@@ -1649,6 +1659,9 @@ def pcolormesh(self, *args, **kwargs):
16491659 A :class:`~cartopy.crs.Projection`.
16501660
16511661 """
1662+ # Add in an argument checker to handle Matplotlib's potential
1663+ # interpolation when coordinate wraps are involved
1664+ args = self ._wrap_args (* args , ** kwargs )
16521665 result = matplotlib .axes .Axes .pcolormesh (self , * args , ** kwargs )
16531666 # Wrap the quadrilaterals if necessary
16541667 result = self ._wrap_quadmesh (result , ** kwargs )
@@ -1659,22 +1672,62 @@ def pcolormesh(self, *args, **kwargs):
16591672 self .autoscale_view ()
16601673 return result
16611674
1675+ def _wrap_args (self , * args , ** kwargs ):
1676+ """
1677+ Handle the interpolation when a wrap could be involved with
1678+ the data coordinates before passing on to Matplotlib.
1679+ """
1680+ if (kwargs .get ('shading' , 'auto' ) in ('nearest' , 'auto' ) and
1681+ len (args ) == 3 and
1682+ isinstance (kwargs .get ('transform' ), _WRAP_PROJECTIONS )):
1683+ X = np .asanyarray (args [0 ])
1684+ Y = np .asanyarray (args [1 ])
1685+ nrows , ncols = np .asanyarray (args [2 ]).shape
1686+ Nx = X .shape [- 1 ]
1687+ Ny = Y .shape [0 ]
1688+ if X .ndim != 2 or X .shape [0 ] == 1 :
1689+ x = X .reshape (1 , Nx )
1690+ X = x .repeat (Ny , axis = 0 )
1691+ if Y .ndim != 2 or Y .shape [1 ] == 1 :
1692+ y = Y .reshape (Ny , 1 )
1693+ Y = y .repeat (Nx , axis = 1 )
1694+
1695+ def _interp_grid (X , wrap = 0 ):
1696+ # helper for below
1697+ if np .shape (X )[1 ] > 1 :
1698+ dX = np .diff (X , axis = 1 )
1699+ # account for the wrap
1700+ if wrap :
1701+ dX = (dX + wrap / 2 ) % wrap - wrap / 2
1702+ dX = dX / 2
1703+ X = np .hstack ((X [:, [0 ]] - dX [:, [0 ]],
1704+ X [:, :- 1 ] + dX ,
1705+ X [:, [- 1 ]] + dX [:, [- 1 ]]))
1706+ else :
1707+ # This is just degenerate, but we can't reliably guess
1708+ # a dX if there is just one value.
1709+ X = np .hstack ((X , X ))
1710+ return X
1711+ t = kwargs .get ('transform' )
1712+ xwrap = abs (t .x_limits [1 ] - t .x_limits [0 ])
1713+ if ncols == Nx :
1714+ X = _interp_grid (X , wrap = xwrap )
1715+ Y = _interp_grid (Y )
1716+ if nrows == Ny :
1717+ X = _interp_grid (X .T , wrap = xwrap ).T
1718+ Y = _interp_grid (Y .T ).T
1719+
1720+ args = (X , Y , args [2 ])
1721+ return args
1722+
16621723 def _wrap_quadmesh (self , collection , ** kwargs ):
16631724 """
16641725 Handles the Quadmesh collection when any of the quadrilaterals
16651726 cross the boundary of the projection.
16661727 """
16671728 t = kwargs .get ('transform' , None )
1668- wrap_proj_types = (ccrs ._RectangularProjection ,
1669- ccrs ._WarpedRectangularProjection ,
1670- ccrs .InterruptedGoodeHomolosine ,
1671- ccrs .Mercator ,
1672- ccrs .LambertAzimuthalEqualArea ,
1673- ccrs .AzimuthalEquidistant ,
1674- ccrs .TransverseMercator ,
1675- ccrs .Stereographic )
1676- if not (isinstance (t , wrap_proj_types ) and
1677- isinstance (self .projection , wrap_proj_types )):
1729+ if not (isinstance (t , _WRAP_PROJECTIONS ) and
1730+ isinstance (self .projection , _WRAP_PROJECTIONS )):
16781731 # Nothing to do
16791732 return collection
16801733
@@ -1785,6 +1838,9 @@ def pcolor(self, *args, **kwargs):
17851838 A :class:`~cartopy.crs.Projection`.
17861839
17871840 """
1841+ # Add in an argument checker to handle Matplotlib's potential
1842+ # interpolation when coordinate wraps are involved
1843+ args = self ._wrap_args (* args , ** kwargs )
17881844 result = matplotlib .axes .Axes .pcolor (self , * args , ** kwargs )
17891845
17901846 # Update the datalim for this pcolor.
0 commit comments