Obtaining coordinates in projected map using Cartopy

老子叫甜甜 提交于 2020-01-13 20:20:11

问题


I'm trying to obtain the coordinates of the features of a map using Cartopy but I would like to obtain the map projected coordinates instead of the data from the original projection.

For instance:

import matplotlib.pyplot as plt
import cartopy.crs as ccrs

fig = plt.figure(figsize=(10, 10))
ax = plt.axes(projection=ccrs.epsg(3857))
fig.add_axes(ax)
ax.coastlines()
ax.set_global()
lines = ax.plot((0, 360), (-85.06, 85.06), transform=ccrs.PlateCarree())
fig.show()

The previous code shows a map with two lines using the map projection but lines (a list with matplotlib.lines.Line2D instances) is just only one object with the coordinates in the original projection of the data (lines[0].get_data() ---> (array([ 0, 360]), array([-85.06, 85.06]))).

On an interactive plot, a Qt5 backend obtained after fig.show(), I can see coordinates in EPSG:3857 and in PlateCarree when the cursor is over the map so I wonder if there is an easy way to get lines in EPSG:3857 coordinates.

EDIT: The example above is quite simplified. I've tried to do it simple for better understanding but maybe is better to show the real problem.

I have a grid of data with longitudes in the range [0, 360]. I can modify the arrays in order to have inputs in the range [-180, 180] and I'm using Cartopy/Matplotlib to plot contours. From the contours I'm obtaining a matplotlib.contour.QuadContourSet with several matplotlib.collections.LineCollection. From each matplotlib.collections.LineCollection I can obtain the matplotlib.path.Paths and I would like to have the coordinates of each Path in EPSG:3857 instead of in the original PlateCarree so I can use cartopy.mpl.patch.path_to_geos to convert each Path to a shapely geometry object in the EPSG:3857 projection without having to extract vertices from each Path, convert them from PlateCarree to EPSG:3857 and then create a new Path with the converted coordinates to use cartopy.mpl.patch.path_to_geos to obtain geometries in the crs I need.


回答1:


The question asks for a coordinate transformation using Cartopy's feature, and maybe something else. Here I provide the code that performs coordinate transformation and computation check.

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import numpy as np

# Test data in geographic lon, lat (degrees)
lons = np.array((0, 360.01))      # any number of longitude
lats = np.array((-85.06, 85.06))  # .. longitude

# define all CRS
crs_longlat = ccrs.PlateCarree() 
crs_3857 = ccrs.epsg(3857)

# Transformation function
def coordXform(orig_crs, target_crs, x, y):
    """
    Converts array of (y,x) from orig_crs -> target_crs
    y, x: numpy array of float values
    orig_crs: source CRS
    target_crs: target CRS
    """

    # original code is one-liner
    # it leaves an open axes that need to plt.close() later
    # return plt.axes( projection = target_crs ).projection.transform_points( orig_crs, x, y )

    # new improved code follows
    xys = plt.axes( projection = target_crs ).projection.transform_points( orig_crs, x, y )
    # print(plt.gca())  # current axes: GeoAxes: _EPSGProjection(3857)
    plt.close()         # Kill GeoAxes
    # print(plt.gca())  # AxesSubplot (new current axes)
    return xys

# Transform geographic (lon-lat) to (x, y) of epsg(3857)
xys = coordXform(crs_longlat, crs_3857, lons, lats)
for ea in xys:
    print("(x, y) meters: " + str(ea[0]) + ', ' + str(ea[1]))

#Output(1)    
#(x, y) meters: 0.0, -20006332.4374
#(x, y) meters: 1113.19490794, 20006332.4374

# Computation check
# Transform (x, y) of epsg(3857) to geographic (lon-lat), degrees
xs = xys[:,0]  # all x's
ys = xys[:,1]  # all y's
lls = coordXform(crs_3857, crs_longlat, xs, ys)
for ea in lls:
    print("(lon, lat) degrees: " + str(ea[0]) + ', ' + str(ea[1]))

#Output(2)
#(lon, lat) degrees: 0.0, -85.06
#(lon, lat) degrees: 0.01, 85.06

# plt.close() # no need now

Edit 2

According to the constructive comments, the transformation function above can be written as follows:

def coordXform(orig_crs, target_crs, x, y):
    return target_crs.transform_points( orig_crs, x, y )


来源:https://stackoverflow.com/questions/48196797/obtaining-coordinates-in-projected-map-using-cartopy

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!