From: Gael UTARD <gael.ut...@kisis.fr> Signed-off-by: Gael UTARD <gael.ut...@kisis.fr> --- ocitysmap2/layoutlib/abstract_renderer.py | 12 ++++---- ocitysmap2/layoutlib/multi_page_renderer.py | 25 ++++++++-------- ocitysmap2/layoutlib/single_page_renderers.py | 38 +++++++++++++----------- 3 files changed, 39 insertions(+), 36 deletions(-)
diff --git a/ocitysmap2/layoutlib/abstract_renderer.py b/ocitysmap2/layoutlib/abstract_renderer.py index 5517ab9..7103db1 100644 --- a/ocitysmap2/layoutlib/abstract_renderer.py +++ b/ocitysmap2/layoutlib/abstract_renderer.py @@ -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 diff --git a/ocitysmap2/layoutlib/multi_page_renderer.py b/ocitysmap2/layoutlib/multi_page_renderer.py index e41af24..3123593 100644 --- a/ocitysmap2/layoutlib/multi_page_renderer.py +++ b/ocitysmap2/layoutlib/multi_page_renderer.py @@ -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' ] diff --git a/ocitysmap2/layoutlib/single_page_renderers.py b/ocitysmap2/layoutlib/single_page_renderers.py index 04b9938..aa71f06 100644 --- a/ocitysmap2/layoutlib/single_page_renderers.py +++ b/ocitysmap2/layoutlib/single_page_renderers.py @@ -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__': -- 1.7.5.4