source: subversion/applications/routing/pyroute/compress/compress.py @ 33911

Last change on this file since 33911 was 5998, checked in by ojw, 13 years ago

storing nodes in ways. bit more detection of volatile values

  • Property svn:executable set to *
File size: 4.3 KB
Line 
1#!/usr/bin/python
2#----------------------------------------------------------------
3#
4#------------------------------------------------------
5# Usage:
6#
7#------------------------------------------------------
8# Copyright 2007, Oliver White
9#
10# This program is free software: you can redistribute it and/or modify
11# it under the terms of the GNU General Public License as published by
12# the Free Software Foundation, either version 3 of the License, or
13# (at your option) any later version.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License
21# along with this program.  If not, see <http://www.gnu.org/licenses/>.
22#------------------------------------------------------
23import sys
24import os
25from xml.sax import make_parser, handler
26import xml
27from struct import *
28
29class BinaryOsm(handler.ContentHandler):
30 
31  def __init__(self):
32    pass
33   
34  def encode(self, filename, output):
35    self.nextKID = 3
36    self.nextVID = 1
37    self.tags = {}
38    self.values = {}
39   
40    if(not os.path.exists(filename)):
41      print "No such data file %s" % filename
42      return
43    try:
44      self.out = open(output, "wb")
45      parser = make_parser()
46      parser.setContentHandler(self)
47      parser.parse(filename)
48      self.out.write("X")
49      self.out.close()
50    except xml.sax._exceptions.SAXParseException:
51      print "Error loading %s" % filename
52
53  def startElement(self, name, attrs):
54    """Handle XML elements"""
55    if(name =='node'):
56      self.meta = { \
57        'id':int(attrs.get('id')),
58        'lon':float(attrs.get('lat')),
59        'lat':float(attrs.get('lon'))
60        }
61      self.tags = {}
62    elif(name == 'way'):
63      self.meta = {'id':int(attrs.get('id'))}
64      self.tags = {}
65      self.waynodes = []
66    elif(name == 'relation'):
67      self.tags = {}
68    elif name == 'nd':
69      """Nodes within a way -- add them to a list"""
70      self.waynodes.append(int(attrs.get('ref')))
71    elif name == 'tag':
72      """Tags - store them in a hash"""
73      k,v = (attrs.get('k'), attrs.get('v'))
74      if not k in ('created_by'):
75        self.tags[k] = v
76 
77  def endElement(self, name):
78    """Handle ways in the OSM data"""
79    writeTags = False
80    if(name =='node'):
81      data = 'N' + pack("L", self.meta['id']) + self.encodeLL(self.meta['lat'], self.meta['lon'])
82      self.out.write(data)
83      writeTags = True
84   
85    elif(name == 'way'):
86      data = 'W' + pack("L", self.meta['id'])
87      self.out.write(data)
88      self.out.write(pack('H', len(self.waynodes)))
89      for n in self.waynodes:
90        self.out.write(pack('L', n))
91      writeTags = True
92     
93    if(writeTags):
94      n = len(self.tags.keys())
95      if(n > 255):
96        # TODO:
97        print "Error: more than 255 tags on an item"
98        return
99      self.out.write(pack('B', n))
100      for k,v in self.tags.items():
101        self.encodeTag(k, False, k)
102        volatile = k in ('name','ref','ncn_ref','note','notes','description','ele','time','url','website','postal_code','image','source_ref','source:ref','source:name','source_ref:name',"FIXME","fixme","place_numbers")
103        self.encodeTag(v,volatile,k)
104
105  def encodeTag(self,text,volatile,key):
106    text = text.encode('utf8')
107    if(not volatile):
108      try:
109        ID = self.values[text]
110        self.out.write(pack('H', ID))
111      except KeyError:
112        if(self.nextKID >= 65535):
113          # TODO
114          print "Error: too many stored tags!"
115          sys.exit()
116        print "%d: %s %s" % (self.nextKID, key,text)
117        self.values[text] = self.nextKID
118        self.out.write(pack('HHB', 1, self.nextKID, len(text)))
119        self.out.write(text)
120        self.nextKID = self.nextKID + 1
121    else:
122      self.out.write(pack('HB', 0, len(text)))
123      self.out.write(text)
124      #print "Storing simple %s" % (text)
125
126  def encodeLL(self,lat,lon):
127    pLat = (lat + 90.0) / 180.0 
128    pLon = (lon + 180.0) / 360.0 
129    iLat = self.encodeP(pLat)
130    iLon = self.encodeP(pLon)
131    return(pack("II", iLat, iLon))
132   
133  def encodeP(self,p):
134    i = int(p * 4294967296.0)
135    return(i)
136   
137# Parse the supplied OSM file
138if __name__ == "__main__":
139  print "Loading data..."
140  Binary = BinaryOsm()
141  Binary.encode(sys.argv[1], sys.argv[2])
Note: See TracBrowser for help on using the repository browser.