geo_line_to_s2cells()
计算覆盖地球上的一条或多条线的 S2 单元格令牌。 此函数是一种有用的地理空间加入工具。
详细了解 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 |