はじめに
前回は、半平面の交差にもとづいてボロノイ図を計算するための考え方を説明しました。最終回となる今回は、疑似半平面の生成を実装した上で、ボロノイ図作成のプログラムを完成させます。
凸多角形による疑似半平面表現
前回も述べた通り、ある母点のボロノイ領域を求めるには、その母点と他の各母点の垂直二等分線から作られる全ての半平面の交差を計算する必要があります。すでに学習済みの凸多角形の交差計算方法を、そのまま半平面の交差計算にも利用するため、半平面を擬似的に凸多角形へと変換することを考えます。
図1を見てください。点線で囲まれた正方形の内部が、実際にボロノイ図の計算を行いたい座標範囲だとします。この正方形を取り囲むように、三角形が置かれています。(0, -10)といった頂点座標のとり方に特別な意味はなく、正方形を覆い尽くしていることがポイントです。
ある直線が与えられたとき、図2の緑色部分のように、三角形を直線で切断するかたちで凸多角形を生成すれば、この凸多角形は実用上、直線による半平面と同等だと見なすことができます(境界の図形には三角形ではなく四角形などを使ってもかまいませんが、三角形を使うことで、切断の計算をよりシンプルに記述できます)。
実際にこの切断を行い、疑似的な半平面を生成するPseudoHalfPlaneGeneratorクラスの実装を以下に示します。このクラスはまず、コンストラクタで指定された大きさを使い、図1と相似な三角形を用意します。その後、execute()メソッドで半平面を作成します。
execute()メソッドは、直線のline引数と例示点のexample引数を持ちます。lineによって作られる2つの半平面のうち、exampleを含む方の半平面に対応する疑似半平面が、ConvexPolygonオブジェクトとして作成されます。
ボロノイ領域の計算
それではいよいよ、ボロノイ図の計算へと進みましょう。
ある母点のボロノイ領域を求める方針は、次のようになります。まず、途中の計算結果を格納するために、ConvexPolygonオブジェクトを確保しておきます。そして、自身の母点以外の各母点に対し、それぞれ垂直二等分線を計算し、そこから半平面を求めます。この半平面と、途中計算用のConvexPolygonオブジェクトとの交差領域を求め、ConvexPolygonオブジェクトを更新します。こうすると、ConvexPolygonオブジェクトをナイフで少しずつ削るようにして、ボロノイ領域が確定していきます。
以上の方針にしたがって、VoronoiGeneratorクラスを記述してみます。凸多角形の交差計算クラス(第10回)、そしてPseudoHalfPlaneGeneratorとすでに道具が揃っているので、VoronoiGeneratorクラス自身のコードはかなり簡潔なものになります。
VoronoiGeneratorクラスのexecute()メソッドは、areaとsitesの2つの引数を持ちます。areaには、ボロノイ図の外枠となる図形を指定します。sitesは、各母点の座標リストです。計算が終了すると、各母点に対応するボロノイ領域のリストが戻り値として得られます。
デモプログラム
今回解説したアルゴリズムをグラフィカルに動作確認できるよう、Swingアプリケーションのデモプログラムを用意しました。Java Web Start形式になっており、こちらをクリックして直接起動できます。ソースコードは本記事には掲載しませんので、アーカイブをダウンロードして確認してください。
デモプログラムを起動すると、キャンバスに複数の母点と、その母点から作成されるボロノイ図が表示されます。キャンバス上でマウスクリックやドラッグをすることで、母点を自由に追加または移動したり、削除したりすることができます。
最後に
最終回となる今回は、ボロノイ図を作成するプログラムを完成させました。このプログラムには、第1回からのほぼすべての学習内容が応用されています。道具を少しずつ積み上げることによって、より難しい問題が解けるようになることを実感していただけたのではないでしょうか。
今回作成したプログラムのソースコードは、こちらからダウンロードできます。
本連載をきっかけとして、計算幾何学を利用した面白いソフトウェアが生まれることを願っています。12回にわたってお付き合いいただき、ありがとうございました!