GeometryCollection から点と線を削除して MultiPolygon にする方法

標記のこと、buffer(0) でできることを確認しました。
d:id:hfu:20071220 で課題としていた、

Geometry の set-theoretic methods をうまく使って LineString と Point だけをエレガントに消せるかもしれません。

http://d.hatena.ne.jp/hfu/20071220/1198130913

について、buffer(0) で消せることが分かったので、実証してエントリします。

geotools.rb にメソッドを追加

検証作業を簡単にするために、geotools.rb に Geo::create_geometry_collection を加えました。引数に Geometry の配列を与えると、それらの GeometryCollection を返します*1
geotools.rb には、以下の関数が追加されています。

  • Geo::create_geometry_collection([geom1, geom2, ...])
  • Geo::create_multi_point([point1, point2, ...])
  • Geo::create_multi_line_string([line_string1, line_string2, ...])
  • Geo::create_multi_polygon([polygon1, polygon2, ...])

buffer(0) で GeometryCollection から Point と LineString が消せることの実証

buffer(0) で GeometryCollection から Point と LineString が消せることの実証スクリプトは、以下のようになりました:

# test_gc_to_mp.rb
require 'geotools'

# 模擬データを作る
pt0 = Geo::import_wkt_geometry('POINT (0 0)')
ls0 = Geo::import_wkt_geometry('LINESTRING (0 0, 1 1)')
pg0 = Geo::import_wkt_geometry('POLYGON ((0 0, 1 1, 1 0, 0 0))')
pg1 = Geo::import_wkt_geometry('POLYGON ((1 0, 2 1, 2 0, 1 0))')
gc = Geo::create_geometry_collection([pt0, ls0, pg0, pg1])

# GeometryCollection から Point と LineString を排除して MultiPolygon にする
gc = gc.buffer(0)
gc = Geo::create_multi_polygon([gc]) if gc.getNumGeometries == 1

# 表示
p gc.toString
$ ruby test_gc_to_mp.rb 
DEBUG: rjb primitive_conversion mode
"MULTIPOLYGON (((0 0, 1 1, 1 0, 0 0)), ((1 0, 2 1, 2 0, 1 0)))"

まとめ

GeometryCollection#buffer(0) により、GeometryCollection に含まれる LineString や Point を消去することができます。

*1:それほど大げさな処理ではないのですが、Rjb と JRuby の間で微妙に異なってくる処理を吸収するために、処理を geotools.rb の中に入れておきました。