9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Rails+PostGIS+YOLPで現在表示している地域の市区町村境界を描画するサンプル

Last updated at Posted at 2016-07-10

今回はPostGISを使って現在表示している領域に一致する市区町村の多角形情報が欲しいなと思ったためサンプルを作ってみました。
地形データは総務省統計局の国勢調査小地域のデータを利用させてもらっています。

サンプルプログラムの概要
東京・千葉・埼玉・神奈川の範囲内で、地図を移動すると、現在表示している区画に一致する市区町村の境界をポリゴンで表示するサンプルです。

サンプルプログラム動作のために必要な外部環境
PostgreSQL
PostGIS
YOLPのアカウント
Ruby on Rails

サンプルデータ付きソースコード

動作サンプル
表示している領域に合致する市区町村多角形をポリゴン描画した状態
スクリーンショット 2016-07-11 0.19.28.png

ドラッグしたとき(表示領域外のポリゴンが描画されてないことを示すサンプル)
スクリーンショット 2016-07-11 0.21.41.png

環境構築方法
PostgreSQLにPostGISのExtensionを追加する
(PostGISのパッケージインストールについてはGoogle先生にお問い合わせください)

PostgreSQLにPostGIS Extensionを追加する
-- PostGISの追加
-- Enable PostGIS (includes raster)
CREATE EXTENSION postgis;
-- Enable Topology
CREATE EXTENSION postgis_topology;
-- fuzzy matching needed for Tiger
CREATE EXTENSION fuzzystrmatch;
-- Enable US Tiger Geocoder
CREATE EXTENSION postgis_tiger_geocoder;

サンプルデータを追加する
cloneしたプロジェクトの直下にcities.sql.zipがありますので解凍して、

psql -h ご自身のホスト -Uご自身の接続ユーザ名 -p < cities.sql

にてcitiesテーブルをインポートしてください。

Railsの環境を構築
サンプルプログラムのdatabase.ymlをご自身のPostgreSQL環境に合わせて修正してください

config/database.yml
default: &default
  adapter: postgis
  encoding: unicode
  # For details on connection pooling, see rails configuration guide
  # http://guides.rubyonrails.org/configuring.html#database-pooling
  pool: 5
  username: <ご自身のPostgreSQLユーザ名>
  password: <PostgreSQLのパスワード>
  host: localhost
  port: 5432
  schema_search_path: public

YOLPのキーをご自身のキーを割り当ててください。

app/views/top/index.html.erb
<script src="http://js.api.olp.yahooapis.jp/OpenLocalPlatform/V1/jsapi?appid={ご自身のYOLPキーをご利用ください}" type="text/javascript"  charset="UTF-8"></script>

以上で準備が完了です。railsのサーバを起動して動作確認ができます。

rails s

にてサーバを起動し、localhost:3000/ にて地図上にYOLPが表示され、市区町村の境界線に沿ったポリゴンが表示されることを確認できます。
マウスで地図をドラッグすると、ポリゴンが描画されてない地区が表示されます。
ドラッグを終了すると現在の表示区画に一致する市区町村境界が緑色のポリゴンで描画されます。

コードのポイント解説
Gemはactiverecord-postgis-adapterを利用しています。

gem 'activerecord-postgis-adapter'
gem 'pg', '~> 0.15'

geometry列を使ったモデルの作成は以下のようになります。

rails g model city pref:string city:string polygon:geometry

今回かなり手を抜いちゃっていますが、citiesテーブルに格納したgeometryをYOLPのポリゴンに変更するメソッドとして
multiPolygonToPolygonJsonを定義しています。
以下が実装になります。

app/controllers/top_controller.rb
  # ActiveRecordで取得したpolygonをYOLPのpolygon生成javascriptへ変換
  def multiPolygonToPolygonJson(regions)
    # 市区町村毎のjavascriptを格納する結果配列
    result = []
    # 行毎にpolygon javascriptを生成
    regions.each do |row|
      # multipolygonのgeomeryは((polygon),(polygon))の形式で格納されているため、単一のポリゴン情報毎に分解
      polygons = row.polygon.to_s.split("),")

      result_points = ""
      polygons.each_with_index do |b, idx|
        # 余分な情報を除去
        points = b.gsub(/MULTIPOLYGON|\(|\)/, '')
        # PostGISの座標情報は Longtude Latitudeの形式になっていて、YOLPはLatitude Longtudeなので、座標を入れ替えてjavascript生成
        points = points.gsub(/([0-9\\.]+) ([0-9\\.]+)/, 'new Y.LatLng(\2, \1),').gsub(/,,/, ',')

        result_points += "var latlng#{row.id}_#{idx} = [ #{points} ];"
        result_points += <<-EOS
        var polygon#{row.id}_#{idx} = new Y.Polygon(
          latlng#{row.id}_#{idx},
          {
            strokeStyle: new Y.Style("cc0000", 4, 0.7),
            fillStyle: new Y.Style("00ff00", null, 0.2)
          });
        polygon#{row.id}_#{idx}.setClickable(false);
        map.addFeature(polygon#{row.id}_#{idx});
        EOS
      end
      # 生成したpolygonのjavascriptを配列に格納
      result.push(result_points);

    end
    result
   end

ポイントはPostGISで格納した座標がLon / Latになっているので、YOLP形式に合わせるときにLat/Lonに変換すること。
くらいです。
環境構築は手間ですができてしまうと多角形探査が非常に楽になりますので、
地図でなにかしたいときはPostGISを使うことをお勧めします。

9
11
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?