見出し画像

位置情報とパブリックデータ#09: (地理空間関数)オブジェクト間の関係判定

(TeradataのSQL実行環境に関してはこちらをご覧ください)

Teradata Geospatialの関数には判定系の関数がいくつかあります。2つの位置オブジェクトを見て、例えばどちらかが片方を内包している場合には1(True)、していない場合には0(False)を返してくれるといった判定をします。これによって、ある商圏内に内包される顧客をカウントするのが容易になったり、ある商圏と交差している路線を特定するのが容易になったりします。今回挙動を確認したのは以下で、このような判定系の関数からいくつかピックアップしたものです。名前からして紛らわしいのも幾つかあります。英語圏の人たちはintersectsとoverlapsの違いが直感的に判るのでしょうかね。

  • st_intersects()

  • st_disjoint()

  • st_contains()

  • st_within()

  • st_overlaps()

  • st_crosses()

挙動を理解するため、以下のようなデータを用意しました。いくつかのポリゴン、線、折れ線、点を用意し、くっついていない、外側がくっついている、クロスしている、内側がくっついている、中にいる ..といった形が出来上がるようにオブジェクトを配置しました。

テスト用オブジェクト

そしてこれらデータの組み合わせで、以下のようなデータパターンを用意します。

  • 自分自身: まったく同じオブジェクト同士

  • 離れ: オブジェクト同士の重なりは一切ない

  • 外触: オブジェクトの1つがポリゴンで、外側から境界線と接触している

  • 交差: オブジェクト同士が1点を共有している。お互いがお互いを貫く

  • 中に: オブジェクトの1つがポリゴンで、内側に存在しているが境界線と接触していない

  • 内触: オブジェクトの1つがポリゴンで、内側から境界線と接触している

  • 線上: 線同士で、同一線上の一部に存在している

  • 触る: 線同士で、オブジェクト同士が1点を共有しているが、貫いていない

このパターンごとにデータを入力すると、各関数はどんな判定を下すのかを見ていきます。また、関数の前(左)とかっこ内(右)にデータを入力しますが、これを反対にすると挙動が変わるのかも気になります。まずはノートブックを。

関数は左側の頭に1つ、右側かっこ内にもう1つ入力列をセットします。そのため、両側にセットできるようクロスジョインさせて同一行上に乗せ、計算させたい関係だけ名前を付けてあげて、左側と右側をそのまま、そして左右を反対にして関数に突っ込んであげています。データの中身を見るに、まずst_contains()とst_within()以外は、左右を入れ替えても結果が同じであることがわかります。個別にみていきましょう。

  • st_intersects(): 2つのオブジェクトに何らか共通する部分があれば1の判定を下します。貪欲というか何か関係があれば容易に1をくれる関数です。

  • st_disjoint(): st_intersects()と真逆の判定を下します。まったく何も共通要素がないときに1です。ということは同じロジックで結果を反転させただけなのでは、という疑問は抱かないようにします。

  • st_contains(): 同じオブジェクト同士は1と判定します。また左側のオブジェクトの境界を含む中に存在していれば1の判定を下しています。右側のオブジェクトが左側のオブジェクトの外側に飛び出している部分があると0判定です。イメージとしては左側>=右側、left contains right (左側が右側を内包している、英語読み)、ですね。左右を逆にすると判定も逆になります。

  • st_within(): どちらかがどちらかの境界を含む中に存在しているとき、st_contains()の左側と右側を逆にした判定を下します。左側<=右側、left is within of right (左側は右側に収まっている)、です。ということは入ってきた2つの列を入れ替えれば同じロジックなのでは、関数の開発者がロジックを使いまわして、作った関数の数を水増ししたのではという疑問は抱かないようにします。

  • st_overlaps(): まず、同じサブタイプ同士でないと結果を返してくれず、nullとなります。そして実質的にポリゴンとポリゴンで、重なる面があり、なおかつどちらかがどちらかの中であったり、まったく同じでもない場合にのみ1がセットされています。なので、違うポリゴンだけど共有「面」と異なる「面」の両方があるかを判定する関数のようです。

  • st_crosses(): 少なくとも片方のオブジェクトが線である必要があります。そして、お互いがお互いの境界をクロスしているときに1の判定を下しています。接しているだけでは1判定をくれません。そのため点オブジェクトは実質0判定をもらえないということになります。興味深いのが28番と33番で、これは傍目ではクロスしていません。共通の「点」とそうでない「点」の両方を持っていることが判定条件のようです。

以上です。最初に掲載したグラフ画像のデータおよび定義ファイルをご参考までに置いておきます。

#geospatial #gis #teradata #sql #analytics #st_geometry  


この記事が気に入ったらサポートをしてみませんか?