问题描述
如果我采用一组经纬度点,使用 cartopy 的“transform_points”方法将它们转换为 OSGB crs,然后绘制它们,与直接绘制经纬度相比,它们会发生偏移。如果我将它们转换回纬度/经度,它们的绘图就可以了。如果我将它们转换为 UTM 坐标,它们的绘图就可以了。我错过了什么吗? 示例代码:
import numpy as np
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from cartopy.io.img_tiles import OSM
# set up figure and background map tile
fig = plt.figure()
ax = plt.axes(projection=OSM().crs)
ax.set_extent((-2.473911,-2.410147,50.567006,50.605896))
ax.add_image(imagery,14)
# Plot some test points using lat/long (PlateCarree) crs
test_lonlat = np.array([[-2.464482,-2.432523,-2.437892],[50.593243,50.596390,50.573177]])
plt.plot(test_lonlat[0],test_lonlat[1],'r:+',transform=ccrs.PlateCarree())
# Transform to OSGB coords and plot
test_OS = ccrs.OSGB().transform_points(ccrs.PlateCarree(),test_lonlat[0],test_lonlat[1])
plt.plot(test_OS[:,0],test_OS[:,1],'kx-',transform=ccrs.OSGB())
plt.show()
感谢您的建议。
使用单点的简单示例
fig = plt.figure(figsize=[7,7])
ax = plt.axes(projection=OSM().crs)
ax.set_extent((-2.435,-2.405,50.575,50.595))
ax.add_image(OSM(),14)
# Simpler test of OSGB crs
# Take point at end of outer breakwater: OS (370783,76226) or lat/long (-2.414343,50.584978)
point_os = [370774.0,76221.0]
point_lonlat = [-2.414278,50.584971]
# Plot each on OSM tile - both look ok but small error
plt.plot(point_os[0],point_os[1],'r+',transform=ccrs.OSGB(),markersize=15)
plt.plot(point_lonlat[0],point_lonlat[1],'kx',transform=ccrs.PlateCarree(),markersize=10)
# Convert lat/long to OSGB and plot - Now offset by ~50 m to NW
point_os_new = ccrs.OSGB().transform_point(point_lonlat[0],ccrs.PlateCarree())
plt.plot(point_os_new[0],point_os_new[1],'m^',markersize=10)
# Print both sets of OS coords
print(f'Original point: {point_os}')
print(f'Transformed point: {point_os_new}')
解决方法
当你用这行代码创建一个 axes
来绘图时
ax = plt.axes(projection=OSM().crs)
您应该使用 cartopy.crs.Mercator
投影坐标在其上绘图,因为 OSM().crs 是墨卡托。
这部分代码:
# Transform to OSGB coords and plot
test_OS = ccrs.OSGB().transform_points(ccrs.PlateCarree(),\
test_lonlat[0],test_lonlat[1])
plt.plot(test_OS[:,0],test_OS[:,1],'kx-',transform=ccrs.OSGB())
使用 OSGB 坐标绘制墨卡托投影。那是错误的部分。
正确的代码行应该是
test2_OS = OSM().crs.transform_points(ccrs.PlateCarree(),test_lonlat[1])
ax.plot(test2_OS[:,test2_OS[:,transform=OSM().crs)
编辑 1
我上面图中的平铺图像是 OSM()
,通过 ax.add_image(OSM(),14)
。
OP面临的问题是数据和轴之间没有使用匹配的坐标系,或者错误的值。