次の方法で共有


geo_polygon_to_s2cells()

適用対象: ✅Microsoft FabricAzure データ エクスプローラーAzure MonitorMicrosoft Sentinel

地球上のポリゴンまたはマルチポリゴンをカバーする S2 セル トークンを計算します。 この関数は、便利な地理空間結合ツールです。

詳細については、「S2 セルの階層」を参照してください。

構文

geo_polygon_to_s2cells(polygon [, level[, radius]])

構文規則について詳しく知る。

パラメーター

件名 タイプ Required 説明
polygon dynamic ✔️ GeoJSON 形式の多角形またはマルチポリゴン
level int 要求されたセル レベルを定義します。 サポートされる値の範囲は [0, 30] です。 指定されない場合は、既定値の 11 が使用されます。
半径 real バッファーの半径 (メートル単位)。 指定されない場合は、既定値の 0 が使用されます。

返品

多角形またはマルチポリゴンをカバーする S2 セル トークン文字列の配列。 半径が正の値に設定されている場合、カバーは入力形状に加えて、入力ジオメトリの半径内のすべてのポイントになります。 多角形、レベル、半径が無効であるか、セル数が制限を超えた場合、クエリによって null 結果が生成されます。

Note

  • 多角形を S2 セル トークンで覆うのは、座標を、これらの座標を含む可能性のある多角形に一致し、多角形を多角形に照合する場合に役立ちます。
  • トークンを覆う多角形は、同じ S2 セル レベルです。
  • 多角形あたりのトークンの最大数は 65536 です。
  • 地球上の測定に使用される測地原点は球体です。 ポリゴンのエッジは、球体の測地線です。
  • 入力ポリゴンのエッジが直交直線の場合は、geo_polygon_densify () を使用して平面エッジを測地線に変換することを検討してください。

S2 セル トークンを使用して多角形をカバーするi意図

この関数がないと、座標をこれらの座標を含む多角形に分類するために、次の 1 つのアプローチを取ることができます。

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

出力

緯度 緯度 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 セル レベルの選択

  • 理想的には、2 つの多角形が同じセルを共有しなく、1 つのセルまたは少数の一意のセルですべての多角形をカバーしたいと考えるのが理想的です。
  • 多角形が互いに近い場合は、セルの端が平均多角形の端よりも小さく (4、8、12 倍)、 S2 セル レベルを選択します。
  • 多角形が互いに離れている場合は、 S2 セル レベルを選択します セルの端が平均ポリゴンのエッジと同じか大きくなります。
  • 実際には、10,000 個を超えるセルを含む多角形を覆うと、優れたパフォーマンスが得られない可能性があります。
  • サンプル ユース ケース:
  • S2 細胞レベル 5 は、国/地域をカバーするのに適している可能性があります。
  • S2 セル レベル 16 は、高密度で比較的小規模なマンハッタン (ニューヨーク州) の近隣をカバーできます。
  • S2 セル レベル 11 は、オーストラリアの郊外をカバーするために使用できます。
  • クエリの実行時間とメモリ消費量は、S2 セル レベルの値が異なるため、大きく異なる場合があります。

警告

小さな領域のセルで大きな領域の多角形をカバーすると、膨大な量のカバー セルにつながる可能性があります。 その結果、クエリは null を返す場合があります。

Note

パフォーマンス向上に関する推奨事項:

  • 可能であれば、 地理空間クラスタリングを使用するか データまたはビジネス ニーズの性質上、一意の座標を除外して、非常に近い座標をグループ化することで、結合前に座標テーブルのサイズを小さくします。
  • 可能であれば、データまたはビジネス ニーズの性質上、多角形の数を減らします。 結合する前に不要なポリゴンを除外し、対象領域にスコープを設定するか、ポリゴンを統合します。
  • 非常に大きなポリゴンの場合は、 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

出力

緯度 緯度 description
-73.9741 40.7914 Upper West Side
-73.995 40.734 Greenwich Village
-73.9584 40.7688 Upper East Side

上記のクエリの改善点を次に示します。 米国の状態ごとに Storm イベントをカウントします。 次のクエリは、結合を通じて多角形を運ばず、 lookup 演算子を使用するため、非常に効率的な結合を実行します。

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
フロリダ 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

出力

カウント
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