# 绘图|解决Cartopy Lambert投影坐标轴标签设置问题

python中有两个使用最频繁的地图绘图库：Basemap和Cartopy，两者各有优劣。由于Cartopy和matplotlib的兼容性更好，并且用户友好度更高，开始逐渐被人接受。但是Cartopy也有一些缺点，其中之一就是在设置坐标轴标签的时候对于非矩形投影无法设置标签，比如Lambert投影。

```from copy import copy
import numpy as np
import shapely.geometry as sgeom
import cartopy.crs as ccrs

def find_side(ls, side):
"""
Given a shapely LineString which is assumed to be rectangular, return the
line corresponding to a given side of the rectangle.

"""
minx, miny, maxx, maxy = ls.bounds
points = {'left': [(minx, miny), (minx, maxy)],
'right': [(maxx, miny), (maxx, maxy)],
'bottom': [(minx, miny), (maxx, miny)],
'top': [(minx, maxy), (maxx, maxy)],}
return sgeom.LineString(points[side])

def lambert_xticks(ax, ticks):
"""Draw ticks on the bottom x-axis of a Lambert Conformal projection."""
te = lambda xy: xy[0]
lc = lambda t, n, b: np.vstack((np.zeros(n) + t, np.linspace(b[2], b[3], n))).T
xticks, xticklabels = _lambert_ticks(ax, ticks, 'bottom', lc, te)
ax.xaxis.tick_bottom()
ax.set_xticks(xticks)
ax.set_xticklabels([ax.xaxis.get_major_formatter()(xtick) for xtick in xticklabels])

def lambert_yticks(ax, ticks):
"""Draw ticks on the left y-axis of a Lamber Conformal projection."""
te = lambda xy: xy[1]
lc = lambda t, n, b: np.vstack((np.linspace(b[0], b[1], n), np.zeros(n) + t)).T
yticks, yticklabels = _lambert_ticks(ax, ticks, 'left', lc, te)
ax.yaxis.tick_left()
ax.set_yticks(yticks)
ax.set_yticklabels([ax.yaxis.get_major_formatter()(ytick) for ytick in yticklabels])

def _lambert_ticks(ax, ticks, tick_location, line_constructor, tick_extractor):
"""Get the tick locations and labels for an axis of a Lambert Conformal projection."""
outline_patch = sgeom.LineString(ax.outline_patch.get_path().vertices.tolist())
axis = find_side(outline_patch, tick_location)
n_steps = 30
extent = ax.get_extent(ccrs.PlateCarree())
_ticks = []
for t in ticks:
xy = line_constructor(t, n_steps, extent)
proj_xyz = ax.projection.transform_points(ccrs.Geodetic(), xy[:, 0], xy[:, 1])
xyt = proj_xyz[..., :2]
ls = sgeom.LineString(xyt.tolist())
locs = axis.intersection(ls)
if not locs:
tick = [None]
else:
tick = tick_extractor(locs.xy)
_ticks.append(tick[0])
# Remove ticks that aren't visible:
ticklabels = copy(ticks)
while True:
try:
index = _ticks.index(None)
except ValueError:
break
_ticks.pop(index)
ticklabels.pop(index)
return _ticks, ticklabels```

```import cartopy.crs as ccrs
import cartopy.feature as cfeature
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
from cartopy.mpl.gridliner import LATITUDE_FORMATTER, LONGITUDE_FORMATTER
import matplotlib.pyplot as plt

proj = ccrs.LambertConformal(central_longitude=117, central_latitude=26,
standard_parallels=(30, 60))

shpfn = 'bou2_4l.shp'
states_provinces = cfeature.ShapelyFeature(reader.geometries(), crs = ccrs.PlateCarree(), edgecolor = 'face', facecolor = 'None')

fig = plt.figure(figsize=(9, 9), frameon=True)

ax = fig.add_axes([0.08, 0.05, 0.8, 0.94], projection=proj)

# Label axes of a Mercator projection without degree symbols in the labels
# and formatting labels to include 1 decimal place:
ax.set_extent([85, 135, 0, 55], crs=ccrs.PlateCarree())

#    ax.coastlines(resolution='50m')
# *must* call draw in order to get the axis boundary used to add ticks:
fig.canvas.draw()

# Define gridline locations and draw the lines using cartopy's built-in gridliner:
xticks = list(range(60, 176, 10))
yticks = list(range(-5, 66, 10))
ax.gridlines(xlocs=xticks, ylocs=yticks)

# Label the end-points of the gridlines using the custom tick makers:
ax.xaxis.set_major_formatter(LONGITUDE_FORMATTER)
ax.yaxis.set_major_formatter(LATITUDE_FORMATTER)
# xticks and yticks only is list
lambert_xticks(ax, xticks)
lambert_yticks(ax, yticks)

plt.show()```

0 条评论

• ### 建议收藏！Matplotlib常见组件设置整理

继上一篇文章为大家介绍了plt和ax绘图的区别后，这篇文章结合我自己的一些使用经历，为大家整理了Matplotlib中比较常用的一些组件设置。

• ### 使用 Cartopy 和 netCDF4 可视化 WRF 模式数据

对比使用 Basemap，gdal 和 Cartopy，netCDF4 读取 WRF 模式数据并绘图。

• ### 真・WRF模式后处理之Python版

WRF模式是数值天气预报和大气模拟系统，其开发目的就是用语研究和实际应用。运行WRF模式时，可以利用多种初始场数据来驱动，然后配置好选项之后便可以模拟天气过程（...

• ### 全文检索Solr集成HanLP中文分词

以前发布过HanLP的Lucene插件，后来很多人跟我说其实Solr更流行（反正我是觉得既然Solr是Lucene的子项目，那么稍微改改配置就能支持Solr），...

• ### JBPM4.4(1)-简单工程的搭建

源码下载 https://anonsvn.jboss.org/repos/jbpm/jbpm4/ JBPM是什么？ jBPM是一个可扩展、灵活的流程引擎， 它可...

• ### python3装饰器

装饰器本质其实就是一个函数, 可以让其它函数不改动源代码的情况下增加其他新功能, 比如网站经常需要的权限校验等场景

• ### Linux命令之time——计算命令运行时间

linux下time命令可以获取到一个程序的执行时间，包括程序的实际运行时间(real time)，以及程序运行在用户态的时间(user time)和内核态的时...

• ### JS实现网页简体繁体字转换功能

在网页中经常会遇到将简体字转换成繁体字，方便于其他同胞查看。网页中实现简体中文转换成繁体字方法，今天分享给大家，此方法借鉴于他人博客；

• ### FPGA设计心得（9）基于DDS IP核的任意波形发生器设计

数据手册[1]博客首页[2]花了几个小时写了这篇博客，不得不说的是了解的还是皮毛而已，但尽力写的详细点，这比较适合新手，老手可以忽略繁琐的部分。注：学习交流使用...