geo_polygon_to_s2cells()
Menghitung token sel S2 yang mencakup poligon atau multipoligon di Bumi. Fungsi ini adalah alat gabungan geospasial yang bermanfaat.
Baca selengkapnya tentang hierarki sel S2.
Sintaks
geo_polygon_to_s2cells(
polygon [,
level[,
radius]])
Pelajari selengkapnya tentang konvensi sintaksis.
Parameter
Nama | Tipe | Wajib | Deskripsi |
---|---|---|---|
polygon | dynamic |
✔️ | Poligon atau multipoligon dalam format GeoJSON. |
tingkat | int |
Menentukan tingkat sel yang diminta. Nilai yang didukung berada dalam rentang [0, 30]. Jika tidak ditentukan, nilai default 11 akan digunakan. |
|
radius | real |
Radius buffer dalam meter. Jika tidak ditentukan, nilai default 0 akan digunakan. |
Mengembalikan
Array string token sel S2 yang mencakup poligon atau multipoligon. Jika radius diatur ke nilai positif, maka penutupnya akan, selain bentuk input, dari semua titik dalam radius geometri input. Jika poligon, tingkat, radius tidak valid, atau jumlah sel melebihi batas, kueri akan menghasilkan hasil null.
Catatan
- Mencakup poligon dengan token sel S2 dapat bermanfaat dalam pencocokan koordinat dengan poligon yang mungkin mencakup koordinat ini dan pencocokan poligon dengan poligon.
- Token yang mencakup poligon memiliki tingkat sel S2 yang sama.
- Jumlah maksimum token per poligon adalah 65536.
- Datum geodetik yang digunakan untuk pengukuran di Bumi adalah bola. Tepi poligon bersifat geodesik pada bola.
- Jika tepi poligon input adalah garis kartesius lurus, pertimbangkan untuk menggunakan geo_polygon_densify() untuk mengonversi tepi planar menjadi geodesik.
Motivasi untuk mencakup poligon dengan token sel S2
Tanpa fungsi ini, berikut adalah salah satu pendekatan yang dapat kita ambil untuk mengklasifikasikan koordinat ke dalam poligon yang berisi koordinat ini.
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
Hasil
garis bujur | garis lintang | description |
---|---|---|
-73.95 | 40.75 | Kota New York |
-122,3 | 47.6 | Seattle |
-115.18 | 36.16 | Las Vegas |
Meskipun metode ini bekerja dalam beberapa kasus, metode ini tidak efisien. Metode ini melakukan gabungan silang, yang berarti bahwa metode tersebut mencoba mencocokkan setiap poligon dengan setiap titik. Proses ini menghabiskan sejumlah besar memori dan sumber daya komputasi. Sebaliknya, kami ingin mencocokkan setiap poligon ke titik dengan probabilitas keberhasilan pembatasan yang tinggi, dan memfilter titik lainnya.
Kecocokan ini dapat dicapai dengan proses berikut:
- Mengubah poligon menjadi sel S2 level k,
- Mengonversi titik ke sel S2 level k yang sama,
- Digabungkan di sel S2,
- Pemfilteran berdasarkan geo_point_in_polygon(). Fase ini dapat dihilangkan jika beberapa jumlah positif palsu ok. Kesalahan maksimum akan menjadi area sel s2 pada tingkat k di luar batas poligon.
Memilih tingkat sel S2
- Idealnya, kita ingin mencakup setiap poligon dengan satu atau hanya beberapa sel unik sehingga tidak ada dua poligon yang memiliki sel yang sama.
- Jika poligon dekat satu sama lain, pilih tingkat sel S2 sehingga tepi selnya akan menjadi lebih kecil (4, 8, 12 kali lebih kecil) daripada tepi poligon rata-rata.
- Jika poligon jauh satu sama lain, pilih tingkat sel S2 sehingga tepi selnya akan serupa atau lebih besar dari tepi poligon rata-rata.
- Dalam praktiknya, mencakup poligon dengan lebih dari 10.000 sel mungkin tidak menghasilkan performa yang baik.
- Sampel kasus penggunaan:
- Sel S2 tingkat 5 mungkin terbukti baik untuk mencakup negara/wilayah.
- Sel S2 level 16 dapat mencakup lingkungan Manhattan (New York) yang padat dan relatif kecil.
- Sel S2 level 11 dapat digunakan untuk mencakup pinggiran kota Australia.
- Durasi kueri dan konsumsi memori mungkin sangat berbeda karena nilai tingkat sel S2 yang berbeda.
Peringatan
Mencakup poligon area besar dengan sel area kecil dapat menghasilkan sejumlah besar sel penutup. Akibatnya, kueri tersebut mungkin menampilkan null.
Catatan
Saran peningkatan performa:
- Jika memungkinkan, kurangi ukuran tabel koordinat sebelum bergabung, dengan mengelompokkan koordinat yang sangat dekat satu sama lain dengan menggunakan pengklusteran geospasial atau dengan memfilter koordinat yang tidak perlu karena sifat data atau kebutuhan bisnis.
- Jika memungkinkan, kurangi jumlah poligon karena sifat data atau kebutuhan bisnis. Filter poligon yang tidak perlu sebelum bergabung, cakupan ke area yang menarik atau satukan poligon.
- Dalam kasus poligon yang sangat besar, kurangi ukurannya menggunakan geo_polygon_simplify().
- Mengubah tingkat sel S2 dapat meningkatkan performa dan konsumsi memori.
- Mengubah jenis gabungan dan petunjuk dapat meningkatkan performa dan konsumsi memori.
- Jika radius positif diatur, Anda dapat mencoba meningkatkan performa dengan kembali ke radius 0 pada bentuk buffer menggunakan geo_polygon_buffer().
Contoh
Contoh berikut mengklasifikasikan koordinat ke dalam poligon.
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
Hasil
garis bujur | garis lintang | description |
---|---|---|
-73.9741 | 40.7914 | Upper West Side |
-73.995 | 40.734 | Greenwich Village |
-73.9584 | 40.7688 | Upper East Side |
Berikut adalah penyempurnaan yang lebih besar pada kueri di atas. Hitung peristiwa badai per negara bagian AS. Kueri di bawah ini melakukan gabungan yang sangat efisien karena tidak membawa poligon melalui gabungan dan menggunakan operator pencarian
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
Hasil
StateName | StormEventsCountByState |
---|---|
Florida | 960 |
Georgia | 1085 |
... | ... |
Contoh berikut memfilter poligon yang tidak bersinggungan dengan area poligon yang diinginkan. Kesalahan maksimum adalah diagonal panjang s2cell. Contoh ini didasarkan pada file raster bumi yang dipoligonisasi pada malam hari.
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
Hasil
Hitung |
---|
83 |
Jumlah sel yang akan dibutuhkan untuk mencakup beberapa poligon dengan sel S2 level 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));
Hasil
s2_cell_token_count |
---|
286 |
Pencakupan poligon area besar dengan sel area kecil menampilkan null.
let polygon = dynamic({"type":"Polygon","coordinates":[[[0,0],[0,50],[100,50],[0,0]]]});
print geo_polygon_to_s2cells(polygon, 30);
Hasil
print_0 |
---|
Pencakupan poligon area besar dengan sel area kecil menampilkan null.
let polygon = dynamic({"type":"Polygon","coordinates":[[[0,0],[0,50],[100,50],[0,0]]]});
print isnull(geo_polygon_to_s2cells(polygon, 30));
Hasil
print_0 |
---|
1 |
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk