簡體   English   中英

有沒有辦法使用 matplotlib/cartopy 來 plot 一條長度一致的線?

[英]Is there a way to plot a line that is a consistent length using matplotlib/cartopy?

我正在使用 matplotlib 和 cartopy 繪制覆蓋在 python 地圖上的線。截至目前,我只是確定兩點的緯度/經度並在它們之間繪制一條線。 由於我正在截取這些線路的橫截面,我想找到一種方法使線路的長度相同(比如 300 公里長),無論我將它放在 map 上的哪個位置。這是否可能而無需反復試驗和設置這些點直到它們達到所需的長度?

lat1, lat2, lon1, lon2 = [34.5, 36, -100, -97] x, y = [lon1, lon2], [lat1, lat2]

ax1.plot(x, y, color="black", marker="o", zorder=3, transform = ccrs.PlateCarree(), 線寬 = 2.5)

以下是我現在使用的代碼的相關部分。 這行得通,但我正在尋找一種方法來保持線長度不變,而不是更改“lat1、lat2、lon1、lon2”處端點的值。 我設想設置一條線長、一個中點(緯度/經度)和一個圍繞該點的角度 pivot。 我不知道這是否可能,但這就是我想象它必須工作的方式!

橫截面將穿過的線示例

來自pyprojGeod class 對於這些類型的操作非常方便。 下面的示例根據方位角和距離(以米為單位)從給定的緯度/經度沿直線移動。

既然你提到從中點開始,你可以為每個方向做兩次以獲得完整的線。

在下面的示例中,我只是檢索端點並使用 Cartopy ( ccrs.Geodetic() ) 對大圓進行插值。 但您也可以使用相同的 Geod object( 請參閱 npts 方法)自己執行此操作,並沿直線采樣給定數量的點。 例如,如果您需要這些坐標來提取數據,后者可能會很方便。

import matplotlib.pyplot as plt
import cartopy.crs as ccrs
from pyproj import Geod
import numpy as np

# start with a random point
np.random.seed(0)
lon = np.random.randint(-180,180)
lat  = np.random.randint(-90,90)

# and a random direction and distance
half_width = (1 + np.random.rand()) * 5000000 # meters
azimuth = np.random.randint(0,360)

# calculate the end points
geod = Geod(ellps="WGS84")
lon_end1, lat_end1, azi_rev1 = geod.fwd(lon, lat, azimuth, half_width)
lon_end2, lat_end2, azi_rev2 = geod.fwd(lon, lat, azimuth-180, half_width)

# visualize the result
fig, ax = plt.subplots(
    figsize=(8,4), dpi=86, layout="compressed", facecolor="w", 
    subplot_kw=dict(projection=ccrs.PlateCarree()),
)

ax.set_title(f"{lon=}, {lat=}, {azimuth=}, {half_width=:1.1f}m")
ax.plot(
    [lon_end1, lon, lon_end2], 
    [lat_end1, lat, lat_end2], 
    "ro-",
    transform=ccrs.Geodetic(),
)
ax.coastlines()
ax.set_global()

在此處輸入圖像描述

最簡單的方法可能是將數據重新投影到等距投影中,例如azimuthal equidistant ,然后將該點緩沖 300 公里。 你可以這樣做

import cartopy.crs as ccrs
import geopandas as gpd

point = gpd.GeoDataFrame(
    geometry=gpd.points_from_xy([-100], [34.5], crs="epsg:4326")
)

crs = ccrs.AzimuthalEquidistant(-100, 34.5)

circle = point.to_crs(crs).buffer(300000).boundary.to_crs("epsg:4326")

這將在緯度/經度空間中創建一個橢圓體點(實際距離為一個圓):

In [17]: circle.iloc[0]
Out[17]: <shapely.geometry.linestring.LineString at 0x18c3db7c0>

In [18]: circle.iloc[0].xy
Out[18]:
(array('d', [-96.73458302693649, -96.76051210175493, -96.81721890848735, -96.90389145413285, -97.0194601113924, -97.16261553916054, -97.33182721184983, -97.52536229026433, -97.74130463130324, -97.97757379088794, -98.23194392302969, -98.5020625175967, -98.78546895046141, -99.07961284313612, -99.38187224585855, -99.68957166961148, -100.0, -100.31042833038852, -100.61812775414145, -100.92038715686388, -101.21453104953859, -101.4979374824033, -101.76805607697031, -102.02242620911204, -102.25869536869676, -102.47463770973567, -102.66817278815017, -102.83738446083946, -102.98053988860761, -103.09610854586715, -103.18278109151265, -103.23948789824507, -103.26541697306351, -103.26003093177158, -103.22308261845816, -103.15462889147989, -103.05504203609833, -102.92501821713451, -102.7655823598689, -102.57808885099398, -102.3642174900262, -102.12596419991539, -101.86562612586265, -101.58578091250277, -101.28926014666801, -100.97911717692438, -100.65858975917035, -100.33105821410338, -100.0, -99.66894178589662, -99.34141024082963, -99.02088282307564, -98.710739853332, -98.41421908749726, -98.13437387413735, -97.87403580008461, -97.63578250997378, -97.42191114900605, -97.23441764013111, -97.07498178286552, -96.94495796390169, -96.84537110852011, -96.77691738154184, -96.73996906822842, -96.73458302693649]),
 array('d', [34.45635448578617, 34.191923718769814, 33.930839345631036, 33.67556892797355, 33.42850443127362, 33.191942126948454, 32.96806390193457, 32.75892001047773, 32.566413289704464, 32.39228485200862, 32.23810126231687, 32.105243205881486, 31.99489565146612, 31.90803951485474, 31.845444827911535, 31.80766541851577, 31.795035106337213, 31.80766541851577, 31.845444827911535, 31.90803951485474, 31.99489565146612, 32.105243205881486, 32.23810126231687, 32.392284852008615, 32.566413289704464, 32.75892001047773, 32.96806390193457, 33.191942126948454, 33.42850443127362, 33.67556892797355, 33.93083934563104, 34.191923718769814, 34.45635448578617, 34.72160994100843, 34.985136962504626, 35.244374905489536, 35.49678051263328, 35.739853647811024, 35.97116361010222, 36.18837573214065, 36.38927791396905, 36.57180669376817, 36.73407241410168, 36.874383010755274, 36.99126593481258, 37.08348772070849, 37.15007073604399, 37.19030669398129, 37.20376657546522, 37.19030669398129, 37.15007073604399, 37.08348772070849, 36.99126593481258, 36.87438301075528, 36.73407241410169, 36.57180669376818, 36.38927791396906, 36.18837573214065, 35.97116361010222, 35.739853647811024, 35.496780512633286, 35.244374905489536, 34.98513696250464, 34.72160994100843, 34.45635448578617]))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM