source: subversion/applications/utils/export/osm2kml/osm2kml.py @ 28865

Last change on this file since 28865 was 1846, checked in by joerg, 13 years ago

set executable property

  • Property svn:executable set to *
File size: 6.6 KB
Line 
1#!/opt/python-2_5/bin/python
2
3import sys,xml.sax
4from xml.sax.handler import ContentHandler
5#from cElementTree import Element, SubElement, ElementTree
6from optparse import OptionParser
7
8exportTags = [ ("name","varchar(64)"),
9               ("place","varchar(32)"),
10               ("landuse","varchar(32)"),
11               ("leisure","varchar(32)"),
12               ("waterway","varchar(32)"),
13               ("highway","varchar(32)"),
14               ("amenity","varchar(32)"),
15               ("tourism","varchar(32)"),
16               ("learning","varchar(32)")
17               ]
18segments = {}
19table_name = "planet_osm"
20
21class osm2sql (ContentHandler):
22    def __init__(self,fh):
23        ContentHandler.__init__(self)
24        self.fh = fh
25    def startDocument (self):
26        self.node = {}
27        self.stack = []
28    def startElement(self,name,attr):
29        if name == 'node':
30            self.node[attr["id"]] = (attr["lon"], attr["lat"])
31            self.stack.append({'type':'node','id':attr["id"],'tags':{}})
32        elif name == 'segment':
33            from_node = self.node[attr["from"]]
34            to_node   = self.node[attr["to"]]
35            segments[attr["id"]] = from_node,to_node
36        elif name == 'tag':
37            k = attr['k'].replace(":","_").replace(" ","_")
38            v = attr['v']
39            self.stack.append((k,v))
40        elif name == 'way':
41            self.stack.append({'type':'way','id':attr["id"],'segs': [],'tags':{}})
42        elif name == 'seg':
43            self.stack[-1]['segs'].append(attr["id"])
44           
45    def endElement (self,name):
46        if name == 'segment':
47            pass
48        elif name == 'node':
49            node = self.stack.pop()
50            osm_id = node['id']
51
52            if 'name' in node['tags']: # only create POINT feature if node has a name
53                xml = u'''    <Placemark>
54      <name>%s</name>
55      <Point>
56        <coordinates>%s,%s,0</coordinates>
57      </Point>
58    </Placemark>
59''' % (node['tags'].get('name',str(node['tags'])), self.node[osm_id][0], self.node[osm_id][1])
60                print xml.encode("UTF-8")
61
62        elif name == 'tag':
63            tag = self.stack.pop()
64            if len(self.stack) > 0 :
65                if 'type' in self.stack[-1] and ( self.stack[-1]['type'] == 'way' or self.stack[-1]['type'] == 'node') :
66                    self.stack[-1]['tags'][tag[0]] = tag[1]
67               
68        elif name == 'way':
69            way = self.stack.pop()
70            osm_id = way['id']
71            fields = ",".join(["%s" % f[0] for f in exportTags])
72            polygon = False
73            values = []
74            closetags=""
75            for tag in exportTags:
76                if tag[0] in way['tags']:
77                    if tag[0] == 'landuse' or tag[0] == 'leisure':
78                        polygon = True
79                    values.append("$$%s$$" % way['tags'][tag[0]])
80                else:
81                    values.append("$$$$")
82            values = ",".join(values)
83
84            if polygon:
85              print '''        <Polygon>
86      <name>%s</name>
87      <!-- specific to Polygon -->
88      <extrude>0</extrude>                       <!-- boolean -->
89      <tessellate>0</tessellate>                 <!-- boolean -->
90      <altitudeMode>clampToGround</altitudeMode>
91        <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
92      <outerBoundaryIs>
93        <LinearRing>
94          <coordinates>''' % way['tags'].get('name',str(way['tags']))
95              closetags=u'''        </coordinates>
96        </LinearRing>
97      </outerBoundaryIs>
98    </Polygon>'''
99            else:
100              print u'''    <Placemark>
101      <name>%s</name>
102      <MultiGeometry>
103      <LineString>
104        <extrude>0</extrude>                   <!-- boolean -->
105        <tessellate>0</tessellate>             <!-- boolean -->
106        <altitudeMode>clampToGround</altitudeMode>
107            <!-- kml:altitudeModeEnum: clampToGround, relativeToGround, or absolute -->
108        <coordinates>''' % way['tags'].get('name',str(way['tags']))
109              closetags=u'''        </coordinates>
110      </LineString>
111      </MultiGeometry>
112    </Placemark>'''
113
114
115            wkt,status = self.WKT(way,polygon)
116            if status :
117                sql = wkt
118                print sql.encode("UTF-8")
119            else:
120                for s in way['segs']:
121                    try:
122                        from_node,to_node = segments[s]
123                        sql = '%s,%s,0 %s,%s,0' % (from_node[0],from_node[1],to_node[0],to_node[1]) 
124                        print sql.encode("UTF-8")
125                    except:
126                        pass
127
128            print closetags
129    def WKT(self,way, polygon=False):
130        first = True
131        wkt = ""
132
133        max = len(way['segs']) * len(way['segs'])
134        i = 0
135        while way['segs'] and i < max:
136            id = way['segs'].pop()
137            i+=1
138            if id in segments:
139                from_node,to_node = segments[id]
140                x0 = from_node[0]
141                y0 = from_node[1]
142                x1 = to_node[0]
143                y1 = to_node[1]
144           
145                if first:
146                    first = False
147                    start_x = x0
148                    start_y = y0
149                    end_x = x1
150                    end_y = y1
151                    wkt = '%s,%s,0 %s,%s,0' % (x0,y0,x1,y1)
152                else:
153                    if (start_x == x0) and (start_y == y0) :
154                        start_x = x1
155                        start_y = y1
156                        wkt ='%s,%s,0 ' % (x1,y1) + wkt
157                    elif (start_x == x1) and (start_y == y1) :
158                        start_x = x0
159                        start_y = y0
160                        wkt ='%s,%s,0 ' % (x0,y0) + wkt
161                    elif (end_x == x0) and (end_y == y0) :
162                        end_x = x1
163                        end_y = y1
164                        wkt += ' %s,%s,0' % (x1,y1)
165                    elif (end_x == x1) and (end_y == y1) :
166                        end_x = x0
167                        end_y = y0
168                        wkt += ' %s,%s,0' % (x0,y0)
169                    else:
170                        way['segs'].insert(0,id)
171           
172        if polygon:
173            wkt = wkt + " %s,%s,0" % (start_x,start_y)
174        if way['segs']:
175            return wkt,False
176        else:
177            return wkt,True
178           
179if __name__ == "__main__":
180    parser = osm2sql(sys.stdout)
181    fields = ",".join(["%s %s" % (tag[0],tag[1]) for tag in exportTags])
182    print '''<?xml version="1.0" encoding="UTF-8"?>
183<kml xmlns="http://earth.google.com/kml/2.1">
184  <Folder>
185    <name>Open Street Map Export</name>'''
186    xml.sax.parse(sys.stdin,parser)
187    print '''  </Folder>
188</kml>'''
Note: See TracBrowser for help on using the repository browser.