mk-mode BLOG

このブログは自作の自宅サーバに構築した Debian GNU/Linux で運用しています。
PC・サーバ構築等の話題を中心に公開しております。(クローンサイト: GitHub Pages

ブログ開設日2009-01-05
サーバ連続稼働時間
Reading...
Page View 合計
Reading...
今日
Reading...
昨日
Reading...

GIS, Ruby - georuby で Shapefile のジオメトリデータ取得!

[ プログラミング ] [ GIS, 地図 ]

こんにちは。

以前、Ruby で地理空間情報データ Shapefile の属性情報(DBF)を読み込む方法について記事にしました。

今回はジオメトリデータ(緯度・経度の情報)を取得する方法についての記録です。

0. 前提条件

  • Ruby 2.2.1-p85 での作業を想定。
  • RubyGems ライブラリの georuby-2.5.2(GeoRuby でない方)がインストール済み。
  • テストで使用した Shapefile は国土交通省・国土数値情報の行政区域データ(島根県分)。

1. Ruby スクリプトの作成

簡単なスクリプトなので、特に説明は不要だと思う。
以下の例ではas_json メソッドを使用して JSON(GeoJSON) 形式でデータを取得しているが、 as_wkt, as_ewkt, as_hex_wkt, as_hex_ewkt, as_georss, as_kml メソッドも使用可能である。
また、 shebang ストリングは環境に合わせて適宜変更すること。ちなみに、当方はサーバ環境での cron 運用(cron では環境変数 PATH が通常の実行と異なること)を考慮して #! /usr/bin/env ruby を使用しない主義。

geo_ruby_geometry.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
#! /usr/local/bin/ruby
# coding: utf-8
#*********************************************
# Ruby script to read geometric datas from shapefile.
#*********************************************
#
require 'georuby'
require 'geo_ruby/shp'

include GeoRuby::Shp4r

class Shp
  def initialize
    @shpfile = "/path/to/shapefile.shp"
  end

  def exec
    begin
      ShpFile.open(@shpfile) do |shp|
        shp.each { |s| p s.geometry.as_json }
      end
    rescue => e
      $stderr.puts "[ERROR][#{self.class.name}.#{__method__}] #{e}"
      e.backtrace.each{ |trace| $stderr.puts "\t#{trace}" }
      exit 1
    end
  end
end

Shp.new.exec

3. 取得データ

参考までに、取得できるデータは以下のようなもの。(可読性を高めるため整形している)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  :type=>"MultiPolygon",
  :coordinates=>[
    [
      [
        [133.276009003, 36.354486000000065],
        [133.2760620030001, 36.35453600000005],
                :
        ===< 途中省略 >===
                :
      ],
              :
      ===< 途中省略 >===
              :
    ],
            :
    ===< 途中省略 >===
            :
  ]
}
        :
===< 以下省略 >===
        :

4. 応用例

上記の例を応用して、東西南北端の座標(経度・緯度)を取得する Ruby スクリプトを作成してみた。
(北半球&東経0〜180度限定)

geo_ruby_nsew.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#! /usr/local/bin/ruby
# coding: utf-8
#*********************************************
# Ruby script to get NorthSouthEastWest ends from shapefile.
#*********************************************
#
require 'georuby'
require 'geo_ruby/shp'

include GeoRuby::Shp4r

class Shp
  def initialize
    @shpfile = "/path/to/shapefile.shp"
  end

  def exec
    # 北・南・東・西の緯度・経度初期値
    n_end, s_end, e_end, w_end = [0, 0], [0, 90], [0, 0], [180, 0]

    begin
      # 東西南北端取得
      ShpFile.open(@shpfile) do |shp|
        shp.each do |s|
          crds = s.geometry.as_json[:coordinates]
          crds.each do |c_0|
            c_0.each do |c_1|
              c_1.each do |c|
                e_end = c if c[0] > e_end[0]
                w_end = c if c[0] < w_end[0]
                n_end = c if c[1] > n_end[1]
                s_end = c if c[1] < s_end[1]
              end
            end
          end
        end
      end

      # 結果出力
      printf("North end: %8.4f%s, %7.4f%s\n", n_end[0], n_end[1])
      printf("South end: %8.4f%s, %7.4f%s\n", s_end[0], s_end[1])
      printf("East  end: %8.4f%s, %7.4f%s\n", e_end[0], e_end[1])
      printf("West  end: %8.4f%s, %7.4f%s\n", w_end[0], w_end[1])
    rescue => e
      $stderr.puts "[ERROR][#{self.class.name}.#{__method__}] #{e}"
      e.backtrace.each{ |trace| $stderr.puts "\t#{trace}" }
      exit 1
    end
  end
end

Shp.new.exec

実行。

1
2
3
4
5
$ ./geo_ruby_nsew_end.rb
North end: 131.8654, 37.2443
South end: 131.8204, 34.3024
East  end: 133.3907, 36.2707
West  end: 131.6679, 34.5054

これは国土交通省・国土数値情報の行政区域データ「島根県」を使用した結果であるが、「日本の東西南北端点の経度緯度|国土地理院」発表の東西南北端の経度・緯度情報とほぼ同じ結果となった。

参考サイト


Shapefile を読み込んで処理を行う場合に役立つことがあるでしょう。

以上。

Comments