Created
March 15, 2011 06:08
-
-
Save yehara/870384 to your computer and use it in GitHub Desktop.
KML データを JSON に変換するスクリプト
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!ruby | |
# -*- encoding: UTF-8 -*- | |
require "rubygems" | |
require "rexml/document" | |
require "rexml/streamlistener" | |
require "sqlite3" | |
require "pr_geohash" | |
include REXML | |
class KmlListener | |
include StreamListener | |
@@placemark_context = ['kml', 'Document', 'Folder', 'Placemark'] | |
@@name_context = @@placemark_context + ['name'] | |
@@description_context = @@placemark_context + ['description'] | |
@@coordinate_context = @@placemark_context + ['Point', 'coordinates'] | |
def initialize | |
@context = [] | |
@array = [] | |
end | |
def array | |
@array | |
end | |
def tag_start(tag, attrs) | |
@context.push tag | |
case tag | |
when "kml" | |
@id = 0 | |
when "Placemark" | |
@place = Hash::new | |
@id += 1 | |
@place["id"] = @id | |
@place["name"] = "" | |
@place["description"] = "" | |
end | |
end | |
def tag_end(tag) | |
case tag | |
when "Placemark" | |
# puts @place | |
@array.push @place | |
end | |
@context.delete_at -1 | |
end | |
def cdata(content) | |
case @context.last | |
when "name" | |
if @context == @@name_context then | |
@place["name"] = content | |
end | |
when "description" | |
if @context == @@description_context then | |
/<b>住所:<\/b>\s*(.*)\s*<\/div>/m =~ content | |
@place["description"] = $1.chomp | |
end | |
end | |
end | |
def text(text) | |
case @context.last | |
when "coordinates" | |
if @context == @@coordinate_context then | |
/([-0-9\.]+),([-0-9\.]+)(?:,([-0-9\.]+))/m =~ text | |
@place["lng"] = $1.to_f | |
@place["lat"] = $2.to_f | |
end | |
end | |
end | |
end | |
listener = KmlListener.new | |
Document.parse_stream($stdin, listener) | |
db = SQLite3::Database.new("shelter.db") | |
db.execute("create table if not exists places (id integer primary key, name text, lat real, lng real, detail text);") | |
db.execute("create table if not exists geohash (geohash text primary key, lat real, lng real, glat real, glng real, length integer, center_count integer, neighbor_count integer);") | |
db.execute("create table if not exists place_geohashes (places_id integer references places(id), geohash text references geohash(geohash), center integer);") | |
db.execute("delete from place_geohashes;") | |
db.execute("delete from geohash;") | |
db.execute("delete from places;") | |
db.execute("vacuum;") | |
db.transaction do | |
array = listener.array | |
array.each {|place| | |
next if !place.key?('lat') || !place.key?('lng') | |
p place["id"] | |
db.execute("insert or replace into places values (:id, :name, :lat, :lng, :detail);", place["id"], place["name"], place["lat"], place["lng"], place["description"]) | |
[4, 5, 6].each {|l| | |
center = GeoHash.encode(place["lat"], place["lng"], l) | |
center_pos = GeoHash.decode(center) | |
db.execute("insert or replace into geohash values (:geohash, :lat, :lng, 0, 0, :length, 0, 0)", center, (center_pos[0][0]+center_pos[1][0])/2, (center_pos[0][1]+center_pos[1][1])/2, l) | |
GeoHash.neighbors(center).each {|n| | |
n_pos = GeoHash.decode(n) | |
db.execute("insert or replace into geohash values (:geohash, :lat, :lng, 0, 0, :length, 0, 0)", n, (n_pos[0][0]+n_pos[1][0])/2, (n_pos[0][1]+n_pos[1][1])/2, l) | |
} | |
} | |
} | |
array.each {|place| | |
next if !place.key?('lat') || !place.key?('lng') | |
p place["id"] | |
[4, 5, 6].each {|l| | |
center = GeoHash.encode(place["lat"], place["lng"], l) | |
db.execute("insert into place_geohashes values (:placesid, :geohash, 1)", place["id"], center) | |
db.execute("update geohash set center_count=center_count+1, glat=(glat*center_count+:lat)/(center_count+1), glng=(glng*center_count+:lng)/(center_count+1) where geohash=:geohash", place["lat"], place["lng"], center) | |
GeoHash.neighbors(center).each {|n| | |
n_pos = GeoHash.decode(n) | |
db.execute("insert into place_geohashes values (:placesid, :geohash, 0)", place["id"], n) | |
db.execute("update geohash set neighbor_count=neighbor_count+1 where geohash=:geohash", n) | |
} | |
} | |
} | |
end | |
db.execute("vacuum;") | |
db.close |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment