-
Notifications
You must be signed in to change notification settings - Fork 0
/
ocitysmap2-render
executable file
·241 lines (209 loc) · 9.76 KB
/
ocitysmap2-render
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
#!/usr/bin/env python
# -*- coding: utf-8; mode: Python -*-
# ocitysmap, city map and street index generator from OpenStreetMap data
# Copyright (C) 2009 David Decotigny
# Copyright (C) 2009 Frédéric Lehobey
# Copyright (C) 2009 David Mentré
# Copyright (C) 2009 Maxime Petazzoni
# Copyright (C) 2009 Thomas Petazzoni
# Copyright (C) 2009 Gaël Utard
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or any later version.
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
__version__ = '0.1'
import logging
import optparse
import sys, os
import ocitysmap2
import ocitysmap2.layoutlib.renderers
from coords import BoundingBox
def main():
logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
# Paper sizes, sorted in increasing widths
KNOWN_PAPER_SIZE_NAMES = \
map(lambda p: p[0],
sorted(ocitysmap2.layoutlib.PAPER_SIZES,
key=lambda p: p[1]))
# Known renderer names
KNOWN_RENDERERS_NAMES = \
map(lambda r: "%s (%s)" % (r.name, r.description),
ocitysmap2.layoutlib.renderers.get_renderers())
# Known paper orientations
KNOWN_PAPER_ORIENTATIONS = ['portrait', 'landscape']
usage = '%prog [options] [-b <lat1,long1 lat2,long2>|--osmid <osmid>]'
parser = optparse.OptionParser(usage=usage,
version='%%prog %s' % __version__)
parser.add_option('-C', '--config', dest='config_file', metavar='FILE',
help='Specify the location of the config file.')
parser.add_option('-p', '--prefix', dest='output_prefix', metavar='PREFIX',
help='Specify the prefix of generated files. '
'Defaults to "citymap".',
default='citymap')
parser.add_option('-f', '--format', dest='output_formats', metavar='FMT',
help='Specify the output formats. Supported file '
'formats: svg, svgz, pdf, ps, ps.gz, png, and csv. '
'Defaults to PDF. May be specified multiple times.',
action='append')
parser.add_option('-t', '--title', dest='output_title', metavar='TITLE',
help='Specify the title displayed in the output files.',
default="My Map")
parser.add_option('--osmid', dest='osmid', metavar='OSMID',
help='OSM id representing the polygon of the city '
'to render.', type="int"),
parser.add_option('-b', '--bounding-box', dest='bbox', nargs=2,
metavar='LAT1,LON1 LAT2,LON2',
help='Bounding box (EPSG: 4326).')
parser.add_option('-L', '--language', dest='language',
metavar='LANGUAGE_CODE',
help='Language to use when generating the index'
' (default=fr_FR.UTF-8).',
default='fr_FR.UTF-8')
parser.add_option('-s', '--stylesheet', dest='stylesheet',
metavar='NAME',
help="Name of the stylesheet to use. Defaults to the "
"first specified in the config file.")
parser.add_option('-l', '--layout', dest='layout',
metavar='NAME',
default=KNOWN_RENDERERS_NAMES[0].split()[0],
help= ("Name of the layout to use, among %s. Default: %s."
% (', '.join(KNOWN_RENDERERS_NAMES),
KNOWN_RENDERERS_NAMES[0].split()[0])))
parser.add_option('--paper-format', metavar='FMT',
help='Either "default", or one of %s.'\
% ', '.join(KNOWN_PAPER_SIZE_NAMES),
default='default')
parser.add_option('--orientation', metavar='ORIENTATION',
help='Either "portrait" or "landscape".',
default='portrait')
(options, args) = parser.parse_args()
if len(args):
parser.print_help()
return 1
# Make sure either -b or -c is given
optcnt = 0
for var in options.bbox, options.osmid:
if var:
optcnt += 1
if optcnt == 0:
parser.error("One of --bounding-box "
"or --osmid is mandatory")
if optcnt > 1:
parser.error("Options --bounding-box "
"or --osmid are exclusive")
# Parse config file and instanciate main object
mapper = ocitysmap2.OCitySMap([options.config_file
or os.path.join(os.environ["HOME"],
'.ocitysmap.conf')])
# Parse bounding box arguments when given
bbox = None
if options.bbox:
try:
bbox = BoundingBox.parse_latlon_strtuple(options.bbox)
except ValueError:
parser.error('Invalid bounding box!')
# Check that latitude and langitude are different
lat1, lon1 = bbox.get_top_left()
lat2, lon2 = bbox.get_bottom_right()
if lat1 == lat2:
parser.error('Same latitude in bounding box corners')
if lon1 == lon2:
parser.error('Same longitude in bounding box corners')
# Parse OSM id when given
if options.osmid:
try:
bbox = BoundingBox.parse_wkt(
mapper.get_geographic_info(options.osmid)[0])
except LookupError:
parser.error('No such OSM id: %d' % options.osmid)
# Parse stylesheet (defaults to 1st one)
if options.stylesheet is None:
stylesheet = mapper.get_all_style_configurations()[0]
else:
try:
stylesheet = mapper.get_stylesheet_by_name(options.stylesheet)
except LookupError, ex:
parser.error("%s. Available stylesheets: %s."
% (ex, ', '.join(map(lambda s: "%s (%s)"
% (s.name, s.description),
mapper.STYLESHEET_REGISTRY))))
# Parse rendering layout
if options.layout is None:
cls_renderer = ocitysmap2.layoutlib.renderers.get_renderers()[0]
else:
try:
cls_renderer = ocitysmap2.layoutlib.renderers.get_renderer_class_by_name(options.layout)
except LookupError, ex:
parser.error("%s\nAvailable layouts: %s."
% (ex, ', '.join(map(lambda lo: "%s (%s)"
% (lo.name, lo.description),
ocitysmap2.layoutlib.renderers.get_renderers()))))
# Output file formats
if not options.output_formats:
options.output_formats = ['pdf']
options.output_formats = set(options.output_formats)
# Reject output formats that are not supported by the renderer
compatible_output_formats = cls_renderer.get_compatible_output_formats()
for format in options.output_formats:
if format not in compatible_output_formats:
parser.error("Output format %s not supported by layout %s" %
(format, cls_renderer.name))
# Parse paper size
if (options.paper_format != 'default') \
and options.paper_format not in KNOWN_PAPER_SIZE_NAMES:
parser.error("Invalid paper format. Allowed formats = default, %s"
% ', '.join(KNOWN_PAPER_SIZE_NAMES))
# Determine actual paper size
compat_papers = cls_renderer.get_compatible_paper_sizes(bbox)
if not compat_papers:
parser.error("No paper size compatible with this rendering.")
paper_descr = None
if options.paper_format == 'default':
for p in compat_papers:
if p[5]:
paper_descr = p
break
else:
# Make sure the requested paper size is in list
for p in compat_papers:
if p[0] == options.paper_format:
paper_descr = p
break
if not paper_descr:
parser.error("Requested paper format not compatible with rendering. Compatible paper formats are: %s."
% ', '.join(map(lambda p: "%s (%.1fx%.1fcm²)"
% (p[0], p[1]/10., p[2]/10.),
compat_papers)))
assert paper_descr[3] or paper_descr[4] # Portrait or Landscape accepted
# Validate requested orientation
if options.orientation not in KNOWN_PAPER_ORIENTATIONS:
parser.error("Invalid paper orientation. Allowed orientations: %s"
% KNOWN_PAPER_ORIENTATIONS)
if (options.orientation == 'portrait' and not paper_descr[3]) or \
(options.orientation == 'landscape' and not paper_descr[4]):
parser.error("Requested paper orientation %s not compatible with this rendering at this paper size." % options.orientation)
# Prepare the rendering config
rc = ocitysmap2.RenderingConfiguration()
rc.title = options.output_title
rc.osmid = options.osmid or None # Force to None if absent
rc.bounding_box = bbox
rc.language = options.language
rc.stylesheet = stylesheet
if options.orientation == 'portrait':
rc.paper_width_mm = paper_descr[1]
rc.paper_height_mm = paper_descr[2]
else:
rc.paper_width_mm = paper_descr[2]
rc.paper_height_mm = paper_descr[1]
# Go !...
mapper.render(rc, cls_renderer.name, options.output_formats,
options.output_prefix)
return 0
if __name__ == '__main__':
sys.exit(main())