【问题标题】:Plot LINESTRING Z from GeoDataFrame using pydeck's PathLayer (or TripLayer)使用 pydeck 的 PathLayer(或 TripLayer)从 GeoDataFrame 绘制 LINESTRING Z
【发布时间】:2021-11-17 04:49:14
【问题描述】:

我有一个带有 LINESTRING Z 几何图形的地理数据框:

TimeUTC Latitude Longitude AGL geometry
0 2021-06-16 00:34:04+00:00 42.8354 -70.9196 82.2 LINESTRING Z (42.83541343273769 -70.91961015378617 82.2, 42.83541343273769 -70.91961015378617 82.2)
1 2021-06-14 13:32:18+00:00 42.8467 -70.8192 66.3 LINESTRING Z (42.84674080836037 -70.81919357049679 66.3, 42.84674080836037 -70.81919357049679 66.3)
2 2021-06-18 23:56:05+00:00 43.0788 -70.7541 0.9 LINESTRING Z (43.07882882269921 -70.75414567194126 0.9, 43.07884601143309 -70.75416286067514 0, 43.07885174101104 -70.75416286067514 0, 43.07884028185512 -70.75415713109717 0, 43.07884601143309 -70.75414567194126 0, 43.07884601143309 -70.75414567194126 0)

我可以使用 pydeck 的 ScatterplotLayer 使用 raw 绘制组件点 (不是地理)数据框,但我还需要绘制完整、平滑的轨迹。

我试过了:

        layers = [ 
pdk.Layer(
    type = "PathLayer",
    data=tracks,
    get_path="geometry",
    width_scale=20,
    width_min_pixels=5,
    get_width=5,
    get_color=[180, 0, 200, 140],
    pickable=True,
    ),
]
view_state = pdk.ViewState(
    latitude=gdf_polygon.centroid.x,
    longitude=gdf_polygon.centroid.y,
    zoom=6,
    min_zoom=5,
    max_zoom=15,
    pitch=40.5,
    bearing=-27.36)

r = pdk.Deck(layers=[layers], initial_view_state=view_state)
return(r)

静默失败。尽我所能,我找不到转换的方法 LINESTRING Z(如果需要,我可以不使用 Z 组件)到对象 pydeck 会接受。

【问题讨论】:

    标签: geopandas pydeck


    【解决方案1】:

    我找到了一种从 GeoPandas 中提取所需信息并使其在 pydeck 中工作的方法。您只需要 apply 一个从 shapely 几何图形中提取坐标作为列表的函数。这是一个完全可重现的示例:

    import shapely
    import numpy as np
    import pandas as pd
    import pydeck as pdk
    import geopandas as gpd
    
    
    linestring_a = shapely.geometry.LineString([[0,1,2],
                                                [3,4,5],
                                                [6,7,8]])
    
    linestring_b = shapely.geometry.LineString([[7,15,1],
                                                [8,14,2],
                                                [9,13,3]])
    
    multilinestring = shapely.geometry.MultiLineString([[[10,11,2],
                                                         [13,14,5],
                                                         [16,17,8]],
                                                        [[19,10,11],
                                                         [12,15,4],
                                                         [10,13,0]]])
    
    
    
    gdf = gpd.GeoDataFrame({'id':[1,2,3],
                            'geometry':[linestring_a,
                                        linestring_b,
                                        multilinestring],
                            'color_hex':['#ed1c24',
                                         '#faa61a',
                                         '#ffe800']})
    
    # Function that transforms a hex string into an RGB tuple.
    def hex_to_rgb(h):
        h = h.lstrip("#")
        return tuple(int(h[i : i + 2], 16) for i in (0, 2, 4))
    
    # Applying the HEX-to-RGB function above
    gdf['color_rgb'] = gdf['color_hex'].apply(hex_to_rgb)
    
    # Function that extracts the 2d list of coordinates from an input geometry
    def my_geom_coord_extractor(input_geom):
        if (input_geom is None) or (input_geom is np.nan):
            return []
        else:
            if input_geom.type[:len('multi')].lower() == 'multi':
                full_coord_list = []
                for geom_part in input_geom.geoms:
                    geom_part_2d_coords = [[coord[0],coord[1]] for coord in list(geom_part.coords)]
                    full_coord_list.append(geom_part_2d_coords)
            else:
                full_coord_list = [[coord[0],coord[1]] for coord in list(input_geom.coords)]
            return full_coord_list
    
    # Applying the coordinate list extractor to the dataframe
    gdf['coord_list'] = gdf['geometry'].apply(my_geom_coord_extractor)
    
    gdf_polygon = gdf.unary_union.convex_hull 
    
    # Establishing the default view for the pydeck output
    view_state = pdk.ViewState(latitude=gdf_polygon.centroid.coords[0][1], 
                               longitude=gdf_polygon.centroid.coords[0][0], 
                               zoom=4)
    
    # Creating the pydeck layer
    layer = pdk.Layer(
        type="PathLayer",
        data=gdf,
        pickable=True,
        get_color='color_rgb',
        width_scale=20,
        width_min_pixels=2,
        get_path="coord_list",
        get_width=5,
    )
    
    # Finalizing the pydeck output
    r = pdk.Deck(layers=[layer], initial_view_state=view_state, tooltip={"text": "{id}"})
    r.to_html("path_layer.html")
    

    这是它产生的输出:

    大警告

    似乎 pydeck 无法处理 MultiLineString 几何图形。请注意,在上面的示例中,我的原始数据框有 3 个几何图形,但在屏幕截图中只绘制了 2 条线。

    【讨论】:

    • 这巧妙地解决了一半的问题,谢谢!不幸的是,pydeck 似乎并不喜欢 LINESTRING,就像它不喜欢 LINESTRING Z 一样。
    • 那里!我更新了代码以使其与 pydeck 的 PathLayer 方法一起使用。如果您在将我上面的示例转换为您需要的具体案例时遇到任何问题,请告诉我。
    • 非常感谢。我花了一个下午尝试各种转换,但它们要么默默地失败,要么抛出与 JSON 相关的解析错误。这行得通,效果很好,而且很清楚。据说 PathLayer 需要 3D 坐标,但改天我会担心的。非常感谢。
    • 太棒了!很高兴听到这个消息=)
    • 记好!我已经更新了上面的代码以纳入建议 =) 感谢您的提示!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-12-04
    • 1970-01-01
    • 1970-01-01
    • 2018-08-25
    • 1970-01-01
    • 1970-01-01
    • 2011-04-28
    相关资源
    最近更新 更多