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