source: subversion/applications/utils/little-osm/readxml.rb @ 34318

Last change on this file since 34318 was 1519, checked in by imi, 13 years ago

little-osm now uses mysql geometry extension

  • Property svn:executable set to *
File size: 3.6 KB
Line 
1#!/usr/bin/ruby
2
3# Read in planet.osm and create a database "little-osm"
4
5$: << File.dirname(__FILE__)+"/../osm-data/lib"
6
7require 'osm/data'
8require 'rexml/document'
9require 'mysql'
10require 'time'
11
12
13module OSM
14  class Node < OsmPrimitive
15    def self.from_db uid, tags, time, reference, min, max
16                        min =~ /POINT\(([^ ]* [^)]*)\)/
17      Node.new $1.to_f, $2.to_f, OSM::uid_to_id(uid), time
18    end
19    def self.from_db_id uid
20      complete_node = $db.query("select uid, tags, time, reference, astext(min), astext(max) from data where uid=#{uid};").fetch_row
21      if complete_node.nil?
22        $current = nil
23        throw :incomplete
24      end
25      Node.from_db(*complete_node)
26    end
27  end
28 
29
30  # define load_references in segment and way, which replaces the id-references by their real data
31  class Segment < OsmPrimitive
32    def load_references
33      self.from = Node.from_db_id OSM::idclass_to_uid(self.from, Node)
34      self.to = Node.from_db_id OSM::idclass_to_uid(self.to, Node)
35    end
36    def self.from_db uid, tags, time, reference
37      fid, tid = reference.split ','
38      Segment.new(Node.from_db_id(fid.to_i), Node.from_db_id(tid.to_i), OSM::uid_to_id(uid).to_s, time)
39    end
40    def self.from_db_id uid
41      q = $db.query("select uid, tags, time, reference from data where uid=#{uid};").fetch_row
42      if q.nil?
43        $current = nil
44        throw :incomplete
45      end
46      Segment.from_db(*q)
47    end
48  end
49
50
51  class Way < OsmPrimitive
52    def load_references
53      self.segments.collect! do |id|
54        Segment.from_db_id OSM::idclass_to_uid(id, Segment)
55      end
56    end
57  end
58end
59
60# writes the data object into the database.
61def write_sql data
62  tags = data.tags ? data.tags.to_a.join("\n") : "null"
63  tags.gsub!(/\"/, '')
64  if (data.timestamp)
65    time = data.timestamp.xmlschema
66    time = time[0..-7] if time.include? "+"
67    time = 'TIMESTAMP("'+time+'")'
68        else
69                time = 'NULL'
70  end
71  case data.class.name
72  when "OSM::Node"
73        reference = ""
74  when "OSM::Segment"
75        reference = OSM::idclass_to_uid(data.from, OSM::Node).to_s + "," + OSM::idclass_to_uid(data.to, OSM::Node).to_s
76        data.load_references
77  when "OSM::Way"
78        reference = data.segments.collect {|s| OSM.idclass_to_uid(s, OSM::Segment).to_s}.join ','
79        data.load_references
80  end
81  sql = %Q{insert into data values (#{data.to_uid}, "#{tags}", #{time}, "#{reference}", GeomFromText('POINT(#{data.bbox[0..1].join(' ')})'), GeomFromText('POINT(#{data.bbox[2..3].join(' ')})'));}
82        $db.query sql
83end
84
85# parses the input data and call to write_sql for each object.
86class XmlReader
87  def method_missing sym, *args; end
88  def tag_start name, a
89    time = Time.parse(a['timestamp']) if a.include? 'timestamp'
90    id = a['id'].to_i
91
92    case name
93    when "node"
94      @current = OSM::Node.new :lat => a['lat'].to_f, :lon => a['lon'].to_f, :id => id, :timestamp => time
95    when "segment"
96      @current = OSM::Segment.new :from => a['from'].to_i, :to => a['to'].to_i, :id => id, :timestamp => time
97    when "way"
98      @current = OSM::Way.new :segments => [], :id => id, :timestamp => time
99    when "tag"
100      @current[a['k']] = a['v']
101    when "seg"
102      @current.segments << a['id'].to_i
103    end
104  end
105
106  def tag_end name
107    catch :incomplete do
108                        return unless name =~ /node|segment|way/
109                        $obj = $obj + 1
110                        puts $obj if $obj % 100000 == 0
111      write_sql @current
112    end
113  end
114end
115
116$obj = 0
117
118puts Time.now
119$stdout.flush
120$stdout.sync = true
121abort "planet.osm not found." unless File.exist? "planet.osm"
122$db = Mysql.real_connect "localhost", "root", "", "little-osm"
123$db.query "delete from data;"
124REXML::Document.parse_stream File.new('planet.osm'), XmlReader.new
Note: See TracBrowser for help on using the repository browser.