JTS を使って、Ruby 上で2つのジオメトリの間で最も近い点を得る
JTS を使って、Ruby 上で2つのジオメトリの間で最も近い点を得る方法を入門者向けに説明します。
以前、PostGIS を Sequel 経由で Ruby から操って、PostGIS の空間拡張関数を使って幾何を処理する方法を説明しましたが、必要な処理の全てが必ずしも PostGIS の空間拡張関数を使って処理できるわけではありません。
例題として、「2つのジオメトリの間で最も近い点を得る*1」タスクを、JTS を Rjb 経由で Ruby から操る方法を説明します。
実装
require 'rubygems' require 'rjb' # JTS つきの Java VM を読み込む Rjb::load('jts-1.11.jar') # WKTReader のインスタンスを作成する wktr = Rjb::import('com.vividsolutions.jts.io.WKTReader').new # 例題用の二つのジオメトリインスタンスを用意する。 # 実際のタスクでは、ジオメトリは PostGIS や Shapefile から WKT 形式で # 得れば良い。 LINE = wktr.read("LINESTRING (0 1, 1 0)") POINT = wktr.read("POINT (0 0)") # JTS で距離計算処理を実際に行っているクラスである、DistanceOp を # Rjb 経由で Ruby から使えるようにする。 DistanceOp = Rjb::import('com.vividsolutions.jts.operation.distance.DistanceOp') # DistanceOp のスタティックメソッド closestPoints を呼び出す。 # Coordinate の配列が返される。 # c.f. http://tsusiatsoftware.net/jts/javadoc/com/vividsolutions/jts/operation/distance/DistanceOp.html # c.f. http://tsusiatsoftware.net/jts/javadoc/com/vividsolutions/jts/geom/Coordinate.html coordinates = DistanceOp.closestPoints(LINE, POINT) # 第一引数(LINE)側の該当点は、配列の 0 番目の要素。この x, y 座標を出力してみる。 print "Closest point on the line: (#{coordinates[0].x} #{coordinates[0].y})\n"
実行結果
$ ruby shortest_line.rb Closest point on the line: (0.5 0.5)
*1:実は、PostGIS の 1.5 からは、ST_ShortestLine という関数が追加されて、このタスクは PostGIS 関数だけでも実現できるようになりました。c.f. http://www.finds.jp/docs/pgisman/1.5.1/postgis.html#ST_ShortestLine