ruby-robotの夢

cygwin-ruby,qgisの達人を目指す奮闘記

georuby で shpの読み書き方法

georuby と geo_ruby と GeoRuby

gem には、 georuby と geo_ruby という似たものが存在する。
私は、この区別、意味はよくわからないが、これまで、人のコードをまねして、
shpの入力ではgeorubyを、出力ではgeo_rubyを使っていた。
gem list でみると、geo_rubyというのは無く、
georuby (2.5.2)
GeoRuby (1.3.4)
となっている。geo_rubyがGeoRubyなのか?

1つのプログラムで両方の実行を試してみたが、うまく動かない。
ライブラリのソースを調べれば何かわかるかもしれないが、かなり複雑で、面倒だ。
このため、プログラムを分けて、
①shpを読み込み、アイテム編集し、jsonに出力する。
別プログラムで②jsonからshpを書き出すこととした。
①の中で、②を実行してやれば、基本的に①のみの編集でよい。

JSON2SHP

下は、json2shp.rb

# $0:Usage >$0 -l gis.json -> create gis.shp
require 'rubygems'
require "geo_ruby"
require "geo_ruby/shp"
include GeoRuby::Shp4r
include GeoRuby::SimpleFeatures
require "json"

  j_dbg=false
  typh={"l"=>ShpType::POLYLINE,"p"=>ShpType::POINT, "a"=>ShpType::POLYGON}
  type="p"
  while ARGV.size>0 and m=ARGV[0].match(/^-([pla])/) #command line option
    type=m[1]
    ARGV.shift
  end
  print "type",type if j_dbg
  nfi=ARGV[0]
  nfo=File.basename(nfi,".json")+".shp" ;  print "nfo",nfo if j_dbg
  json=IO.readlines(nfi)[0] ;  print "len",json.size if j_dbg

  es=JSON.parse(json);  print "es",es.size if j_dbg
  keyset=es.map{|e| e["data"].keys}.uniq
  abort "keyset.size!=!",keyset if  keyset.size!=1
  keys=es[0]["data"].keys.map(&:to_s)
  vals=es[0]["data"].values ;  print "vals",vals if j_dbg
  ftyps=vals.map{|v| v.class.to_s};  print "ftyps",ftyps if j_dbg
  clens=ftyps.map{|t| (t[0]=="I")?["I",8,0]:((t[0]=="F")?["F",16,8]:["C",128,0])}
  print "clens",clens if j_dbg
  shptyp=typh[type]
  fields=[keys,clens].transpose.map{|key,(styp,len0,len1)|
    Dbf::Field.new(key,styp,len0,len1)} ;  print "fields",fields if j_dbg
  ShpFile.create(nfo,shptyp,fields){|dst|
    dst.transaction{|src|
      es.each do |e|
              xys=e["geometry"].map{|xy| xy.map(&:to_f)}; print "xys",xys if j_dbg
              points=xys.map{|xy| GeoRuby::SimpleFeatures::Point.from_x_y(*xy)}
              n_parts=1;np=points.size
              parts=[0,np]
              linear_rings=Array.new(n_parts){|i|
                GeoRuby::SimpleFeatures::LineString.from_points(
                points[(parts[i])...(parts[i+1])]) } ;print "lr",linear_rings if j_dbg
        if type=="l"
                geometry=GeoRuby::SimpleFeatures::MultiLineString
            .from_line_strings(linear_rings) 
        elsif type=="a"
                geometry=GeoRuby::SimpleFeatures::MultiPolygon.from_polygons(
                  [GeoRuby::SimpleFeatures::Polygon.from_linear_rings(linear_rings)]) 
        elsif type=="p"
                geometry=GeoRuby::SimpleFeatures::Point.from_x_y(*xys[0])
        end
              print "data",e["data"] if j_dbg
              src.add(ShpRecord.new(geometry,e["data"]))
      end #es
    } #src
  } #dst