Geo::Reader の Deegree 版と JUMP 版を雑に作ってみました
Geo::Reader を、GeoTools と同じく Java の地理情報処理ライブラリである Deegree と JUMP でも作ってみました。今回の作業の趣旨は、
もし Deegree や JUMP で実装すると 10 倍速いというようなことがあったら悔しいから、一応試しておこう
という程度のもので、今まで以上に雑なテストですのでご了承ください。実は、型変換もきちんとはそろえていません。
テストの結果、Shapefile 形式の同一ファイルを読むのに要する時間は、以下のようになりました:
geotools.rb on GeoTools | 41秒 |
degree.rb on Deegree | 46秒 |
jump.rb on JUMP | 39秒、但し -Xmx1024m とする必要あり |
この結果、Deegree や JUMP が GeoTools と比べて劇的に速いということはないことが分かりましたので、当面は GeoTools に対して geotools.rb を作っていきたいと思います。
JUMP の、「Shapefile の内容をいったん全部メモリにロードして FeatureCollection として返す」という実装は「すごい」なあと思いました。標準化によるミスリードの典型例だと思います。この話題については、あとで書くかもしれません。
現時点の deegree.rb & jump.rb
雑で恐縮ですが、ご参考のため。deegree.rb:
# this code is under development and subject to major change. module Geo module Deegree QUALIFIED_NAMES = %w{org.deegree.io.shpapi.ShapeFile} begin require 'rjb' QUALIFIED_NAMES.each do |qn| sn = qn.split('.').last module_eval "#{sn} = Rjb::import('#{qn}')" end IMPLEMENTATION = 'rjb' rescue LoadError require 'java' QUALIFIED_NAMES.each do |qn| include_class qn end IMPLEMENTATION = 'java' end end class Reader def Reader::foreach(file_name, sjis_workaround = false) sf = Geo::Deegree::ShapeFile.new(file_name.sub(/.shp$/, '')) keys = sf.getProperties sf.getRecordNum.times do |i| feat = sf.getFeatureByRecNo(i + 1) attrs = {} keys.each do |key| attrs[key] = feat.getAttribute(key) end yield feat.getDefaultGeometryPropertyValue, attrs end end end end # ad hoc tests if __FILE__ == $0 ## TODO: better separate tests as unit tests. start_time = Time.now Geo::Reader.foreach('transl_1_1.shp', false) do |geom, attrs| #print "#{geom} #{attrs.inspect}\n" end print "#{Time.now - start_time} sec.\n" end
それから jump.rb
# this code is under development and subject to major change. module Geo module Jump QUALIFIED_NAMES = %w{com.vividsolutions.jump.io.ShapefileReader com.vividsolutions.jump.io.DriverProperties} begin require 'rjb' Rjb::primitive_conversion = true Rjb::load(nil, ['-Xmx1024m']) QUALIFIED_NAMES.each do |qn| sn = qn.split('.').last module_eval "#{sn} = Rjb::import('#{qn}')" end IMPLEMENTATION = 'rjb' rescue LoadError require 'java' QUALIFIED_NAMES.each do |qn| include_class qn end IMPLEMENTATION = 'java' end end class Reader def Reader::foreach(file_name, sjis_workaround = false) dp = Geo::Jump::DriverProperties.new(file_name) r = Geo::Jump::ShapefileReader.new() fc = r.read(dp) fs = fc.getFeatureSchema keys = [] fs.getAttributeCount.times do |i| key = fs.getAttributeName(i) keys << key unless key == 'GEOMETRY' end iter = fc.iterator while(iter.hasNext) feat = iter.next attrs = {} keys.each do |key| attrs[key] = feat.getAttribute(key) end yield feat.getGeometry, attrs end end end end # ad hoc tests if __FILE__ == $0 ## TODO: better separate tests as unit tests. start_time = Time.now Geo::Reader.foreach('transl_1_1.shp', false) do |geom, attrs| #print "#{geom} #{attrs.inspect}\n" end print "#{Time.now - start_time} sec.\n" end