😀

PostGIS 2.3以降はボロノイ図を作る関数を持っているので独自に作る必要が無い

2020/10/27に公開

先にまとめ

前の記事で、ドロネー三角形分割からボロノイ図を作る方法を編み出した方がいらっしゃったことをご紹介しました。

それとはまったく異なるラインで、2.3.0で ST_VoronoiLinesST_VoronoiPolygons とが追加されています。

ST_VoronoiPolygonsを実行してみましょう

ST_VoronoiPolygon()の引数はマルチポイントです。シングルのポイントを持っている場合には、ST_Collect()でマルチポイントにまとめてから与えてください。

db=# SELECT ST_AsText(
  ST_VoronoiPolygons(
    'MULTIPOINT(12 5, 5 7, 2 5, 19 6, 19 13, 15 18, 10 20, 4 18, 0 13, 0 6, 4 1, 10 0, 15 1, 19 6)'                                                               )                  
);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          st_astext                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 GEOMETRYCOLLECTION(POLYGON((-20 33.1,-20 40,0 40,9.02941176470588 12.9117647058824,5.62244897959184 12.6020408163265,-20 33.1)),POLYGON((0 40,20.9 40,9.92666666666667 12.5666666666667,9.02941176470588 12.9117647058824,0 40)),POLYGON((-20 -14.1,-20 9.5,1.9 9.5,2.21428571428571 7.92857142857143,-1.33333333333333 0.833333333333333,-20 -14.1)),POLYGON((3.58333333333333 -20,-20 -20,-20 -14.1,-1.33333333333333 0.833333333333333,4.875 3.9375,7.5 3.5,3.58333333333333 -20)),POLYGON((-20 9.5,-20 33.1,5.62244897959184 12.6020408163265,1.9 9.5,-20 9.5)),POLYGON((1.9 9.5,5.62244897959184 12.6020408163265,9.02941176470588 12.9117647058824,9.92666666666667 12.5666666666667,10.2835051546392 12.2422680412371,7.85897435897436 3.75641025641026,7.5 3.5,4.875 3.9375,2.21428571428571 7.92857142857143,1.9 9.5)),POLYGON((-1.33333333333333 0.833333333333333,2.21428571428571 7.92857142857143,4.875 3.9375,-1.33333333333333 0.833333333333333)),POLYGON((16.6 -20,3.58333333333333 -20,7.5 3.5,7.85897435897436 3.75641025641026,12.195652173913 2.02173913043478,16.6 -20)),POLYGON((7.85897435897436 3.75641025641026,10.2835051546392 12.2422680412371,12.3358208955224 11.7686567164179,14.9285714285714 9.5,15.6290322580645 4.59677419354839,12.195652173913 2.02173913043478,7.85897435897436 3.75641025641026)),POLYGON((39 9.5,39 -14.1,15.6290322580645 4.59677419354839,14.9285714285714 9.5,39 9.5)),POLYGON((20.9 40,39 40,39 33.1,12.3358208955224 11.7686567164179,10.2835051546392 12.2422680412371,9.92666666666667 12.5666666666667,20.9 40)),POLYGON((39 -14.1,39 -20,16.6 -20,12.195652173913 2.02173913043478,15.6290322580645 4.59677419354839,39 -14.1)),POLYGON((39 33.1,39 9.5,14.9285714285714 9.5,12.3358208955224 11.7686567164179,39 33.1)))
(1 行)

ジオメトリコレクションが出たので、ポリゴンだけを抽出するST_CollectionExtract()を使ってみます。

db=# SELECT ST_AsText(
  ST_CollectionExtract(
    ST_VoronoiPolygons(
      'MULTIPOINT(12 5, 5 7, 2 5, 19 6, 19 13, 15 18, 10 20, 4 18, 0 13, 0 6, 4 1, 10 0, 15 1, 19 6)'
    ),
    3
  )
);

                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                         st_astext                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                          
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MULTIPOLYGON(((-20 33.1,-20 40,0 40,9.02941176470588 12.9117647058824,5.62244897959184 12.6020408163265,-20 33.1)),((0 40,20.9 40,9.92666666666667 12.5666666666667,9.02941176470588 12.9117647058824,0 40)),((-20 -14.1,-20 9.5,1.9 9.5,2.21428571428571 7.92857142857143,-1.33333333333333 0.833333333333333,-20 -14.1)),((3.58333333333333 -20,-20 -20,-20 -14.1,-1.33333333333333 0.833333333333333,4.875 3.9375,7.5 3.5,3.58333333333333 -20)),((-20 9.5,-20 33.1,5.62244897959184 12.6020408163265,1.9 9.5,-20 9.5)),((1.9 9.5,5.62244897959184 12.6020408163265,9.02941176470588 12.9117647058824,9.92666666666667 12.5666666666667,10.2835051546392 12.2422680412371,7.85897435897436 3.75641025641026,7.5 3.5,4.875 3.9375,2.21428571428571 7.92857142857143,1.9 9.5)),((-1.33333333333333 0.833333333333333,2.21428571428571 7.92857142857143,4.875 3.9375,-1.33333333333333 0.833333333333333)),((16.6 -20,3.58333333333333 -20,7.5 3.5,7.85897435897436 3.75641025641026,12.195652173913 2.02173913043478,16.6 -20)),((7.85897435897436 3.75641025641026,10.2835051546392 12.2422680412371,12.3358208955224 11.7686567164179,14.9285714285714 9.5,15.6290322580645 4.59677419354839,12.195652173913 2.02173913043478,7.85897435897436 3.75641025641026)),((39 9.5,39 -14.1,15.6290322580645 4.59677419354839,14.9285714285714 9.5,39 9.5)),((20.9 40,39 40,39 33.1,12.3358208955224 11.7686567164179,10.2835051546392 12.2422680412371,9.92666666666667 12.5666666666667,20.9 40)),((39 -14.1,39 -20,16.6 -20,12.195652173913 2.02173913043478,15.6290322580645 4.59677419354839,39 -14.1)),((39 33.1,39 9.5,14.9285714285714 9.5,12.3358208955224 11.7686567164179,39 33.1)))
(1 行)

次のようになります。

ST_VoronoiPolygonsの結果

前の記事の画像と比較してみて下さい。

「全く違うじゃないか」と思われるかも知れませんが、いいえ「同じ」です。ボロノイ図は放っておくと無限遠まで伸ばせるところを、ある程度の範囲で切っています。その切り方が長方形にしたか凸包にしたかの違いだけです。

ST_VoronoiLinesの方もやってみましょう

同じように、ST_VoronoiLines()の方もやってみましょう。

db=# SELECT ST_AsText(
  ST_VoronoiLines(
    'MULTIPOINT(12 5, 5 7, 2 5, 19 6, 19 13, 15 18, 10 20, 4 18, 0 13, 0 6, 4 1, 10 0, 15 1, 19 6)'
  )
);
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        st_astext                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                        
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 MULTILINESTRING((0 40,9.02941176470588 12.9117647058824),(9.02941176470588 12.9117647058824,5.62244897959184 12.6020408163265),(5.62244897959184 12.6020408163265,-20 33.1),(20.9 40,9.92666666666667 12.5666666666667),(9.92666666666667 12.5666666666667,9.02941176470588 12.9117647058824),(-20 9.5,1.9 9.5),(1.9 9.5,2.21428571428571 7.92857142857143),(2.21428571428571 7.92857142857143,-1.33333333333333 0.833333333333333),(-1.33333333333333 0.833333333333333,-20 -14.1),(-1.33333333333333 0.833333333333333,4.875 3.9375),(4.875 3.9375,7.5 3.5),(7.5 3.5,3.58333333333333 -20),(5.62244897959184 12.6020408163265,1.9 9.5),(9.92666666666667 12.5666666666667,10.2835051546392 12.2422680412371),(10.2835051546392 12.2422680412371,7.85897435897436 3.75641025641026),(7.85897435897436 3.75641025641026,7.5 3.5),(4.875 3.9375,2.21428571428571 7.92857142857143),(7.85897435897436 3.75641025641026,12.195652173913 2.02173913043478),(12.195652173913 2.02173913043478,16.6 -20),(10.2835051546392 12.2422680412371,12.3358208955224 11.7686567164179),(12.3358208955224 11.7686567164179,14.9285714285714 9.5),(14.9285714285714 9.5,15.6290322580645 4.59677419354839),(15.6290322580645 4.59677419354839,12.195652173913 2.02173913043478),(14.9285714285714 9.5,39 9.5),(39 -14.1,15.6290322580645 4.59677419354839),(39 33.1,12.3358208955224 11.7686567164179))
(1 行)

図で示すと次のようになります。

ST_VoronoiLinesの結果

ポリゴンと違い、各サイトを閉じたラインストリングにする必要が無いので、ボロノイ辺だけが出力されています。

おわりに

今更ながらですが、2.3.0から追加された関数 ST_VoronoiPolygons()ST_VoronoiLines() について、ご紹介しました。

ボロノイ分割は、最も近いポイントを共有する領域を計算してくれるものです。たとえば、ポイントを学校ととらえたら、ボロノイ分割で得られるポリゴンは、道路設置状況を全く考慮しませんが、いちおう「校区」になるでしょう。その他にも、知っていたら意外と使えるかも知れません。

本記事のライセンス

クリエイティブ・コモンズ・ライセンス
この記事は クリエイティブ・コモンズ 表示 4.0 国際 ライセンス の下に提供されています。

Discussion