Построение дорожек GeoJSON по линии данных без ошибочных линий с помощью Картографии

#python-3.x #geojson #geopandas #cartopy

Вопрос:

Я создаю карту мира с дорожками судов, предоставленными в GeoJSON — когда дорожка пересекает линию 180/-180, я получаю ошибочную линию по всему миру. Чтобы упростить вещи, я сократил количество дорожек.файл json в единственную дорожку, но обычный файл содержит несколько дорожек корабля.

Затем участок сохраняется в виде карты мира без границ с разрешением 4000×2000 пикселей — см.:

https://www.oceanic.udel.edu/globaldataview/rt_content/ships/latest/ship_locations.jpg

Графическое изображение, показывающее отклоняющуюся линию

 import os
import matplotlib as mpl
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
import geopandas as gpd

def main():

    tracks = gpd.read_file('https://www.researchvessels.org/data/tracks.json')

    fig = plt.figure(dpi=100, figsize=(40, 20), frameon=False)
    plt.axis('off')
    ax = fig.add_subplot(1, 1, 1, projection=ccrs.PlateCarree())
    ax.set_extent([-180, 180, -90, 90], ccrs.PlateCarree())
    ax.set_axis_off()
    tracks.plot(ax=ax, color="yellow")
    fig.add_axes(ax)
    # Background Image below is available via https://www.researchvessels.org/data/nasa_bm_default.jpg
    img = plt.imread('c:/scripts/NASA_BM_default.jpg')
    img_extent = (-180, 180, -90, 90)
    ax.imshow(img, origin='upper', extent=img_extent, transform=ccrs.PlateCarree(), aspect='auto')
    fig.subplots_adjust(bottom = 0)
    fig.subplots_adjust(top = 1)
    fig.subplots_adjust(right = 1)
    fig.subplots_adjust(left = 0)
    plt.show()
    plt.close(fig)
 

Ответ №1:

Чтобы правильно отобразить дорожки, вам необходимо очистить значения longitude в дорожках, пересекающих линию даты.

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

def sanitize_lonlist(lons):
    new_list = []
    oldval = 0
    # used to compare with the adjacent longitudes
    # and values exceed, disconnect linestring
    treshold = 10   
    for ix,ea in enumerate(lons):
        diff = oldval - ea
        if (ix>0):
            if (diff>treshold):
                ea = ea 360
        oldval = ea
        new_list.append(ea)
    return new_list

tracks = gpd.read_file('https://www.researchvessels.org/data/tracks.json')
# grab x and y of the first geometry object
xs = tracks.geometry[0].xy[0]
ys = tracks.geometry[0].xy[1]

ax = plt.axes(projection=ccrs.PlateCarree()) 
ax.set_global() 
ax.coastlines()

# plot the geometry using sanitized values
ax.plot(sanitize_lonlist(xs), ys, transform=ccrs.PlateCarree(), color='red', lw=3)
plt.show()
 

Выход:

след судна