geo_line_to_s2cells()

计算覆盖地球上的一条或多条线的 S2 单元格令牌。 此函数是一种有用的地理空间加入工具。

语法

geo_line_to_s2cells(lineString [,level[ ,radius]])

详细了解语法约定

参数

客户 类型​​ 必需 说明
lineString dynamic GeoJSON 格式的一条或多条直线。
level int 定义所请求的单元格级别。 支持的值范围为 [0, 30]。 如果未指定,则使用默认值 11
radius real 以米为单位的缓冲区半径。 如果未指定,则使用默认值 0

返回

覆盖一条或多条直线的 S2 单元格标记字符串数组。 如果 radius 设置为正值,那么覆盖范围将包括输入形状和输入几何图形半径内的所有点。

如果 line、level 和 radius 任一无效,或者单元格计数超出限制,则查询会返回 null 结果。

注意

  • 用 S2 单元格标记覆盖线条有助于匹配坐标与线条,从而查找附近的线点。
  • 覆盖标记的线条具有相同的 S2 单元格级别。
  • 每条线的最大标记数量为 65536。
  • 用于测量地球上的距离的大地基准是一个球体。 直线边缘是球体上的测地线
  • 如果输入直线边缘是直笛卡尔线,请考虑使用 geo_line_densify() 以便将平面边缘转换为测地线。

选择 S2 单元级别

  • 理想情况下,最好是仅用一个或少数几个独立单元格就能覆盖每条线,以避免两条线共用同一单元格。
  • 在实践中,请试着仅用少数几个单元格覆盖,不超过十二个。 使用多于 10,000 个单元格覆盖可能不会得到好的性能。
  • 查询运行时间和内存消耗可能因 S2 单元级别值的不同而产生很大差异。

性能改进建议

  • 如果可能,请在联接前减少坐标表大小,方法是使用地理空间聚类分析对彼此非常接近的坐标进行分组,或者根据数据类型或业务需求筛选掉非必需坐标。
  • 如果可能,请根据数据类型或业务需求减少线条数量。 在联接之前筛选掉不必要的线条、将范围缩小到感兴趣的区域或统一线条。
  • 如果线条很多,请使用 geo_polygon_simplify() 缩减规模。
  • 更改 S2 单元级别可能会提高性能和内存消耗。
  • 更改联接类型和提示可以提高性能和内存消耗。
  • 如果 radius 设置为正,则使用 geo_line_buffer () 将缓冲形状上的 radius 还原 0 可以提高性能。

示例

以下查询将查找街道 500 米范围内的所有地铁站,并按街道名称聚合地铁计数。

let radius = 500;
let tube_stations = datatable(tube_station_name:string, lng:real, lat: real)
[
    "St. James' Park",        -0.13451078568013486, 51.49919145858172,
     "London Bridge station", -0.08492752160134387, 51.504876316440914,
     // more points
];
let streets = datatable(street_name:string, line:dynamic)
[
    "Buckingham Palace", dynamic({"type":"LineString","coordinates":[[-0.1399656708283601,51.50190802248855],[-0.14088438832752104,51.50012082761452]]}),
    "London Bridge",    dynamic({"type":"LineString","coordinates":[[-0.087152,51.509596],[-0.088340,51.506110]]}),
    // more lines
];
let join_level = 14;
let lines = materialize(streets | extend id = new_guid());
let res = 
    lines
    | project id, covering = geo_line_to_s2cells(line, join_level, radius)
    | mv-expand covering to typeof(string)
    | join kind=inner hint.strategy=broadcast
    (
        tube_stations
        | extend covering = geo_point_to_s2cell(lng, lat, join_level)
    ) on covering;
res | lookup lines on id
| where geo_distance_point_to_line(lng, lat, line) <= radius
| summarize count = count() by name = street_name
name count
白金汉宫 1
伦敦桥 1

如果线条无效,将返回 null 结果。

let line = dynamic({"type":"LineString","coordinates":[[[0,0],[0,0]]]});
print isnull(geo_line_to_s2cells(line))
print_0
True