用 folium 将航向绘制到对象上

plot heading direction with folium onto an object

我用以下数据绘制了热图。

我有几千行。它只是一个样本。我还想查看该坐标的 google 地图视图。所以我做了这样的事情。

import folium
from folium.plugins import HeatMap
from folium.plugins import FastMarkerCluster


default_location=[11.1657, 45.4515]
m = folium.Map(location=default_location, zoom_start=13)


heat_data = [[row['lat'],row['lon']] for index, row in test.iterrows()]

# Plot it on the map
HeatMap(heat_data).add_to(m)

callback = ('function (row) {' 
                'var marker = L.marker(new L.LatLng(row[0], row[1]), {color: "red"});'
                'var icon = L.AwesomeMarkers.icon({'
                "icon: 'info-sign',"
                "iconColor: 'white',"
                "markerColor: 'green',"
                "prefix: 'glyphicon',"
                "extraClasses: 'fa-rotate-0'"
                    '});'
                'marker.setIcon(icon);'
                "var popup = L.popup({maxWidth: '300'});"
                "const display_text = {text1: row[0], text2: row[1]};"
                "var mytext = $(`<div id='mytext' class='display_text' style='width: 100.0%; height: 100.0%;'>\
                <a href=https://https://www.google.com/maps?ll=${display_text.text1},${display_text.text2} target='_blank'>Open Google Maps</a></div>`)[0];"
                "popup.setContent(mytext);"
                "marker.bindPopup(popup);"
                'return marker};')
            
m.add_child(FastMarkerCluster(heat_data, callback=callback))


# Display the map
m

现在我想为每个 gps 坐标绘制 一个小箭头几个小箭头箭头heading_direction 的角度,如果可能的话显示 distance_of_item从gps坐标的那个角度。预期的结果可能是这样的。

上图中,位置指针是gps坐标,方向和角度根据航向角,画出一个小星星就是目标。该对象应放置在数据集中提到的距离(以米为单位)处。我不确定如何实现。欢迎任何线索或建议。谢谢!

  • 假设您的样本数据是图像,使用备用 GPS 数据(英国医院)然后添加距离和方向列作为随机值
  • 给定的要求是在距离和方向定义的位置绘制标记,第一步是计算其 GPS 坐标。
    1. 使用 UTM CRS 使距离有意义
    2. 用高中数学在UTM CRS
    3. 中计算xy
    4. 将 CRS 转换回 WSG 84 以便具有 GPS 坐标
  • 您已将问题标记为 plotly 所以我使用 mapbox 线和散点图来演示构建平铺地图
  • 样本数据为1200+家医院,表现不错
  • geopandas 数据框也可用于构建 folium 瓦片/标记。关键步骤是计算 GPS 坐标
import geopandas as gpd
import pandas as pd
import numpy as np
import shapely
import math
import plotly.express as px
import plotly.graph_objects as go
import io, requests
# get some public addressess - hospitals.  data that has GPS lat / lon
dfhos = pd.read_csv(io.StringIO(requests.get("http://media.nhschoices.nhs.uk/data/foi/Hospital.csv").text),
    sep="¬",engine="python",).loc[:, ["OrganisationName", "Latitude", "Longitude"]]

# debug with fewer records
# df = dfhos.loc[0:500]
df = dfhos

# to use CRS transformations use geopandas, initial data is WSG 84, transform to UTM geometry
# directions and distances are random
gdf = gpd.GeoDataFrame(
    data=df.assign(
        heading_direction=lambda d: np.random.randint(0, 360, len(d)),
        distance_of_item=lambda d: np.random.randint(10 ** 3, 10 ** 4, len(d)),
    ),
    geometry=df.loc[:, ["Longitude", "Latitude"]].apply(
        lambda r: shapely.geometry.Point(r["Longitude"], r["Latitude"]), axis=1
    ),
    crs="EPSG:4326",
).pipe(lambda d: d.to_crs(d.estimate_utm_crs()))

# standard high school geometry...
def new_point(point, d, alpha):
    alpha = math.radians(alpha)
    return shapely.geometry.Point(
        point.x + (d * math.cos(alpha)),
        point.y + (d * math.sin(alpha)),
    )

# calculate points based on direction and distance in UTM CRS.  Then convert back to WSG 84 CRS
gdf["geometry2"] = gpd.GeoSeries(
    gdf.apply(
        lambda r: new_point(
            r["geometry"], r["distance_of_item"], r["heading_direction"]
        ),
        axis=1,
    ),
    crs=gdf.geometry.crs,
).to_crs("EPSG:4326")
gdf = gdf.to_crs("EPSG:4326")


# plot lines to show start point and direct.  plot markers of destinations for text of distance, etc
fig = px.line_mapbox(
    lon=np.stack(
        [gdf.geometry.x.values, gdf.geometry2.x.values, np.full(len(gdf), np.nan)],
        axis=1,
    ).reshape([1, len(gdf) * 3])[0],
    lat=np.stack(
        [gdf.geometry.y.values, gdf.geometry2.y.values, np.full(len(gdf), np.nan)],
        axis=1,
    ).reshape([1, len(gdf) * 3])[0],
).add_traces(
    px.scatter_mapbox(
        gdf,
        lat=gdf.geometry2.y,
        lon=gdf.geometry2.x,
        hover_data=["distance_of_item", "OrganisationName"],
    ).data
)
# c = gdf.loc[]
fig.update_layout(mapbox={"style": "open-street-map", "zoom": 8, 'center': {'lat': 52.2316838387109, 'lon': -1.4577750831062155}}, margin={"l":0,"r":0,"t":0,"r":0})