Skip to content

Commit 70c622d

Browse files
committed
split Nik4Image.setup_options into multiple methods
1 parent 2a40f8b commit 70c622d

File tree

4 files changed

+70
-59
lines changed

4 files changed

+70
-59
lines changed

nik4.py

Lines changed: 3 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -126,35 +126,6 @@ def prepare_wld(bbox, mwidth, mheight):
126126
]])
127127

128128

129-
def get_paper_size(name):
130-
"""Returns paper size for name, [long, short] sides in mm"""
131-
# ISO A*
132-
m = re.match(r'^a?(\d)$', name)
133-
if m:
134-
return [math.floor(1000 / 2**((2*int(m.group(1)) - 1) / 4.0) + 0.2),
135-
math.floor(1000 / 2**((2*(int(m.group(1)) + 1) - 1) / 4.0) + 0.2)]
136-
# ISO B*
137-
m = re.match(r'^b(\d)$', name)
138-
if m:
139-
return [math.floor(1000 / 2**((int(m.group(1)) - 1) / 2.0) + 0.2),
140-
math.floor(1000 / 2**(int(m.group(1)) / 2.0) + 0.2)]
141-
# German extensions
142-
if name == '4a0':
143-
return [2378, 1682]
144-
if name == '2a0':
145-
return [1682, 1189]
146-
# US Legal
147-
if re.match(r'^leg', name):
148-
return [355.6, 215.9]
149-
# US Letter
150-
if re.match(r'^l', name):
151-
return [279.4, 215.9]
152-
# Cards
153-
if re.match(r'^c(?:re|ar)d', name):
154-
return [85.6, 54]
155-
return None
156-
157-
158129
def xml_vars(style, variables):
159130
"""Replace ${name:default} from style with variables[name] or 'default'"""
160131
# Convert variables to a dict
@@ -244,7 +215,7 @@ def run(options, settings):
244215
if options.fit:
245216
settings.bbox = layer_bbox(m, options.fit.split(','), settings.proj_target, settings.bbox)
246217
# here's where we can fix scale, no new bboxes below
247-
if settings.bbox and fix_scale:
218+
if settings.bbox and settings.fix_scale:
248219
settings.scale = settings.scale / math.cos(math.radians(settings.transform.backward(settings.bbox.center()).y))
249220
bbox_web_merc = Nik4Image.TRANSFORM_LONLAT_WEBMERC.forward(settings.transform.backward(settings.bbox))
250221
settings.correct_scale(bbox_web_merc)
@@ -255,7 +226,7 @@ def run(options, settings):
255226
else:
256227
tscale = min((settings.bbox.maxx - settings.bbox.minx) / max(settings.size[0], 0.01),
257228
(settings.bbox.maxy - settings.bbox.miny) / max(settings.size[1], 0.01))
258-
settings.bbox.pad(options.padding * ppmm * tscale)
229+
settings.bbox.pad(options.padding * settings.ppmm * tscale)
259230

260231
# bbox should be specified by this point
261232
if not settings.bbox:
@@ -409,7 +380,7 @@ def run(options, settings):
409380
else:
410381
log_level = logging.INFO
411382
logging.basicConfig(level=log_level, format='%(asctime)s %(message)s', datefmt='%H:%M:%S')
412-
settings = Nik4Image(options)
383+
settings = Nik4Image(options, HAS_CAIRO)
413384
settings.setup_options()
414385
logging.info(settings.__dict__)
415386
run(options, settings)

nik4/nik4_image.py

Lines changed: 36 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
# -*- coding: utf-8 -*-
22

33
import argparse
4-
import math
4+
import logging
55
import mapnik
6+
import math
7+
import re
8+
from nik4.paper_size import get_paper_size
69

710

811
VERSION = '1.7'
@@ -15,12 +18,14 @@
1518

1619
class Nik4Image:
1720

18-
def __init__(self, options):
21+
def __init__(self, options, has_cairo):
1922
self.options = options
23+
self.has_cairo = has_cairo
2024
self.need_cairo = False
2125
self.fmt = None
2226
self.ppmm = None
2327
self.scale = None
28+
self.fix_scale = False
2429
self.scale_factor = None
2530
self.size = None
2631
self.bbox = None
@@ -29,7 +34,7 @@ def __init__(self, options):
2934
self.rotate = None
3035

3136

32-
def parse_url(url, options):
37+
def _parse_url(self, url, options):
3338
"""Parse map URL into options map"""
3439
lat = None
3540
lon = None
@@ -81,11 +86,34 @@ def _set_ppm_and_scale_factor(self):
8186
self.ppmm = 90.7 / 25.4 * self.scale_factor
8287

8388
# svg / pdf can be scaled only in cairo mode
84-
if self.scale_factor != 1 and self.need_cairo and not HAS_CAIRO:
89+
if self.scale_factor != 1 and self.need_cairo and not self.has_cairo:
8590
logging.error('Warning: install pycairo for using --factor or --ppi')
8691
self.scale_factor = 1
8792
self.ppmm = 90.7 / 25.4
8893

94+
def _set_projections_and_transform(self):
95+
if self.options.projection.isdigit():
96+
self.proj_target = mapnik.Projection('+init=epsg:{}'.format(self.options.projection))
97+
else:
98+
self.proj_target = mapnik.Projection(self.options.projection)
99+
self.transform = mapnik.ProjTransform(PROJ_LONLAT, self.proj_target)
100+
101+
def _set_bbox_with_center_scale_and_size(self):
102+
# We don't know over which latitude range the bounding box spans, so we
103+
# first do everything in Web Mercator.
104+
center = TRANSFORM_LONLAT_WEBMERC.forward(mapnik.Coord(*self.options.center))
105+
w = self.size[0] * self.scale / 2
106+
h = self.size[1] * self.scale / 2
107+
bbox_web_merc = mapnik.Box2d(center.x-w, center.y-h, center.x+w, center.y+h)
108+
self.bbox = TRANSFORM_LONLAT_WEBMERC.backward(bbox_web_merc)
109+
self.bbox = self.transform.forward(self.bbox)
110+
# now correct the scale
111+
self.correct_scale(bbox_web_merc)
112+
center = self.transform.forward(mapnik.Coord(*self.options.center))
113+
w = self.size[0] * self.scale / 2
114+
h = self.size[1] * self.scale / 2
115+
self.bbox = mapnik.Box2d(center.x-w, center.y-h, center.x+w, center.y+h)
116+
89117
def setup_options(self):
90118
dim_mm = None
91119
self.rotate = not self.options.norotate
@@ -98,14 +126,10 @@ def setup_options(self):
98126
self._set_format()
99127

100128
if self.options.url:
101-
parse_url(self.options.url, self.options)
129+
self._parse_url(self.options.url, self.options)
102130

103131
# output projection
104-
if self.options.projection.isdigit():
105-
self.proj_target = mapnik.Projection('+init=epsg:{}'.format(self.options.projection))
106-
else:
107-
self.proj_target = mapnik.Projection(self.options.projection)
108-
self.transform = mapnik.ProjTransform(PROJ_LONLAT, self.proj_target)
132+
self._set_projections_and_transform()
109133

110134
# get image size in millimeters
111135
if self.options.paper:
@@ -145,7 +169,6 @@ def setup_options(self):
145169
self.bbox = self.options.bbox
146170

147171
# scale can be specified with zoom or with 1:NNN scale
148-
fix_scale = False
149172
if self.options.zoom:
150173
self.scale = 2 * 3.14159 * 6378137 / 2 ** (self.options.zoom + 8) / self.scale_factor
151174
elif self.options.scale:
@@ -157,7 +180,7 @@ def setup_options(self):
157180
elif self.options.bbox:
158181
self.scale = self.scale / math.cos(math.radians((self.options.bbox[3] + self.options.bbox[1]) / 2))
159182
else:
160-
fix_scale = True
183+
self.fix_scale = True
161184

162185
# all calculations are in EPSG:3857 projection (it's easier)
163186
if self.bbox:
@@ -168,20 +191,7 @@ def setup_options(self):
168191

169192
# calculate bbox through center, zoom and target size
170193
if not self.bbox and self.options.center and self.size and self.size[0] > 0 and self.size[1] > 0 and self.scale:
171-
# We don't know over which latitude range the bounding box spans, so we
172-
# first do everything in Web Mercator.
173-
center = TRANSFORM_LONLAT_WEBMERC.forward(mapnik.Coord(*self.options.center))
174-
w = self.size[0] * self.scale / 2
175-
h = self.size[1] * self.scale / 2
176-
bbox_web_merc = mapnik.Box2d(center.x-w, center.y-h, center.x+w, center.y+h)
177-
self.bbox = TRANSFORM_LONLAT_WEBMERC.backward(bbox_web_merc)
178-
self.bbox = self.transform.forward(self.bbox)
179-
# now correct the scale
180-
self.correct_scale(bbox_web_merc)
181-
center = self.transform.forward(mapnik.Coord(*self.options.center))
182-
w = self.size[0] * self.scale / 2
183-
h = self.size[1] * self.scale / 2
184-
self.bbox = mapnik.Box2d(center.x-w, center.y-h, center.x+w, center.y+h)
194+
self._set_bbox_with_center_scale_and_size()
185195

186196
def correct_scale(self, bbox_web_merc):
187197
# correct scale if output projection is not EPSG:3857

nik4/paper_size.py

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import math
2+
import re
3+
4+
def get_paper_size(name):
5+
"""Returns paper size for name, [long, short] sides in mm"""
6+
# ISO A*
7+
m = re.match(r'^a?(\d)$', name)
8+
if m:
9+
return [math.floor(1000 / 2**((2*int(m.group(1)) - 1) / 4.0) + 0.2),
10+
math.floor(1000 / 2**((2*(int(m.group(1)) + 1) - 1) / 4.0) + 0.2)]
11+
# ISO B*
12+
m = re.match(r'^b(\d)$', name)
13+
if m:
14+
return [math.floor(1000 / 2**((int(m.group(1)) - 1) / 2.0) + 0.2),
15+
math.floor(1000 / 2**(int(m.group(1)) / 2.0) + 0.2)]
16+
# German extensions
17+
if name == '4a0':
18+
return [2378, 1682]
19+
if name == '2a0':
20+
return [1682, 1189]
21+
# US Legal
22+
if re.match(r'^leg', name):
23+
return [355.6, 215.9]
24+
# US Letter
25+
if re.match(r'^l', name):
26+
return [279.4, 215.9]
27+
# Cards
28+
if re.match(r'^c(?:re|ar)d', name):
29+
return [85.6, 54]
30+
return None

tests/test_map_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def get_args_str(self):
1919
def get_settings(self, test_str):
2020
test_str += ' ' + self.get_args_str()
2121
options = self.parser.parse_args(shlex.split(test_str))
22-
settings = Nik4Image(options)
22+
settings = Nik4Image(options, True)
2323
settings.setup_options()
2424
return settings
2525

0 commit comments

Comments
 (0)