geo_polygon_to_s2cells()

計算在地球上涵蓋多邊形或 Multipolygon 的 S2 資料格標記。 此函式是實用的地理空間聯結工具。

Syntax

geo_polygon_to_s2cells(多邊形 [level[,,radius]])

深入瞭解 語法慣例

參數

名稱 類型 必要 Description
多邊形 dynamic ✔️ GeoJSON 格式的多邊形或多多邊形。
level int 定義要求的儲存格層級。 支援的值位於 [0, 30] 範圍中。 如果未指定,則會使用預設值 11
半徑 real 以公尺為單位的緩衝區半徑。 如果未指定,則會使用預設值 0

傳回

涵蓋多邊形或多多邊形的 S2 單元格標記字串陣列。 如果radius設定為正值,則除了輸入圖形之外,也會是輸入幾何半徑內所有點的涵蓋範圍。 如果多邊形、層級、半徑無效,或單元格計數超過限制,則查詢會產生 Null 結果。

注意

  • 使用 S2 儲存格權杖來涵蓋多邊形,可在比對多邊形的座標 (可能包含這些座標和配對多邊形) 時使用。
  • 涵蓋權杖的多邊形屬於相同的 S2 資料格層級。
  • 每個多邊形的權杖數目上限為 65536。
  • 用來測量地球的大地座標基準是球體。 多邊形邊緣是球體上的測地線
  • 如果輸入多邊形邊緣是直笛卡兒線,請考慮使用 geo_polygon_densify(),以將平面邊緣轉換為測地線。

使用 S2 儲存格權杖來涵蓋多邊形的動機

如果沒有此函式,我們可以使用下列其中一種方法,將座標分類為包含這些座標的多邊形。

let Polygons = 
    datatable(description:string, polygon:dynamic)
    [  
      "New York",  dynamic({"type":"Polygon","coordinates":[[[-73.85009765625,40.85744791303121],[-74.16046142578125,40.84290487729676],[-74.190673828125,40.59935608796518],[-73.83087158203125,40.61812224225511],[-73.85009765625,40.85744791303121]]]}),
      "Seattle",   dynamic({"type":"Polygon","coordinates":[[[-122.200927734375,47.68573021131587],[-122.4591064453125,47.68573021131587],[-122.4755859375,47.468949677672484],[-122.17620849609374,47.47266286861342],[-122.200927734375,47.68573021131587]]]}),
      "Las Vegas", dynamic({"type":"Polygon","coordinates":[[[-114.9,36.36],[-115.4498291015625,36.33282808737917],[-115.4498291015625,35.84453450421662],[-114.949951171875,35.902399875143615],[-114.9,36.36]]]}),
    ];
let Coordinates = 
    datatable(longitude:real, latitude:real)
    [
      real(-73.95),  real(40.75), // New York
      real(-122.3),  real(47.6),  // Seattle
      real(-115.18), real(36.16)  // Las Vegas
    ];
Polygons | extend dummy=1
| join kind=inner (Coordinates | extend dummy=1) on dummy
| where geo_point_in_polygon(longitude, latitude, polygon)
| project longitude, latitude, description

輸出

經度 (longitude) 緯度 (latitude) description
-73.95 40.75 紐約
-122.3 47.6 西雅圖
-115.18 36.16 拉斯維加斯

雖然此方法在某些情況下運作,但效率不佳。 這個方法會進行交叉聯結,這表示其會嘗試比對每個多邊形的每個點。 此程式會耗用大量的記憶體和計算資源。 相反地,我們想要將每個多邊形對應到具有最大內含專案成功機率的點,並篩選掉其他點。

這項比對可透過下列程式來達成:

  1. 將多邊形轉換成層級 k 的 S2 儲存格,
  2. 將點轉換成相同的 S2 資料格層級 k,
  3. 加入 S2 資料格,
  4. geo_point_in_polygon() 篩選。 如果某些誤判是正常的,可以省略這個階段。 最大錯誤會是層級 k 超出多邊形界限的 s2 單元格區域。

選擇 S2 資料格層級

  • 在理想的情況下,我們會想要使用一或多個唯一的儲存格來涵蓋每個多邊形,使兩個多邊形不會共用相同的資料格。
  • 如果多邊形彼此距離相近,請選擇 S2 資料格層級,使其資料格邊緣 (4、8、12 倍) 小於平均多邊形的邊緣。
  • 如果多邊形彼此遠,請選擇 S2 單元格層級 ,使其儲存格邊緣類似或大於平均多邊形的邊緣。
  • 實際上,涵蓋超過10,000個單元格的多邊形可能不會產生良好的效能。
  • 範例使用案例:
  • S2 單元格層級 5 可能證明適合涵蓋國家/地區。
  • S2 儲存格層級 16 可以涵蓋密集且相對較小的曼哈頓 (紐約) 臨近地區。
  • S2 資料格層級 11 可以用來涵蓋澳洲市郊。
  • 查詢運行時間和記憶體耗用量可能會因為不同的 S2 數據格層級值而有很大的差異。

警告

涵蓋具有小型區域儲存格的大型區域多邊形,可能會導致大量的涵蓋儲存格。 因此,查詢可能會傳回 Null。

注意

效能改進建議:

  • 可能的話,請在聯結之前減少座標數據表大小,方法是使用 地理空間叢集 來分組非常接近的座標,或因為數據或業務需求的本質而篩選掉不想要的座標。
  • 可能的話,請減少多邊形計數,因為數據或商務需求的性質。 在聯結之前篩選掉不必要的多邊形、範圍限定於感興趣的區域或統一多邊形。
  • 如果是非常大的多邊形,請使用 geo_polygon_simplify () 來減少其大小。
  • 變更 S2 資料格層級可能會改善效能和記憶體耗用量。
  • 變更 聯結種類和提示 可能會改善效能和記憶體耗用量。
  • 如果設定正半徑,您可以嘗試使用 geo_polygon_buffer () 在緩衝圖形上還原為半徑 0 來改善效能。

範例

下列範例會將座標分類為多邊形。

let Polygons = 
    datatable(description:string, polygon:dynamic)
    [
        'Greenwich Village', dynamic({"type":"Polygon","coordinates":[[[-73.991460000000131,40.731738000000206],[-73.992854491775518,40.730082566051351],[-73.996772,40.725432000000154],[-73.997634685522883,40.725786309886963],[-74.002855946639244,40.728346630056791],[-74.001413,40.731065000000207],[-73.996796995070824,40.73736378205173],[-73.991724524037934,40.735245208931886],[-73.990703782359589,40.734781896080477],[-73.991460000000131,40.731738000000206]]]}),
        'Upper West Side',   dynamic({"type":"Polygon","coordinates":[[[-73.958357552055688,40.800369095633819],[-73.98143901556422,40.768762584141953],[-73.981548752788598,40.7685590292784],[-73.981565335901905,40.768307084720796],[-73.981754418060945,40.768399727738668],[-73.982038573548124,40.768387823012056],[-73.982268248204349,40.768298621883247],[-73.982384797518051,40.768097213086911],[-73.982320919746599,40.767894461792181],[-73.982155532845766,40.767756204474757],[-73.98238873834039,40.767411004834273],[-73.993650353659021,40.772145571634361],[-73.99415893763998,40.772493009137818],[-73.993831082030937,40.772931787850908],[-73.993891252437052,40.772955194876722],[-73.993962585514595,40.772944653908901],[-73.99401262480508,40.772882846631894],[-73.994122058082397,40.77292405902601],[-73.994136652588594,40.772901870174394],[-73.994301342391154,40.772970028663913],[-73.994281535134448,40.77299380206933],[-73.994376552751078,40.77303955110149],[-73.994294029824005,40.773156243992048],[-73.995023275860802,40.773481196576356],[-73.99508939189289,40.773388475039134],[-73.995013963716758,40.773358035426909],[-73.995050284699261,40.773297153189958],[-73.996240651898916,40.773789791397689],[-73.996195837470992,40.773852356184044],[-73.996098807369748,40.773951805299085],[-73.996179459973888,40.773986954351571],[-73.996095245226442,40.774086186437756],[-73.995572265161172,40.773870731394297],[-73.994017424135961,40.77321375261053],[-73.993935876811335,40.773179512586211],[-73.993861942928888,40.773269531698837],[-73.993822393527211,40.773381758622882],[-73.993767019318497,40.773483981224835],[-73.993698463744295,40.773562141052594],[-73.993358326468751,40.773926888327956],[-73.992622663865575,40.774974056037109],[-73.992577842766124,40.774956016359418],[-73.992527743951555,40.775002110439829],[-73.992469745815342,40.775024159551755],[-73.992403837191887,40.775018140390664],[-73.99226708903538,40.775116033858794],[-73.99217809026365,40.775279293897171],[-73.992059084937338,40.775497598192516],[-73.992125372394938,40.775509075053385],[-73.992226867797001,40.775482211026116],[-73.992329346608813,40.775468900958522],[-73.992361756801131,40.775501899766638],[-73.992386042960277,40.775557180424634],[-73.992087684712729,40.775983970821372],[-73.990927174149746,40.777566878763238],[-73.99039616003671,40.777585065679204],[-73.989461267506471,40.778875124584417],[-73.989175778438053,40.779287524015778],[-73.988868617400072,40.779692922911607],[-73.988871874499793,40.779713738253008],[-73.989219022880576,40.779697895209402],[-73.98927785904425,40.779723439271038],[-73.989409054180143,40.779737706471963],[-73.989498614927044,40.779725044389757],[-73.989596493388234,40.779698146683387],[-73.989679812902509,40.779677568658038],[-73.989752702937935,40.779671244211556],[-73.989842247806507,40.779680752670664],[-73.990040102120489,40.779707677698219],[-73.990137977524839,40.779699769704784],[-73.99033584033225,40.779661794394983],[-73.990430598697046,40.779664973055503],[-73.990622199396725,40.779676064914298],[-73.990745069505479,40.779671328184051],[-73.990872114282197,40.779646007643876],[-73.990961672224358,40.779639683751753],[-73.991057472829539,40.779652352625774],[-73.991157429497036,40.779669775606465],[-73.991242817404469,40.779671367084504],[-73.991255318289745,40.779650782516491],[-73.991294887120119,40.779630209208889],[-73.991321967649895,40.779631796041372],[-73.991359455569423,40.779585883337383],[-73.991551059227476,40.779574821437407],[-73.99141982585985,40.779755280287233],[-73.988886144117032,40.779878898532999],[-73.988939656706265,40.779956178440393],[-73.988926103530844,40.780059292013632],[-73.988911680264692,40.780096037146606],[-73.988919261468567,40.780226094343945],[-73.988381050202634,40.780981074045783],[-73.988232413846987,40.781233144215555],[-73.988210420831663,40.781225482542055],[-73.988140000000143,40.781409000000224],[-73.988041288067166,40.781585961353777],[-73.98810029382463,40.781602878305286],[-73.988076449145055,40.781650935001608],[-73.988018059972219,40.781634188810422],[-73.987960792842145,40.781770987031535],[-73.985465811970457,40.785360700575431],[-73.986172704965611,40.786068452258647],[-73.986455862401996,40.785919219081421],[-73.987072345615601,40.785189638820121],[-73.98711901394276,40.785210319004058],[-73.986497781023601,40.785951202887254],[-73.986164628806279,40.786121882448327],[-73.986128422486075,40.786239001331111],[-73.986071135219746,40.786240706026611],[-73.986027274789123,40.786228964236727],[-73.986097637849426,40.78605822569795],[-73.985429321269592,40.785413942184597],[-73.985081137732209,40.785921935110366],[-73.985198833254501,40.785966552197777],[-73.985170502389906,40.78601333415817],[-73.985216218673656,40.786030501816427],[-73.98525509797993,40.785976205511588],[-73.98524273937646,40.785972572653328],[-73.98524962933017,40.785963139855845],[-73.985281779186749,40.785978620950075],[-73.985240032884533,40.786035858136792],[-73.985683885242182,40.786222123919686],[-73.985717529004575,40.786175994668795],[-73.985765660297687,40.786196274858618],[-73.985682871922691,40.786309786213067],[-73.985636270930442,40.786290150649279],[-73.985670722564691,40.786242911993817],[-73.98520511880038,40.786047669212785],[-73.985211035607492,40.786039554883686],[-73.985162639946992,40.786020999769754],[-73.985131636312062,40.786060297019972],[-73.985016964065125,40.78601423719563],[-73.984655078830457,40.786534741807841],[-73.985743787901043,40.786570082854738],[-73.98589227228328,40.786426529019593],[-73.985942854994988,40.786452847880334],[-73.985949561556794,40.78648711396653],[-73.985812373526713,40.786616865357047],[-73.985135209703174,40.78658761889551],[-73.984619428584324,40.786586016349787],[-73.981952458164173,40.790393724337193],[-73.972823037363767,40.803428052816756],[-73.971036786332192,40.805918478839672],[-73.966701,40.804169000000186],[-73.959647,40.801156000000113],[-73.958508540159471,40.800682279767472],[-73.95853274080838,40.800491362464697],[-73.958357552055688,40.800369095633819]]]}),
        'Upper East Side',   dynamic({"type":"Polygon","coordinates":[[[-73.943592454622546,40.782747908206574],[-73.943648235390199,40.782656161333449],[-73.943870759887162,40.781273026571704],[-73.94345932494096,40.780048275653243],[-73.943213862652243,40.779317588660199],[-73.943004239504688,40.779639495474292],[-73.942716005450905,40.779544169476175],[-73.942712374762181,40.779214856940001],[-73.942535563208608,40.779090956062532],[-73.942893408188027,40.778614093246276],[-73.942438481745029,40.777315235766039],[-73.942244919522594,40.777104088947254],[-73.942074188038887,40.776917846977142],[-73.942002667222781,40.776185317382648],[-73.942620205199006,40.775180871576474],[-73.94285645694552,40.774796600349191],[-73.94293043781397,40.774676268036011],[-73.945870899588215,40.771692257932997],[-73.946618690150586,40.77093339256956],[-73.948664164778933,40.768857624399587],[-73.950069793030679,40.767025088383498],[-73.954418260786071,40.762184104951245],[-73.95650786241211,40.760285256574043],[-73.958787773424007,40.758213471309809],[-73.973015157270069,40.764278692864671],[-73.955760332998182,40.787906554459667],[-73.944023,40.782960000000301],[-73.943592454622546,40.782747908206574]]]}),
    ];
let Coordinates = 
    datatable(longitude:real, latitude:real)
    [
        real(-73.9741), 40.7914, // Upper West Side
        real(-73.9950), 40.7340, // Greenwich Village
        real(-73.9584), 40.7688, // Upper East Side
    ];
let Level = 16;
Polygons
| extend covering = geo_polygon_to_s2cells(polygon, Level) // cover every polygon with s2 cell token array
| mv-expand covering to typeof(string)                     // expand cells array such that every row will have one cell mapped to its polygon
| join kind=inner hint.strategy=broadcast                  // assume that Polygons count is small (In some specific case)
(
    Coordinates
    | extend covering = geo_point_to_s2cell(longitude, latitude, Level) // cover point with cell
) on covering // join on the cell, this filters out rows of point and polygons where the point definitely does not belong to the polygon
| where geo_point_in_polygon(longitude, latitude, polygon) // final filtering for exact result
| project longitude, latitude, description

輸出

經度 (longitude) 緯度 (latitude) description
-73.9741 40.7914 上西區
-73.995 40.734 格林威治村
-73.9584 40.7688 上東區

以下是上述查詢的更改善。 計算每個美國州/省的 Storm 事件。 下列查詢會執行非常有效率的聯結,因為它不會透過聯結攜帶多邊形,並使用 查閱運算符

let Level = 6;
let polygons = materialize(
    US_States
    | project StateName = tostring(features.properties.NAME), polygon = features.geometry, id = new_guid());
let tmp = 
    polygons
    | project id, covering = geo_polygon_to_s2cells(polygon, Level) 
    | mv-expand covering to typeof(string)
    | join kind=inner hint.strategy=broadcast
            (
                StormEvents
                | project lng = BeginLon, lat = BeginLat
                | project lng, lat, covering = geo_point_to_s2cell(lng, lat, Level)
            ) on covering
    | project-away covering, covering1;
tmp | lookup polygons on id
| project-away id
| where geo_point_in_polygon(lng, lat, polygon)
| summarize StormEventsCountByState = count() by StateName

輸出

StateName StormEventsCountByState
Florida 960
喬治亞 1085
... ...

下列範例會篩選出不相交於感興趣多邊形區域的多邊形。 最大錯誤是 s2cell 長度的對角線。 這個範例是以夜間點陣檔案的多邊形地球為基礎。

let intersection_level_hint = 7;
let area_of_interest = dynamic({"type": "Polygon","coordinates": [[[-73.94966125488281,40.79698248639272],[-73.95841598510742,40.800426144169315],[-73.98124694824219,40.76806170936614],[-73.97283554077148,40.7645513650551],[-73.94966125488281,40.79698248639272]]]});
let area_of_interest_covering = geo_polygon_to_s2cells(area_of_interest, intersection_level_hint);
EarthAtNight
| project value = features.properties.DN, polygon = features.geometry
| extend covering = geo_polygon_to_s2cells(polygon, intersection_level_hint)
| mv-apply c = covering to typeof(string) on
(
    summarize is_intersects = take_anyif(1, array_index_of(area_of_interest_covering, c) != -1)
)
| where is_intersects == 1
| count

輸出

Count
83

為了涵蓋具有層級 5 之 S2 資料格的某個多邊形所需的儲存格計數。

let polygon = dynamic({"type":"Polygon","coordinates":[[[0,0],[0,50],[100,50],[0,0]]]});
print s2_cell_token_count = array_length(geo_polygon_to_s2cells(polygon, 5));

輸出

s2_cell_token_count
286

涵蓋具有小型區域儲存格的大型區域多邊形會傳回 Null。

let polygon = dynamic({"type":"Polygon","coordinates":[[[0,0],[0,50],[100,50],[0,0]]]});
print geo_polygon_to_s2cells(polygon, 30);

輸出

print_0

涵蓋具有小型區域儲存格的大型區域多邊形會傳回 Null。

let polygon = dynamic({"type":"Polygon","coordinates":[[[0,0],[0,50],[100,50],[0,0]]]});
print isnull(geo_polygon_to_s2cells(polygon, 30));

輸出

print_0
1