-
Notifications
You must be signed in to change notification settings - Fork 11
/
skeletron-generalize.py
95 lines (67 loc) · 3.26 KB
/
skeletron-generalize.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#!/usr/bin/env python
from json import load, JSONEncoder
from optparse import OptionParser
from itertools import repeat
from re import compile
import logging
from Skeletron.output import generalize_geojson_feature
float_pat = compile(r'^-?\d+\.\d+(e-?\d+)?$')
charfloat_pat = compile(r'^[\[,\,]-?\d+\.\d+(e-?\d+)?$')
earth_radius = 6378137
optparser = OptionParser(usage="""%prog [options] <geojson input file> <geojson output file>
Accepts GeoJSON input and generates GeoJSON output.""")
defaults = dict(zoom=12, width=15, single=False, loglevel=logging.INFO)
optparser.set_defaults(**defaults)
optparser.add_option('-z', '--zoom', dest='zoom',
type='int', help='Zoom level. Default value is %s.' % repr(defaults['zoom']))
optparser.add_option('-w', '--width', dest='width',
type='float', help='Line width at zoom level. Default value is %s.' % repr(defaults['width']))
optparser.add_option('-s', '--single', dest='single',
action='store_true',
help='Convert multi-geometries into single geometries on output.')
optparser.add_option('-v', '--verbose', dest='loglevel',
action='store_const', const=logging.DEBUG,
help='Output extra progress information.')
optparser.add_option('-q', '--quiet', dest='loglevel',
action='store_const', const=logging.WARNING,
help='Output no progress information.')
if __name__ == '__main__':
options, (input_file, output_file) = optparser.parse_args()
logging.basicConfig(level=options.loglevel, format='%(levelname)08s - %(message)s')
#
# Input
#
input = load(open(input_file, 'r'))
features = []
for (index, input_feature) in enumerate(input['features']):
try:
feature = generalize_geojson_feature(input_feature, options.width, options.zoom)
if not feature:
continue
except Exception, err:
logging.error('Error on feature #%d: %s' % (index, err))
else:
if options.single and feature['geometry']['type'].startswith('Multi'):
coord = [part for part in feature['geometry']['coordinates']]
types = repeat(feature['geometry']['type'][5:])
props = repeat(feature['properties'])
features.extend([dict(type='Feature', geometry=dict(coordinates=coords, type=type), properties=prop)
for (coords, type, prop) in zip(coord, types, props)])
else:
features.append(feature)
#
# Output
#
geojson = dict(type='FeatureCollection', features=filter(None, features))
output = open(output_file, 'w')
encoder = JSONEncoder(separators=(',', ':'))
encoded = encoder.iterencode(geojson)
for token in encoded:
if charfloat_pat.match(token):
# in python 2.7, we see a character followed by a float literal
output.write(token[0] + '%.5f' % float(token[1:]))
elif float_pat.match(token):
# in python 2.6, we see a simple float literal
output.write('%.5f' % float(token))
else:
output.write(token)