当前位置: 首页 > 知识库问答 >
问题:

matplotlib绘图中卡托地轴如何正确设置投影和变换

李睿
2023-03-14

在使用Python geopandas、cartopy和matplotlib以正确绘制shapefile数据时,我面临着严重的困难。

问题来自于在正确设置转换和投影对象的shapefile数据的困难。

我在这里描述的示例是相对于SIRGAS 2000投影中的SHP而言的,其WKT格式为:

GEOGCS[“SIRGAS 2000”,基准[“D_SIRGAS_2000”,球体[“GRS_1980”,6378137298.257222101]],PRIMEM[“格林威治”,0],单位[“度”,0.017453292519943295]]

从上面的WKT可以看出,我的坐标是以度为单位的。地球仪不是WGS84,而是GRS_1980,与WGS84相似(但不相等)。

该crs尚未在cartopy中实施。因此,尝试使用cartopy.crs.EPSG(4674)这样的函数是行不通的,特别是因为这不是投影crs,而是地理crs。

在打印问题之后,我从逻辑上假设我应该使用四个cartopy.crs选项中的一个来打印我的数据:

transform_option_1 = cartopy.crs.PlateCarree() # works well

transform_option_2 = cartopy.crs.PlateCarree(globe=ccrs.Globe(ellipse='GRS80')) # works well

transform_option_3 = cartopy.crs.Geodetic(globe=ccrs.Globe(ellipse='GRS80')) # doesn't work

# using wkt:

WKT = """GEOGCS["SIRGAS 2000",DATUM["D_SIRGAS_2000",SPHEROID["GRS_1980",6378137,298.257222101]],PRIMEM["Greenwich",0],UNIT["Degree",0.017453292519943295]]"""

transform_option_4 = ccrs.PlateCarree(WKT) # results in an error message (see message in annex)

但是,当我尝试使用四个变换选项打印数据时,我的变换选项3和变换选项4出现错误。

前两个选项(transform_option_1,transform_option_2),一切运作良好。此外,当我比较图中的前两个转换选项时,它们会产生相同的图形,尽管它们会导致略有不同的图(由于全球对象)。这是我的第一个问题:

问题1:尽管Globe对象不同,为什么ccrs.PlateCarree()对象对我的数据产生相同的绘图?

问题2:由于cartopy接受WKT字符串格式用于转换对象实例,为什么会出现错误?请参阅本信息下方所附的错误信息(错误信息编号1)。

问题3:在cartopy中,大地测量投影和platecarree投影之间有什么区别?我不知道什么时候该用这个或那个。由于这两个投影的描述都暗示了以度为单位的坐标,因此我对它们的差异感到奇怪。此外,当我尝试使用cartopy绘制SHP的两个选项时,只有PlateCarree起作用。另一个结果是黑色的地轴。

下面是一段代码片段,可以更好地澄清我的问题3:


# importing libraries:
import geopandas as gpd
import matplotlib.pyplot as plt
import cartopy.crs as ccrs


# importing data:

SHP_path = 'Data_SHP.shp'

SHP = gpd.read_file(SHP_path)


# setting projection to PlateCarre:

projection = ccrs.PlateCarree() # projection.proj4_init


# setting SHP data transform

Transform2 = ccrs.Geodetic(globe=ccrs.Globe(ellipse='GRS80'))


# creating figure:

fig, ax = plt.subplots(1, subplot_kw={'projection':projection})


SHP.plot(ax=ax, transform=Transform2, 
         color='k', alpha=0.5)

# defining a small function to add grilines to the plot:

def custom_plot(geoaxes, projection):



    gl = geoaxes.gridlines(crs=projection)

    tick_axis_positions={'xlabels_top':False,
                     'ylabels_left':True,
                     'ylabels_right':False,
                     'xlabels_bottom':True}

    gl.xlabels_top = tick_axis_positions['xlabels_top']
    gl.ylabels_left = tick_axis_positions['ylabels_left']
    gl.ylabels_right= tick_axis_positions['ylabels_right']
    gl.xlabels_bottom = tick_axis_positions['xlabels_bottom']


    return geoaxes


# adding gridlines to the geoaxes:

ax = custom_plot(ax, projection)

fig.show()

# end of code


问题4:为什么我不能使用crs(WKT格式)实例化cartopy投影对象?当我尝试这样做时,会出现一条错误消息(见附件中的错误消息2)。

Projection = ccrs.Projection(proj4_params=WKT, globe=ccrs.Globe(ellipse='GRS80'))

参考文献:

1) 关于如何从WKT或proj4坐标系投影格式创建cartopy.crs变换对象的讨论

2) 将proj4映射到cartopy CRS

3)在Cartopy中绘制直线,Robinson投影

4)用cartopy绘制SHP的例子

5) cartopy变换与投影理论

附件:

错误消息1)

TypeError: unsupported operand type(s) for -: 'str' and 'float'


Traceback (most recent call last):
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_qt5.py", line 519, in _draw_idle
    self.draw()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\figure.py", line 1649, in draw
    renderer, self, artists, self.suppressComposite)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 385, in draw
    inframe=inframe)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 262, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in _prepare_points
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in <listcomp>
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\transforms.py", line 2451, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 173, in transform_path_non_affine
    src_path.vertices, self.source_projection)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 746, in quick_vertices_transform
    bboxes, proj_offset = self._bbox_and_offset(src_crs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 709, in _bbox_and_offset
    lon_0_offset = other_lon_0 - self_lon_0
TypeError: unsupported operand type(s) for -: 'str' and 'float'
Traceback (most recent call last):
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_qt5.py", line 519, in _draw_idle
    self.draw()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\backends\backend_agg.py", line 402, in draw
    self.figure.draw(self.renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\figure.py", line 1649, in draw
    renderer, self, artists, self.suppressComposite)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 385, in draw
    inframe=inframe)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\axes\_base.py", line 2628, in draw
    mimage._draw_list_compositing_images(renderer, self, artists)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\image.py", line 138, in _draw_list_compositing_images
    a.draw(renderer)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\artist.py", line 50, in draw_wrapper
    return draw(artist, renderer, *args, **kwargs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 262, in draw
    transform, transOffset, offsets, paths = self._prepare_points()
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in _prepare_points
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\collections.py", line 240, in <listcomp>
    for path in paths]
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\matplotlib\transforms.py", line 2451, in transform_path_non_affine
    return self._a.transform_path_non_affine(path)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\mpl\geoaxes.py", line 173, in transform_path_non_affine
    src_path.vertices, self.source_projection)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 746, in quick_vertices_transform
    bboxes, proj_offset = self._bbox_and_offset(src_crs)
  File "C:\Users\lealp\AppData\Local\conda\conda\envs\Python_3.7\lib\site-packages\cartopy\crs.py", line 709, in _bbox_and_offset
    lon_0_offset = other_lon_0 - self_lon_0
TypeError: unsupported operand type(s) for -: 'str' and 'float'

错误消息(2)

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-165-9916b2ddcc67> in <module>
----> 1 ccrs.Projection(proj4_params=Transform_from_wkt, globe=ccrs.Globe(ellipse='GRS80'))

TypeError: Can't instantiate abstract class Projection with abstract methods boundary, threshold, x_limits, y_limits

共有1个答案

郑晨
2023-03-14

>

我不知道CartoPy在任何地方都接受WKT。我认为从Proj.4字符串或WKT创建投影是一个悬而未决的问题。

PlateCarree的工作原理是将lat/lon作为平面上的坐标,所以lat/lon点之间的线是平面上的直线。Geodetic将lat/lons视为球体上的坐标,所以连接lat/lons的线是大圆。这是正确的做事方式,但它使数学更加复杂,对一些绘图选项不起作用。看看这个例子,看看它是如何变化的。

见上文第(2)段

我很好奇将自定义椭球体传递到大地测量时遇到了什么问题。我对该代码和Cartopy 0.17没有任何问题:

import cartopy.crs as ccrs
globe = ccrs.Globe(ellipse='GRS80')
crs = ccrs.Geodetic(globe=globe)

 类似资料:
  • SuperMap iClient for OpenLayers 通过设置 map 中 view 属性的 projection 参数来支持多投影。例如: var map = new ol.Map({ view: new ol.View({ projection: 'EPSG:4326' }); }); projection 参数除了支持 EPSG code 字符串之

  • 我正在使用sharpmap将MSSQL中的边界(几何体)渲染为PNG图像。这一切都很好,除了国家在平面图像格式上看起来太“宽”。 据我所知,我需要创建到EPSG:3857投影的转换,但我不知道如何做。 这是我的密码 WKT可以在这里找到https://pastebin.com/PEbpAdxT 感谢您的帮助。 编辑2 我也尝试了以下转换,但这会呈现空白的png(没有红色的十字线)

  • 有很多关于3D的opengl投影矩阵的很棒的教程,但我不是在做3D。我真的很难根据自己的喜好进行正交投影设置。 int宽=320;int高=480; 我使用这些设置创建了一个视图投影矩阵。 创建此视图和投影矩阵并将它们传递给gpu之后。 然后我创建一个从的四边形,以便它的原点位于中心。 然后我为四边形制作一个比例矩阵,这样我就可以在屏幕上看到它了。它呈现为一个完美的正方形,但当然glViewpor

  • 问题内容: 我正在matplotlib中生成图形,我想将x轴设置在0-10000之间,但我不想更改y轴,我希望图形自己完成。现在,两个轴都会自动生成。 这是一个例子: axis命令无法帮助我,因为我也必须设置y值。同样由于某种原因,xlim不起作用,它表示没有参数xlim。 任何建议表示赞赏,谢谢 问题答案: 这对我来说似乎很好:

  • 我理解为什么墨卡托投影的纬度是有限制的,但是根据我假设的理论,经度是[-180,180]呢。 然而,从几个地图应用程序的源代码中我看到了。他们试图将经度限制在[-177177]之间。 这是什么原因?

  • 基于这种后转换LAT/LON到像素坐标?,这与真正的墨卡托投影很好地工作。 我面临一个问题的svg地图从openstreet map使用“谷歌墨卡托投影与简化网格(1000)”。 我试着在我的法国地图上画一些城市,所有的点都在这里,但不是它们应该在的地方 svg是基于openmapstreet的pdf在Inkscape中创建的,代码有点长,我在这个fiddle中复制粘贴iti(因为我没有附上Rap