#!/usr/bin/env ruby require File.expand_path('../../config/boot', __FILE__) require 'georuby-ext' require 'progressbar' require 'geo_ruby/shp4r/shp' require 'nokogiri' require 'bzip2' # ActiveRecord::Base.logger = Logger.new("log/development.log") class OSMIndex attr_reader :index def initialize @index = Hash.new{|h, k| h[k] = []} end def save(file = "index") File.open(file, "w") do |f| # Recreate index to make marshallable f.write Marshal.dump(Hash[index]) end end def size index.size end def load(file) case file when /.osm.bz2/ Bzip2::Reader.open(file) do |f| # progress = ProgressBar.new("OSM indexation", File.size(osm_file)) #f_with_progress = ProgressiveIO.new(f) do |offset| # progress.set offset #end Nokogiri::XML::SAX::Parser.new(Handler.new(self, $stdout)).parse_io(f) $stdout.puts "" end save "#{File.basename(file, ".osm.bz2")}.tiger.index" else @index = Marshal.load(IO.read(file)) end end def [](tiger_id) index[tiger_id] end class Handler < Nokogiri::XML::SAX::Document attr_reader :index, :out def initialize(index, out = nil) @index = index @out = out @node_count = @way_count = @tiger_id_count = 0 end def start_element(name, attrs = []) case name when "node" @node_count += 1 when "way" @way_osm_id = attrs.assoc("id")[1].to_i @way_count += 1 when "tag" if @way_osm_id and attrs.assoc("k")[1] == "tiger:tlid" attrs.assoc("v")[1].scan(/\d+/).each do |tgid_id| tgid_id = tgid_id.to_i index[tgid_id] << @way_osm_id @tiger_id_count += 1 end end end show end def show if out and refresh_progress? out.write "Nodes: #{@node_count} Ways: #{@way_count} Tiger Ids: #{@tiger_id_count}\r" out.flush end end def refresh_progress? if @shown_at.nil? or (Time.now - @shown_at) > 10 @shown_at = Time.now true end end def end_element(name) if name == "way" @way_osm_id = nil end end end end osm_index = OSMIndex.new.load(osm_index_file = ARGV.shift) puts "Using OSM Index : #{osm_index_file} (#{osm_index.size} entries)" class TigerRecord attr_reader :shape_record @@osm_index = {} cattr_accessor :osm_index def initialize(shape_record) @shape_record = shape_record end def tiger_id shape_record.data["tlid"] end def osm_id osm_index[tiger_id] end def from_point @from_point ||= shape_record.geometry.first.first end def to_point @to_point ||= shape_record.geometry.last.last end def right_from_address shape_record.data["rfromadd"] end def left_from_address shape_record.data["lfromadd"] end def right_to_address shape_record.data["rtoadd"] end def left_to_address shape_record.data["ltoadd"] end def road @road ||= (osm_id and ActiveRoad::Base.find_by_objectid "osm:#{osm_id}") end def attributes [ { :number => right_from_address, :geometry => from_point }, { :number => left_from_address, :geometry => from_point }, { :number => right_to_address, :geometry => to_point }, { :number => left_from_address, :geometry => to_point } ] end def create_numbers attributes.each do |number_attributes| if number_attributes[:number].present? road.numbers.create! number_attributes end end if road end end TigerRecord.osm_index = osm_index until ARGV.empty? file = ARGV.shift GeoRuby::Shp4r::ShpFile.open(file) do |shape_file| progress = ProgressBar.new(file, shape_file.record_count) ActiveRoad::Base.transaction do shape_file.each_record do |shape| TigerRecord.new(shape).create_numbers progress.inc end end end end # osm_id = OSM::ActiveTODO.find_by_sql "select osm_id from france_osm_line where tlid && array[#{shape.tiger_id}]"; # road = ActiveRoad::Base.find_by_objectid "osm:#{osm_id}" # road.numbers.create :number => shape.rfromadd, :geometry => shape.the_geom.first.to_wgs84 # road.numbers.create :number => shape.rtoadd, :geometry => shape.the_geom.last.to_wgs84 # road.numbers.create :number => shape.lfromadd, :geometry => shape.the_geo.first.to_wgs84 # road.numbers.create :number => shape.ltoadd, :geometry => shape.the_geom.last.to_wgs84 # puts shape_file[0].data.inspect # puts shape_file[0].geometry.inspect