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é spojování.

Syntax

geo_polygon_to_s2cells(mnohoúhelník [,úroveň[,radius]])

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

Parametry

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

Návraty

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

Poznámka

  • Překrytí mnohoúhelníku tokeny buněk S2 může být užitečné při porovnávání souřadnic s mnohoúhelníky, které mohou tyto souřadnice zahrnovat, a porovnávání mnohoúhelníků 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 koule. Mnohoúhelníkové hrany jsou geodézie 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 okrajů na geodézie.

Motivace pro překrytí mnohoúhelníku pomocí tokenů buněk S2

Bez této funkce bychom mohli použít jeden přístup ke klasifikaci souřadnic do mnohoúhelníků 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

Délky zeměpisná šířka description
-73.95 40.75 New yorku
-122.3 47.6 Seattle
-115.18 36.16 Las Vegas

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

Této shody můžete dosáhnout následujícím postupem:

  1. Převod mnohoúhelníků na buňky S2 úrovně k,
  2. Převod bodů na stejné buňky S2 úrovně k,
  3. Spojení na buňkách S2,
  4. Filtrování podle geo_point_in_polygon() Pokud je určitý počet falešně pozitivních výsledků v pořádku, můžete tuto fázi vynechat. Maximální chybou bude oblast buněk s2 na úrovni k za hranicí mnohoúhelníku.

Volba úrovně buňky S2

  • V ideálním případě bychom chtěli pokrýt každý mnohoúhelník jednou nebo 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, zvolte ú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 zakrytí mnohoúhelníku s více než 10 000 buňkami nemusí přinést dobrý výkon.
  • Ukázkové případy použití:
  • Buňka S2 úrovně 5 se může ukázat jako dobrá pro pokrytí zemí nebo oblastí.
  • S2 buňka úroveň 16 může pokrýt hustá a relativně malé manhattanské čtvrti (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.

Upozornění

Zakrytí velkého mnohoúhelníku s buňkami s malou oblastí může vést k obrovskému množství pokrývajících buněk. V důsledku toho může dotaz vrátit hodnotu null.

Poznámka

Návrhy na zlepšení výkonu:

  • Pokud je to možné, zmenšete velikost tabulky souřadnic před spojením seskupením souřadnic, které jsou velmi blízko sebe, pomocí geoprostorového clusteringu nebo vyfiltrováním nenesesárních souřadnic vzhledem k povaze dat nebo obchodním potřebám.
  • Pokud je to možné, snižte počet mnohoúhelníků vzhledem k povaze dat nebo obchodním potřebám. Před spojením vyfiltrujte nepotřebné mnohoúhelníky, zadejte obor na oblast zájmu nebo sjednocte mnohoúhelníky.
  • V případě velmi velkých mnohoúhelníku zmenšete jejich velikost pomocí geo_polygon_simplify().
  • Změna úrovně buňky S2 může zvýšit výkon a spotřebu paměti.
  • Změna typu spojení a nápovědy může zlepšit výkon a využití paměti.
  • Pokud je nastaven kladný poloměr, můžete se pokusit zvýšit výkon návratem 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íků.

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

Délky 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ě další vylepšení u výše uvedeného dotazu. Počet událostí bouře na stát USA. Následující dotaz provede velmi efektivní spojení, protože přes spojení neobsahuje mnohoúhelníky 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 (Název státu) StormEventsCountByState
Florida 960
Gruzie 1085
... ...

Následující příklad filtruje mnohoúhelníky, které se neprotínají s oblastí mnohoúhelníku, který vás zajímá. Maximální chyba je diagonála délky s2buňky. Tento příklad je založen na mnohoúhelníkové 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í polygonu 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

Zakrytí mnohoúhelníku s velkými oblastmi 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

Zakrytí mnohoúhelníku s velkými oblastmi 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
1