Fix scale computations to ensure a minimum zoom level

Signed-off-by: Gael UTARD <gael.utard@kisis.fr>
stable
Gael UTARD 2012-04-10 15:48:41 +02:00 zatwierdzone przez Thomas Petazzoni
rodzic a6906098a6
commit 13615f7eaa
3 zmienionych plików z 39 dodań i 36 usunięć

Wyświetl plik

@ -60,9 +60,10 @@ class Renderer:
GRID_LEGEND_MARGIN_RATIO = .02
# The DEFAULT_KM_IN_MM represents the minimum acceptable size in milimeters
# on the rendered map of a kilometer
DEFAULT_KM_IN_MM = 100
# The DEFAULT_KM_IN_MM represents the minimum acceptable mapnik scale
# 12000 ensures that the zoom level will be 16 or higher
# see entities.xml.inc file from osm style sheet
DEFAULT_SCALE = 12000
def __init__(self, db, rc, tmpdir, dpi):
"""
@ -265,15 +266,14 @@ class Renderer:
return [ "png", "svgz", "pdf", "csv" ]
@staticmethod
def get_compatible_paper_sizes(bounding_box, resolution_km_in_mm):
def get_compatible_paper_sizes(bounding_box, scale):
"""Returns a list of the compatible paper sizes for the given bounding
box. The list is sorted, smaller papers first, and a "custom" paper
matching the dimensions of the bounding box is added at the end.
Args:
bounding_box (coords.BoundingBox): the map geographic bounding box.
resolution_km_in_mm (int): size of a geographic kilometer in
milimeters on the rendered map.
scale (int): minimum mapnik scale of the map.
Returns a list of tuples (paper name, width in mm, height in
mm, portrait_ok, landscape_ok, is_default). Paper sizes are

Wyświetl plik

@ -78,7 +78,15 @@ class MultiPageRenderer(Renderer):
self._usable_area_height_pt = (self.paper_height_pt -
(2 * Renderer.PRINT_SAFE_MARGIN_PT))
scale_denom = 10000
scale_denom = Renderer.DEFAULT_SCALE
# the mapnik scale depends on the latitude
lat = self.rc.bounding_box.get_top_left()[0]
scale_denom *= math.cos(math.radians(lat))
# by convention, mapnik uses 90 ppi whereas cairo uses 72 ppi
scale_denom *= float(72) / 90
GRAYED_MARGIN_MM = 10
OVERLAP_MARGIN_MM = 20
@ -671,6 +679,8 @@ class MultiPageRenderer(Renderer):
for map_number, (canvas, grid) in enumerate(self.pages):
rendered_map = canvas.get_rendered_map()
LOG.debug('Mapnik scale: 1/%f' % rendered_map.scale_denominator())
LOG.debug('Actual scale: 1/%f' % canvas.get_actual_scale())
mapnik.render(rendered_map, ctx)
# Place the vertical and horizontal square labels
@ -711,17 +721,6 @@ class MultiPageRenderer(Renderer):
cairo_surface.flush()
# Convert a length in geometric meters (in the real life) into a
# length in paper millimiters (as drawn on the map).
def _geo_m_to_paper_mm(self, geo_m):
return geo_m / 1000.0 * Renderer.DEFAULT_KM_IN_MM * 2
def _paper_mm_to_geo_m(self, paper_mm):
return paper_mm * 1000.0 / (Renderer.DEFAULT_KM_IN_MM * 2)
def _paper_pt_to_geo_m(self, paper_pt):
return self._paper_mm_to_geo_m(commons.convert_pt_to_mm(paper_pt))
# In multi-page mode, we only render pdf format
@staticmethod
def get_compatible_output_formats():
@ -732,7 +731,7 @@ class MultiPageRenderer(Renderer):
# The default paper size is A4 portrait
@staticmethod
def get_compatible_paper_sizes(bounding_box,
resolution_km_in_mm=Renderer.DEFAULT_KM_IN_MM,
scale=Renderer.DEFAULT_SCALE,
index_position=None, hsplit=1, vsplit=1):
valid_sizes = []
acceptable_formats = [ 'A5', 'A4', 'US letter' ]

Wyświetl plik

@ -454,15 +454,14 @@ class SinglePageRenderer(Renderer):
@staticmethod
def _generic_get_compatible_paper_sizes(bounding_box,
resolution_km_in_mm=Renderer.DEFAULT_KM_IN_MM, index_position = None):
scale=Renderer.DEFAULT_SCALE, index_position = None):
"""Returns a list of the compatible paper sizes for the given bounding
box. The list is sorted, smaller papers first, and a "custom" paper
matching the dimensions of the bounding box is added at the end.
Args:
bounding_box (coords.BoundingBox): the map geographic bounding box.
resolution_km_in_mm (int): size of a geographic kilometer in
milimeters on the rendered map.
scale (int): minimum mapnik scale of the map.
index_position (str): None or 'side' (index on side),
'bottom' (index at bottom).
@ -470,9 +469,17 @@ class SinglePageRenderer(Renderer):
mm, portrait_ok, landscape_ok, is_default). Paper sizes are
represented in portrait mode.
"""
# the mapnik scale depends on the latitude
lat = bounding_box.get_top_left()[0]
scale *= math.cos(math.radians(lat))
# by convention, mapnik uses 90 ppi whereas cairo uses 72 ppi
scale *= float(72) / 90
geo_height_m, geo_width_m = bounding_box.spheric_sizes()
paper_width_mm = geo_width_m/1000.0 * resolution_km_in_mm
paper_height_mm = geo_height_m/1000.0 * resolution_km_in_mm
paper_width_mm = geo_width_m * 1000 / scale
paper_height_mm = geo_height_m * 1000 / scale
LOG.debug('Map represents %dx%dm, needs at least %.1fx%.1fcm '
'on paper.' % (geo_width_m, geo_height_m,
@ -543,22 +550,21 @@ class SinglePageRendererNoIndex(SinglePageRenderer):
@staticmethod
def get_compatible_paper_sizes(bounding_box,
resolution_km_in_mm=Renderer.DEFAULT_KM_IN_MM):
scale=Renderer.DEFAULT_SCALE):
"""Returns a list of the compatible paper sizes for the given bounding
box. The list is sorted, smaller papers first, and a "custom" paper
matching the dimensions of the bounding box is added at the end.
Args:
bounding_box (coords.BoundingBox): the map geographic bounding box.
resolution_km_in_mm (int): size of a geographic kilometer in
milimeters on the rendered map.
scale (int): minimum mapnik scale of the map.
Returns a list of tuples (paper name, width in mm, height in
mm, portrait_ok, landscape_ok). Paper sizes are represented in
portrait mode.
"""
return SinglePageRenderer._generic_get_compatible_paper_sizes(
bounding_box, resolution_km_in_mm, None)
bounding_box, scale, None)
class SinglePageRendererIndexOnSide(SinglePageRenderer):
@ -578,22 +584,21 @@ class SinglePageRendererIndexOnSide(SinglePageRenderer):
@staticmethod
def get_compatible_paper_sizes(bounding_box,
resolution_km_in_mm=Renderer.DEFAULT_KM_IN_MM):
scale=Renderer.DEFAULT_SCALE):
"""Returns a list of the compatible paper sizes for the given bounding
box. The list is sorted, smaller papers first, and a "custom" paper
matching the dimensions of the bounding box is added at the end.
Args:
bounding_box (coords.BoundingBox): the map geographic bounding box.
resolution_km_in_mm (int): size of a geographic kilometer in
milimeters on the rendered map.
scale (int): minimum mapnik scale of the map.
Returns a list of tuples (paper name, width in mm, height in
mm, portrait_ok, landscape_ok). Paper sizes are represented in
portrait mode.
"""
return SinglePageRenderer._generic_get_compatible_paper_sizes(
bounding_box, resolution_km_in_mm, 'side')
bounding_box, scale, 'side')
class SinglePageRendererIndexBottom(SinglePageRenderer):
@ -613,22 +618,21 @@ class SinglePageRendererIndexBottom(SinglePageRenderer):
@staticmethod
def get_compatible_paper_sizes(bounding_box,
resolution_km_in_mm=Renderer.DEFAULT_KM_IN_MM):
scale=Renderer.DEFAULT_SCALE):
"""Returns a list of the compatible paper sizes for the given bounding
box. The list is sorted, smaller papers first, and a "custom" paper
matching the dimensions of the bounding box is added at the end.
Args:
bounding_box (coords.BoundingBox): the map geographic bounding box.
resolution_km_in_mm (int): size of a geographic kilometer in
milimeters on the rendered map.
scale (int): minimum mapnik scale of the map.
Returns a list of tuples (paper name, width in mm, height in
mm, portrait_ok, landscape_ok). Paper sizes are represented in
portrait mode.
"""
return SinglePageRenderer._generic_get_compatible_paper_sizes(
bounding_box, resolution_km_in_mm, 'bottom')
bounding_box, scale, 'bottom')
if __name__ == '__main__':