如何用plotly在卫星地图上绘制箭头

2024-03-24

我正在尝试用绘图在卫星视图地图上可视化风向和强度。使用 Python 工作,但我想这个问题不是特定于平台的。

下面是以前用Matlab制作的风图的截图:

这可以通过情节实现吗?我尝试查看注释,但无法让它们在地图上工作。

我尝试了如下所示的操作,但是当我添加注释时,地图停止工作:

import plotly.graph_objects as go
fig = go.Figure(go.Scattermapbox(
    mode = "lines",
    lon = [10, 20],
    lat = [10,20],
    marker = {'size': 10}))
fig.add_annotation(
    x = [10,],
    y = [10],
    xref = "x", yref = "y",
    axref = "x", ayref = "y",
    ax = [20],
    ay = [20],
    text = "",
    showarrow = True
)
fig.update_layout(
    margin ={'l':0,'t':0,'b':0,'r':0},
    mapbox = {
        'center': {'lon': 10, 'lat': 10},
        'style': "stamen-terrain",
        'center': {'lon': 10, 'lat': 10},
        'zoom': 3})

fig.show()

还努力在绘图的 Mapbox 中绘制箭头。

我使用与 @guidout 答案类似的方法来手动构建箭头,但使用单个 geojson 层(这避免了使用多个跟踪的性能问题)。

我正在使用 geojson MultiLineString 层。

geojson MultiLineString 具有以下格式(来自维基百科):

{
    "type": "MultiLineString", 
    "coordinates": [
        [[10, 10], [20, 20], [10, 40]], <-- each of this can be used to draw an arrow
        [[40, 40], [30, 30], [40, 20], [30, 10]]
    ]
}

Code:

function rotate(a, theta) {
    return [a[0]*Math.cos(theta) - a[1]*Math.sin(theta), a[0]*Math.sin(theta) + a[1]*Math.cos(theta)];
}

function createArrow(a, b) {
    // a: source point 
    // b: destination point
    var angle = Math.atan2(a[1]-b[1], a[0]-b[0]);
    var v = [b[0]-a[0], b[1]-a[1]]        // get direction vector
    var m = Math.sqrt(Math.pow(v[0], 2) + Math.pow(v[1], 2))  // module
    var u = [v[0]/m, v[1]/m]              // get unitary vector in the direction
    var k = 0.2                           // how far to place the arrow end
    var newb = [b[0]-u[0]*k, b[1]-u[1]*k] // place the arrow end a bit before the destination
    var s1 = rotate([0.02, 0.02], angle)  // "sides" of the arrow. Applied to a base vector in left direction <--, and rotated to match the correct angle
    var s2 = rotate([0.02, -0.02], angle)
    return [a, newb, [newb[0]+s1[0], newb[1]+s1[1]], newb, [newb[0]+s2[0], newb[1]+s2[1]]]
}

//...

var arrows = sourceDestinationPairs.map(x => createArrow(x[0], x[1]));

var mapboxLayer = { 
    'sourcetype': 'geojson',
    'source': {
        "type": "MultiLineString", 
        "coordinates": arrows
    },
    'below': '', 'type': 'line', 
    'color': 'grey', 'opacity': 1, 
    'line': {'width': 2}
}
layout.mapbox.layers.push(mapboxLayer)

// ...

Plotly.plot('mapDiv', data, layout)

缺点:

  • 必须手动构建箭头
  • 缩放也会缩放箭头
  • 箭头中存在轻微变形,具体取决于投影如何缩放经度与纬度坐标比(默认 Mapbox 墨卡托投影可接受)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何用plotly在卫星地图上绘制箭头 的相关文章

随机推荐