有没有办法将图形的范围设置为超出投影限制?
例如,当使用“ Rijksdriehoek”投影(EPSG 28992)时,来自Cartopy(proj4?)的限制是错误的,太窄了。
该投影旨在覆盖整个荷兰,但施加的限制甚至导致该国部分地区被切断。而我宁愿将范围设置为比官方界限稍宽一些,以提供一些额外的背景信息。
不幸的是,set_extent
方法给出了一个错误:
ValueError: Failed to determine the required bounds in projection
coordinates. Check that the values provided are within the valid range
(x_limits=[646.3608848793374, 284347.25011780026],
y_limits=[308289.55751689477, 637111.0245778429]).
set_xlim
/ set_ylim
方法似乎无能为力,这对普通的matplotlib轴都有效。
示例代码:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
projection = ccrs.epsg(28992)
fig, ax = plt.subplots(figsize=(5,10), subplot_kw=dict(projection=projection))
ax.coastlines(resolution='10m')
ax.add_feature(cfeature.NaturalEarthFeature('cultural', 'admin_0_boundary_lines_land', '10m', facecolor='none', edgecolor='k'))
图形的范围自动设置为投影的极限:
print(projection.bounds)
print(ax.get_extent())
(646.3608848793374, 284347.25011780026, 308289.55751689477, 637111.0245778429)
(646.3608848793374, 284347.25011780026, 308289.55751689477, 637111.0245778429)
根据有关投影的文档,实际限制应为:(-700 300000 289000 629000)
。但是对于可视化目的,即使是那些看起来也有些严格。
例如,请参见“有效范围部分”:
答案 0 :(得分:2)
我发现Cartopy中的投影限制来自Proj4中的限制,因此没有立即解决的方法。 但是,您可以通过查询参数来定义等效投影... 首先,
>>> import pyepsg
>>> proj4_epsg = pyepsg.get(28992)
>>> print(proj4_epsg.as_proj4())
'+proj=sterea +lat_0=52.15616055555555 +lon_0=5.38763888888889 +k=0.9999079 +x_0=155000 +y_0=463000 +ellps=bessel +towgs84=565.417,50.3319,465.552,-0.398957,0.343988,-1.8774,4.0725 +units=m +no_defs'
>>>
然后,例如..
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeat
proj_equivalent = ccrs.Stereographic(central_longitude=5.3876388888, central_latitude=52.15616055555,
false_easting=155000, false_northing=463000, scale_factor=0.9999079)
ax = plt.axes(projection=proj_equivalent)
x0, x1 = -4.7e4, +3.7e5
y0, y1 = 2.6e5, 6.82e5
ax.set_extent((x0, x1, y0, y1), crs=proj_equivalent)
ax.coastlines('50m', color='blue'); ax.gridlines()
ax.add_feature(cfeat.BORDERS, edgecolor='red', linestyle='--')
plt.show()
显然,这里的内置县边界非常原始。 另外,我还没有设置正确的椭圆,这需要更多的研究。 但是它显示了如何突破提供的投影边界的限制。
我不知道这里是否有机会反对Proj4?
答案 1 :(得分:1)
@ pp-mo
的回答非常好。但是,这是另一种解决方案。工作代码为:
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
# subclassing for a modified projection
class nd_prj(ccrs.Stereographic):
"""
Hacked projection for ccrs.epsg(28992) to get extended plotting limits
"""
def __init__(self):
globe = ccrs.Globe(ellipse=u'bessel')
super(nd_prj, self).__init__(central_latitude=52.15616055555555, \
central_longitude=5.38763888888889, \
#true_scale_latitude=52.0, \
scale_factor=0.9999079, \
false_easting=155000, false_northing=463000, globe=globe)
@property
def x_limits(self):
return (500, 300000) # define the values you need
@property
def y_limits(self):
return (300000, 650000) # define the values you need
projection = nd_prj() # make use of the projection
fig, ax = plt.subplots(figsize=(5,10), subplot_kw=dict(projection=projection))
ax.coastlines(resolution='10m')
ax.add_feature(cfeature.NaturalEarthFeature('cultural', 'admin_0_boundary_lines_land', \
'10m', facecolor='none', edgecolor='k'))
plt.show()
结果图:
希望这很有用。
答案 2 :(得分:1)
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import cartopy.feature as cfeature
这里是“自定义范围”投影类的灵活一些的版本。这也应使其适用于其他预测。例如,对于跨赤道国家的UTM投影。范围仍必须手动输入,可以扩展以将默认proj4
范围扩展一个百分比。
class ProjectCustomExtent(ccrs.Projection):
def __init__(self, epsg=28992, extent=[-200000, 500000, 200000, 700000]):
xmin, xmax, ymin, ymax = extent
self.xmin = xmin
self.xmax = xmax
self.ymin = ymin
self.ymax = ymax
super().__init__(ccrs.epsg(epsg).proj4_params)
@property
def boundary(self):
coords = ((self.x_limits[0], self.y_limits[0]),
(self.x_limits[0], self.y_limits[1]),
(self.x_limits[1], self.y_limits[1]),
(self.x_limits[1], self.y_limits[0]))
return ccrs.sgeom.LineString(coords)
@property
def bounds(self):
xlim = self.x_limits
ylim = self.y_limits
return xlim[0], xlim[1], ylim[0], ylim[1]
@property
def threshold(self):
return 1e5
@property
def x_limits(self):
return self.xmin, self.xmax
@property
def y_limits(self):
return self.ymin, self.ymax
获取新的投影:
projection = ProjectCustomExtent(epsg=28992, extent=[-300000, 500000, -100000, 800000])
结果:
fig, ax = plt.subplots(figsize=(10,15), subplot_kw=dict(projection=projection), facecolor='w')
ax.coastlines(resolution='10m')
ax.add_feature(cfeature.NaturalEarthFeature('cultural', 'admin_0_boundary_lines_land', '10m',
facecolor='none', edgecolor='k'), label='Stereo', zorder=999, lw=1, linestyle='-')
ax.set_extent([-100000, 400000, 200000, 700000], crs=projection)