osmlinzaddr.py 4.57 KB
Newer Older
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
1 2 3

# Currently python2 because pyspatialite is 2 only

4
""" OSM LINZ Address
5
Usage: my_program.py [-h -o DIRECTORY --min-nodes=COUNT --max-nodes=COUNT --include-location=LEVEL] [-d DATABASE]
6 7 8 9

Options:
  -d DATABASE --database DATABASE  spatialite database containing linz_addr table [default: osmlinzaddr.sqlite]
  -h --help    show this
10
  -o DIRECTORY --output=DIRECTORY   Specify output directory. [default: linz_places]
11 12
  --min-nodes=COUNT  Minimum number of nodes per output file. [default: 1]
  --max-nodes=COUNT  Maximum number of nodes per output file. [default: 8000]
13
  --include-location=LEVEL  1:Include suburb/hamlet 2: and city tags in output. [default: 1]
14
"""
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
15

16
from __future__ import print_function, division, unicode_literals
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
17
from lxml import etree as ET
18
from docopt import docopt
19
# import itertools
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
20 21
import os
import pyspatialite.dbapi2 as db
22
# import sys
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
23 24


25 26 27 28
def add_tag(node, k, v):
    ET.SubElement(node, "tag", k=k, v=v)


Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
29
def generate_osmchange(dbfile, outdir,
30 31 32
            changeset=1,
            min_nodes=1, max_nodes=8000,
            include_location=False):
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
33 34 35 36 37 38 39 40 41

    try:
        os.makedirs(outdir)
    except OSError:
        pass

    con = db.connect(dbfile)
    cur = con.cursor()

42 43 44
    # Select subsets by place
    q = 'select * from places'
    places = list(cur.execute(q))
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
45

46 47 48
    with open(outdir + '/file_list.csv', 'w') as f:
        f.write('place, num_addresses, uploader, date\n')

49 50 51
    for place in places:
        generate_osmchange_place(place, cur, outdir,
            changeset, include_location)
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
52 53


54
def generate_josm_tags_place(place, fn, outdir='.', source_rev='66'):
55 56 57 58 59 60 61 62 63 64
    tags = []
    tags.append('created_by=https://git.nzoss.org.nz/ewblen/osmlinzaddr/blob/master/osmlinzaddr.py')
    tags.append('attribution=https://wiki.openstreetmap.org/wiki/Contributors#LINZ')
    tags.append('source=https://data.linz.govt.nz/layer/3353-nz-street-address')
    tags.append('source:revision=%s' % source_rev)
    tags.append('comment=LINZ address import %s' % fn)
    tags.append('')
    path = outdir + "/%s.changeset_tags" % fn
    with open(path, 'w') as f:
        f.write('\n'.join(tags))
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
65 66


67
def generate_osmchange_place(place, dbcursor, outdir,
68
                            changeset, include_location):
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
69

70
    if place[0] is None:
71
        q = '''select linz_id, housenumber, street, x, y from linz_not_osm
72
        where city is NULL and suburb="{1}"
73 74
        '''.format(*(place))
    else:
75
        q = '''select linz_id, housenumber, street, x, y from linz_not_osm
76
        where city="{0}" and suburb="{1}"
77
        '''.format(*(place))
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
78

79
    rows = dbcursor.execute(q)
80

81
    lrows = list(rows)
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
82

83
    city, suburb = place[0:2]
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
84

85
    if city is None:
86 87 88 89 90
        fn = suburb
    else:
        fn = city + '-' + suburb
    fn = fn.replace(' ', '_')
    fn = fn.replace('/', '_')
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
91

92 93 94 95 96 97 98 99
    with open(outdir + '/file_list.csv', 'a') as f:
        f.write('%s,%d\n' % (fn, len(lrows)))
    # keep track of empty (complete) places too

    if not len(lrows):
        print("No addresses in %s!?" % str(place))
        return

100
    path = outdir + "/%s.osc" % fn
101
    print("%s : %d nodes" % (fn, len(lrows)))
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
102

103 104
    # generate_changeset_place(place, fn, outdir)
    generate_josm_tags_place(place, fn, outdir)
105

106 107
    osmchange = ET.Element('osmChange', version="0.6",
        generator="osmlinzaddr.py")
108

109
    for r in lrows:
110 111 112
        (linz_id, housenumber, street, lon, lat) = r
        if lon > 180.0:
            lon = lon - 360
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
113 114 115

        create = ET.SubElement(osmchange, "create")
        dnode = {
116 117
            'id': "-%d" % linz_id,
            'changeset': '0',
118 119
            'lat': "%8.8f" % lat,
            'lon': "%8.8f" % lon,
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
120 121 122
        }

        node = ET.SubElement(create, "node", dnode)
123
        add_tag(node, "ref:linz:address_id", str(linz_id))
124
        add_tag(node, "addr:housenumber", housenumber)
125
        add_tag(node, "addr:street", street)
126 127 128 129 130 131 132
        if include_location:
            if city is not None:
                if include_location > 1:
                    add_tag(node, "addr:city", city)
                add_tag(node, "addr:suburb", suburb)
            else:
                add_tag(node, "addr:hamlet", suburb)
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
133

134 135
    tree = ET.ElementTree(osmchange)
    tree.write(path, pretty_print=True)
Eliot Blennerhassett's avatar
Eliot Blennerhassett committed
136 137 138


if __name__ == '__main__':
139
    opts = docopt(__doc__, version='osmlinzaddr v0.1')
140 141 142 143 144
    for k in opts.keys():
        try:
            opts[k] = int(opts[k])
        except:
            pass
145 146
    print(opts)
    if True:
147 148 149 150 151 152 153
        generate_osmchange(
            opts['--database'],
            opts['--output'],
            min_nodes=opts['--min-nodes'],
            max_nodes=opts['--max-nodes'],
            include_location=opts['--include-location']
        )