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 ):
@@ -1663,6 +1673,9 @@ def pcolormesh(self, *args, **kwargs):
16631673 A :class:`~cartopy.crs.Projection`.
16641674
16651675 """
1676+ # Add in an argument checker to handle Matplotlib's potential
1677+ # interpolation when coordinate wraps are involved
1678+ args = self ._wrap_args (* args , ** kwargs )
16661679 result = matplotlib .axes .Axes .pcolormesh (self , * args , ** kwargs )
16671680 # Wrap the quadrilaterals if necessary
16681681 result = self ._wrap_quadmesh (result , ** kwargs )
@@ -1673,22 +1686,62 @@ def pcolormesh(self, *args, **kwargs):
16731686 self .autoscale_view ()
16741687 return result
16751688
1689+ def _wrap_args (self , * args , ** kwargs ):
1690+ """
1691+ Handle the interpolation when a wrap could be involved with
1692+ the data coordinates before passing on to Matplotlib.
1693+ """
1694+ if (kwargs .get ('shading' , 'auto' ) in ('nearest' , 'auto' ) and
1695+ len (args ) == 3 and
1696+ isinstance (kwargs .get ('transform' ), _WRAP_PROJECTIONS )):
1697+ X = np .asanyarray (args [0 ])
1698+ Y = np .asanyarray (args [1 ])
1699+ nrows , ncols = np .asanyarray (args [2 ]).shape
1700+ Nx = X .shape [- 1 ]
1701+ Ny = Y .shape [0 ]
1702+ if X .ndim != 2 or X .shape [0 ] == 1 :
1703+ x = X .reshape (1 , Nx )
1704+ X = x .repeat (Ny , axis = 0 )
1705+ if Y .ndim != 2 or Y .shape [1 ] == 1 :
1706+ y = Y .reshape (Ny , 1 )
1707+ Y = y .repeat (Nx , axis = 1 )
1708+
1709+ def _interp_grid (X , wrap = 0 ):
1710+ # helper for below
1711+ if np .shape (X )[1 ] > 1 :
1712+ dX = np .diff (X , axis = 1 )
1713+ # account for the wrap
1714+ if wrap :
1715+ dX = (dX + wrap / 2 ) % wrap - wrap / 2
1716+ dX = dX / 2
1717+ X = np .hstack ((X [:, [0 ]] - dX [:, [0 ]],
1718+ X [:, :- 1 ] + dX ,
1719+ X [:, [- 1 ]] + dX [:, [- 1 ]]))
1720+ else :
1721+ # This is just degenerate, but we can't reliably guess
1722+ # a dX if there is just one value.
1723+ X = np .hstack ((X , X ))
1724+ return X
1725+ t = kwargs .get ('transform' )
1726+ xwrap = abs (t .x_limits [1 ] - t .x_limits [0 ])
1727+ if ncols == Nx :
1728+ X = _interp_grid (X , wrap = xwrap )
1729+ Y = _interp_grid (Y )
1730+ if nrows == Ny :
1731+ X = _interp_grid (X .T , wrap = xwrap ).T
1732+ Y = _interp_grid (Y .T ).T
1733+
1734+ args = (X , Y , args [2 ])
1735+ return args
1736+
16761737 def _wrap_quadmesh (self , collection , ** kwargs ):
16771738 """
16781739 Handles the Quadmesh collection when any of the quadrilaterals
16791740 cross the boundary of the projection.
16801741 """
16811742 t = kwargs .get ('transform' , None )
1682- wrap_proj_types = (ccrs ._RectangularProjection ,
1683- ccrs ._WarpedRectangularProjection ,
1684- ccrs .InterruptedGoodeHomolosine ,
1685- ccrs .Mercator ,
1686- ccrs .LambertAzimuthalEqualArea ,
1687- ccrs .AzimuthalEquidistant ,
1688- ccrs .TransverseMercator ,
1689- ccrs .Stereographic )
1690- if not (isinstance (t , wrap_proj_types ) and
1691- isinstance (self .projection , wrap_proj_types )):
1743+ if not (isinstance (t , _WRAP_PROJECTIONS ) and
1744+ isinstance (self .projection , _WRAP_PROJECTIONS )):
16921745 # Nothing to do
16931746 return collection
16941747
@@ -1751,6 +1804,7 @@ def _wrap_quadmesh(self, collection, **kwargs):
17511804 # where the main plot is obscured
17521805 zorder = collection .zorder - .1
17531806 kwargs .pop ('zorder' , None )
1807+ kwargs .pop ('shading' , None )
17541808 kwargs .setdefault ('snap' , False )
17551809 vmin = kwargs .pop ('vmin' , None )
17561810 vmax = kwargs .pop ('vmax' , None )
@@ -1799,6 +1853,9 @@ def pcolor(self, *args, **kwargs):
17991853 A :class:`~cartopy.crs.Projection`.
18001854
18011855 """
1856+ # Add in an argument checker to handle Matplotlib's potential
1857+ # interpolation when coordinate wraps are involved
1858+ args = self ._wrap_args (* args , ** kwargs )
18021859 result = matplotlib .axes .Axes .pcolor (self , * args , ** kwargs )
18031860
18041861 # Update the datalim for this pcolor.
0 commit comments