在底图中绘制包裹路径
Plotting a wrapped path in Basemap
我正在尝试绘制卫星地面轨道。我有一个以度为单位的纬度和经度列表。经度值都在 -180 到 +180 度之间。我的第一个问题是使用 latlon
关键字(顺便说一句,我在 Julia 中通过 PyCall.jl
包使用它,所以请原谅看起来很奇怪的语法):
map = Basemap.Basemap(projection="mill",lon_0=0)
map[:drawcoastlines]()
map[:drawparallels](-90:30:90,labels=[1,0,0,0])
map[:drawmeridians](map[:lonmin]:60:map[:lonmax]+30,labels=[0,0,0,1])
map[:plot](lon,lat,color="red",latlon=true)
这...不是应该的样子。我不太确定问题出在哪里。但是,如果我先转换为地图坐标:
xx,yy = map(lon,lat)
map[:plot](xx,yy,color="red")
这要好得多,除了 经度从 +180 到 -180 的线。有什么建议可以使它看起来更好吗?
可以找到用于生成这些图的纬度、经度对(以度为单位)here。
一开始我认为这可能与Basemap
的old issue有关。但是,我认为您的问题不是由于 Basemap
,它实际上正确地处理了经度环绕,正如您所看到的,如果您只使用标记来绘制卫星地面轨道。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x,y = m(lon, lat)
m.plot(x, y, color="red", latlon=False, marker='.', linestyle='None')
最终的解决方案是将地面轨道分成多个轨道并使用 LineCollection
绘制它们,如 here 所述。一种更简单的方法(如果您期望经度不连续):
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
latlon_ar = np.array(latlon)
threshold = 90
idx_wrap = np.nonzero(np.abs(np.diff(latlon_ar[:,1])) > threshold)[0]+1
lon_1 = lon[:idx_wrap]
lat_1 = lat[:idx_wrap]
lon_2 = lon[idx_wrap:]
lat_2 = lat[idx_wrap:]
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x1, y1 = m(lon_1, lat_1)
x2, y2 = m(lon_2, lat_2)
m.plot(x1, y1, color="red", latlon=False)
m.plot(x2, y2, color="blue", latlon=False)
编辑这个confirmed bug in Basemap
is responsible for the behaviour in the first example of the question, where Basemap.plot
is called directly with latitude and longitude values, having set the latlon
flag to True
. There is a solution,也就是在绘图前手动平移输入的坐标,如下代码
lons, lats = m.shiftdata(lon, lat)
m.plot(lons, lats, color="blue", latlon=True, marker='.', linestyle='None')
我正在尝试绘制卫星地面轨道。我有一个以度为单位的纬度和经度列表。经度值都在 -180 到 +180 度之间。我的第一个问题是使用 latlon
关键字(顺便说一句,我在 Julia 中通过 PyCall.jl
包使用它,所以请原谅看起来很奇怪的语法):
map = Basemap.Basemap(projection="mill",lon_0=0)
map[:drawcoastlines]()
map[:drawparallels](-90:30:90,labels=[1,0,0,0])
map[:drawmeridians](map[:lonmin]:60:map[:lonmax]+30,labels=[0,0,0,1])
map[:plot](lon,lat,color="red",latlon=true)
这...不是应该的样子。我不太确定问题出在哪里。但是,如果我先转换为地图坐标:
xx,yy = map(lon,lat)
map[:plot](xx,yy,color="red")
这要好得多,除了 经度从 +180 到 -180 的线。有什么建议可以使它看起来更好吗?
可以找到用于生成这些图的纬度、经度对(以度为单位)here。
一开始我认为这可能与Basemap
的old issue有关。但是,我认为您的问题不是由于 Basemap
,它实际上正确地处理了经度环绕,正如您所看到的,如果您只使用标记来绘制卫星地面轨道。
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x,y = m(lon, lat)
m.plot(x, y, color="red", latlon=False, marker='.', linestyle='None')
最终的解决方案是将地面轨道分成多个轨道并使用 LineCollection
绘制它们,如 here 所述。一种更简单的方法(如果您期望经度不连续):
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.basemap import Basemap
latlon_ar = np.array(latlon)
threshold = 90
idx_wrap = np.nonzero(np.abs(np.diff(latlon_ar[:,1])) > threshold)[0]+1
lon_1 = lon[:idx_wrap]
lat_1 = lat[:idx_wrap]
lon_2 = lon[idx_wrap:]
lat_2 = lat[idx_wrap:]
f = plt.figure(figsize(10,7.5))
m = Basemap(projection="mill", lon_0=0)
m.drawcoastlines()
m.drawparallels(np.arange(-90,91,30),labels=[1,0,0,0])
m.drawmeridians(np.arange(-180,181,60), labels=[0,0,0,1])
x1, y1 = m(lon_1, lat_1)
x2, y2 = m(lon_2, lat_2)
m.plot(x1, y1, color="red", latlon=False)
m.plot(x2, y2, color="blue", latlon=False)
编辑这个confirmed bug in Basemap
is responsible for the behaviour in the first example of the question, where Basemap.plot
is called directly with latitude and longitude values, having set the latlon
flag to True
. There is a solution,也就是在绘图前手动平移输入的坐标,如下代码
lons, lats = m.shiftdata(lon, lat)
m.plot(lons, lats, color="blue", latlon=True, marker='.', linestyle='None')