Sdílet prostřednictvím


geo_polygon_to_s2cells()

Vypočítá tokeny buněk S2, které pokrývají mnohoúhelník nebo multipolygon na Zemi. Tato funkce je užitečný nástroj pro geoprostorové spojení.

Přečtěte si další informace o hierarchii buněk S2.

Syntaxe

geo_polygon_to_s2cells(mnohoúhelník [, úroveň[, poloměr]])

Přečtěte si další informace o konvencích syntaxe.

Parametry

Název Type Požadováno Popis
mnohoúhelník dynamic ✔️ Mnohoúhelník nebo multipolygon ve formátu GeoJSON.
úroveň int Definuje požadovanou úroveň buňky. Podporované hodnoty jsou v rozsahu [0, 30]. Pokud není zadáno, použije se výchozí hodnota 11 .
poloměr real Poloměr vyrovnávací paměti v metrech. Pokud není zadáno, použije se výchozí hodnota 0 .

Návraty

Pole řetězců tokenů buněk S2, které pokrývají mnohoúhelník nebo multipolygon. Pokud je poloměr nastaven na kladnou hodnotu, kryt bude kromě vstupního tvaru všechny body v poloměru vstupní geometrie. Pokud je mnohoúhelník, úroveň, poloměr neplatný nebo počet buněk překročí limit, dotaz vytvoří výsledek null.

Poznámka:

  • Pokrytí mnohoúhelníku s tokeny buněk S2 může být užitečné při porovnávání souřadnic s mnohoúhelníky, které mohou zahrnovat tyto souřadnice a odpovídající mnohoúhelníky s mnohoúhelníky.
  • Mnohoúhelník překrývající tokeny mají stejnou úroveň buněk S2.
  • Maximální počet tokenů na mnohoúhelník je 65536.
  • Geodetické datum používané pro měření na Zemi je sféra. Polygonové hrany jsou Geodesics na kouli.
  • Pokud jsou vstupní mnohoúhelníky rovné kartézské čáry, zvažte použití geo_polygon_densify() k převodu planárních hran na geodesické čáry.

Motivace pro pokrytí mnohoúhelníku pomocí tokenů buněk S2

Bez této funkce bychom mohli použít jeden přístup, abychom mohli klasifikovat souřadnice do mnohoúhelníku obsahujících tyto souřadnice.

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

Výstup

longitude zeměpisná šířka description
-73.95 40.75 New York city
-122.3 47.6 Seattle
-115.18 36.16 Las Vegas

I když tato metoda funguje v některých případech, je neefektivní. Tato metoda provede křížové spojení, což znamená, že se pokusí shodovat s každým mnohoúhelníkem ke každému bodu. Tento proces spotřebovává velké množství paměti a výpočetních prostředků. Místo toho bychom chtěli shodovat každý mnohoúhelník k bodu s vysokou pravděpodobností úspěchu uzavření a vyfiltrovat další body.

Tuto shodu lze dosáhnout následujícím postupem:

  1. Převod mnohoúhelníku na buňky S2 úrovně k,
  2. Převod bodů na stejnou úroveň buněk S2 k
  3. Spojení s buňkami S2,
  4. Filtrování podle geo_point_in_polygon() Tuto fázi je možné vynechat, pokud je v pořádku určité množství falešně pozitivních výsledků. Maximální chyba bude oblast buněk s2 na úrovni k nad hranicí mnohoúhelníku.

Výběr úrovně buňky S2

  • V ideálním případě bychom chtěli pokrýt každý mnohoúhelník jedním nebo jen několika jedinečnými buňkami tak, aby žádné dva mnohoúhelníky nesdílely stejnou buňku.
  • Pokud jsou mnohoúhelníky blízko sebe, zvolte úroveň buňky S2 tak, aby její okraj buňky byl menší (4, 8, 12krát menší) než okraj průměrného mnohoúhelníku.
  • Pokud jsou mnohoúhelníky daleko od sebe, vyberte úroveň buňky S2 tak, aby její okraj buňky byl podobný nebo větší než okraj průměrného mnohoúhelníku.
  • V praxi nemusí pokrytí mnohoúhelníku s více než 10 000 buňkami přinést dobrý výkon.
  • Ukázkové případy použití:
  • Buňka S2 úroveň 5 může být vhodná pro pokrytí zemí/oblastí.
  • S2 buňka úroveň 16 může pokrýt hustá a relativně malá manhattanská čtvrť (New York).
  • S2 buňka úroveň 11 lze použít pro pokrytí předměstí Austrálie.
  • Doba běhu dotazu a spotřeba paměti se můžou výrazně lišit kvůli různým hodnotám na úrovni buněk S2.

Upozorňující

Pokrytí velkého mnohoúhelníku s malými buňkami může vést k obrovskému množství překrývajících se buněk. Výsledkem může být, že dotaz vrátí hodnotu null.

Poznámka:

Návrhy vylepšení výkonu:

  • Pokud je to možné, zmenšete velikost tabulky před spojením seskupením souřadnic, které jsou velmi blízko sebe, pomocí geoprostorového clusteringu nebo filtrováním nenesesárních souřadnic kvůli povaze dat nebo obchodních potřeb.
  • Pokud je to možné, snižte počet mnohoúhelníku z důvodu povahy dat nebo obchodních potřeb. Vyfiltrujte nepotřebné mnohoúhelníky před spojením, rozsah oblasti zájmu nebo sjednocení mnohoúhelníku.
  • V případě velmi velkých mnohoúhelníku zmenšete jejich velikost pomocí geo_polygon_simplify().
  • Změna úrovně buněk S2 může zvýšit výkon a spotřebu paměti.
  • Změna typu spojení a rady může zvýšit výkon a spotřebu paměti.
  • Pokud je nastavený kladný poloměr, můžete zkusit zvýšit výkon tak, že se vrátíte k poloměru 0 u obrazce ve vyrovnávací paměti pomocí geo_polygon_buffer().

Příklady

Následující příklad klasifikuje souřadnice do mnohoúhelníku.

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

Výstup

longitude zeměpisná šířka description
-73.9741 40.7914 Horní západní strana
-73.995 40.734 Vesnice Greenwich
-73.9584 40.7688 Horní východní strana

Tady je ještě větší vylepšení výše uvedeného dotazu. Spočítejte události stormu na stav USA. Následující dotaz provádí velmi efektivní spojení, protože neprovádí mnohoúhelníky spojením a používá operátor vyhledávání.

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

Výstup

StateName StormEventsCountByState
Florida 960
Gruzie 1085
... ...

Následující příklad vyfiltruje mnohoúhelníky, které se neprotínají s oblastí mnohoúhelníku zájmu. Maximální chyba je diagonální délka s2cell. Tento příklad je založen na polygonizované zemi v nočním rastrovém souboru.

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

Výstup

Počet
83

Počet buněk, které budou potřeba k pokrytí některých mnohoúhelníku s buňkami S2 úrovně 5.

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));

Výstup

s2_cell_token_count
286

Pokrytí mnohoúhelníku s velkými oblastmi s buňkami s malou oblastí vrátí hodnotu null.

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

Výstup

print_0

Pokrytí mnohoúhelníku s velkými oblastmi s buňkami s malou oblastí vrátí hodnotu null.

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

Výstup

print_0
0