Amazon Athenaで地理空間データのクエリをしてみた(地理空間関係関数)
こんにちは、CX事業本部 IoT事業部の若槻です。
Amazon Athenaでは、Prestoエンジンが使われているため、地理空間関数(Geospatial Functions)をサポートしており、地理空間データのクエリが可能です。
今回は、Amazon Athenaで使用できる地理空間関数のうち、地理空間関係関数の動作をいくつか確認してみました。
地理空間関係関数とは
地理空間関係関数(Geospatial Relationship Functions)とは、地理空間関数の1種で、2つの異なるジオメトリ間の関係をboolean型で取得することができます。
地理空間関係関数には次のような種類があります。
- ST_Contains(geometry, geometry)
- ST_Crosses(geometry, geometry)
- ST_Disjoint(geometry, geometry)
- ST_Equals(geometry, geometry)
- ST_Intersects(geometry, geometry)
- ST_Overlaps(geometry, geometry)
- ST_Relate(geometry, geometry, varchar)
- ST_Touches(geometry, geometry)
- ST_Within(geometry, geometry)
今回は、これらのうち始めの3つを試してみたいと思います。
やってみた
前提として、エンジンバージョン2を使用します。
ST_Contains(geometry, geometry)
ST_Contains(geometry, geometry)
は、左ジオメトリに右ジオメトリが含まれている場合に限りTRUE
を返します。
ポリゴンとポリゴンを指定した場合
まずはポリゴンとポリゴンを指定してみます。POLYGON
は、一連の座標を直線で接続した幾何学図形(ポリゴン)を定義します。
SELECT ST_Contains('POLYGON((0 2,1 1,0 -1,0 2))', 'POLYGON((-1 3,2 1,0 -3,-1 3))')
右のポリゴンが左のポリゴンに含まれていないため、クエリ実行結果はfalse
となります。
両ポリゴンの位置関係を図示すると次のようになります。不慣れですがSVGで描いてみました。右のポリゴン(青色)が左のポリゴン(黒色)を含んでいますね。
<svg viewBox="-3 -4 10 10" xmlns="http://www.w3.org/2000/svg"> <polygon points="0 2,1 1,0 -1,0 2" fill="none" stroke="black" stroke-width="0.05" /> <polygon points="-1 3,2 1,0 -3,-1 3" fill="none" stroke="blue" stroke-width="0.05" /> </svg>
よってポリゴンの指定を左右反対にするとクエリ実行結果はtrue
となります。
SELECT ST_Contains('POLYGON((-1 3,2 1,0 -3,-1 3))', 'POLYGON((0 2,1 1,0 -1,0 2))')
ポリゴンとポイントを指定した場合
次にポリゴンとポイントを指定してみます。
SELECT ST_Contains('POLYGON((0 2,1 1,0 -1,0 2))', ST_Point(0, 0))
左のポリゴンに右のポイントが含まれていないためfalse
となります。
位置関係を図示すると次のようになります。ポイント(赤色)がポリゴン(青色)の線上に位置しているため含まれない判定となっているようです。
<svg viewBox="-2 -2 10 10" xmlns="http://www.w3.org/2000/svg"> <polygon points="0 2,1 1,0 -1,0 2" fill="none" stroke="blue" stroke-width="0.05" /> <circle cx="0" cy="0" r="0.1" fill="#e00" /> </svg>
ポイントの位置をポリゴンに含まれるようにずらすと、クエリ実行結果はtrue
となりました。
SELECT ST_Contains('POLYGON((0 2,1 1,0 -1,0 2))', ST_Point(0.5, 1))
ずらした後の位置関係を図示すると次のようになります。
<svg viewBox="-2 -2 10 10" xmlns="http://www.w3.org/2000/svg"> <polygon points="0 2,1 1,0 -1,0 2" fill="none" stroke="blue" stroke-width="0.05" /> <circle cx="0.5" cy="1" r="0.1" fill="#e00" /> </svg>
ST_Crosses(geometry, geometry)
ST_Crosses(geometry, geometry)
は、左ジオメトリと右ジオメトリがクロスする場合に限りTRUE
を返します。
ここではラインを2つ指定します。ST_Line
で指定した座標でラインを表現します。
SELECT ST_Crosses(ST_Line('linestring(1 1, 2 2 )'), ST_Line('linestring(0 1, 2 2)'))
クロスしていないためクエリ実行結果はfalse
となりました。
上記の位置関係を図示すると次のようになります。ラインが接してはいますがこれではクロス判定とならないようです。
<svg viewBox="-0.5 0.5 5 5" xmlns="http://www.w3.org/2000/svg"> <polyline points="1 1, 2 2" fill="none" stroke="black" stroke-width="0.05" /> <polyline points="0 1, 2 2" fill="none" stroke="blue" stroke-width="0.05" /> </svg>
クロスするように右ジオメトリ(黒色)の座標を変更してみます。
SELECT ST_Crosses(ST_Line('linestring(10 10, 0 20)'), ST_Line('linestring(0 10, 20 20)'))
true
となりました。
変更後の位置関係を図示すると次のようになります。ラインがちゃんとクロスしています。
<svg viewBox="-0.5 0.5 5 5" xmlns="http://www.w3.org/2000/svg"> <polyline points="1 1, 0 2" fill="none" stroke="black" stroke-width="0.05" /> <polyline points="0 1, 2 2" fill="none" stroke="blue" stroke-width="0.05" /> </svg>
ST_Disjoint(geometry, geometry)
ST_Disjoint(geometry, geometry)
は、左ジオメトリと右ジオメトリが共通部分が空(クロスしていない)の場合に限りTRUE
を返します。
SELECT ST_Disjoint(ST_Line('linestring(0 0, 0 1)'), ST_Line('linestring(1 1, 1 0)'))
指定したライン同士がクロスしていないためクエリ実行結果はtrue
となりました。
上記の位置関係を図示すると次のようになります。ラインが平行になっておりクロスしていません。
<svg viewBox="-0.5 -0.5 5 5" xmlns="http://www.w3.org/2000/svg"> <polyline points="0 0, 0 1" fill="none" stroke="black" stroke-width="0.05" /> <polyline points="1 1, 1 0" fill="none" stroke="blue" stroke-width="0.05" /> </svg>
クロスするように右ジオメトリ(黒色)の座標を変更してみます。
SELECT ST_Disjoint(ST_Line('linestring(0 0.5, 2 0.5)'), ST_Line('linestring(1 1, 1 0)'))
するとクエリ実行結果はfalse
となりました。
変更後の位置関係を図示すると次のようになります。ラインがクロスしています。
<svg viewBox="-0.5 -0.5 5 5" xmlns="http://www.w3.org/2000/svg"> <polyline points="0 0.5, 2 0.5" fill="none" stroke="black" stroke-width="0.05" /> <polyline points="1 1, 1 0" fill="none" stroke="blue" stroke-width="0.05" /> </svg>
おわりに
Amazon Athenaで使用できる地理空間関数のうち、地理空間関係関数の動作をいくつか確認してみました。
今まではAthenaでデータをクエリするとなると、データのフィルターやジョインなどの操作がほとんどだったので、地理空間関数は新鮮でした。
また座標の数値だけでジオメトリ間の位置関係をイメージするのが大変だったので、SVGで図示する方法を見つけられて良かったです。
参考
- SVG: Scalable Vector Graphics | MDN - 基本図形 – SVG 1.1 (第2版)
- SVGのviewBoxをわかりやすく紐解く|NEWS|株式会社INDETAIL(インディテール)
- 塗りつぶしとストローク - SVG: Scalable Vector Graphics | MDN
以上