maposmatic-dev
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Maposmatic-dev] [PATCH 2/2] Fix scale computations to ensure a minimum


From: gael . utard
Subject: [Maposmatic-dev] [PATCH 2/2] Fix scale computations to ensure a minimum zoom level
Date: Tue, 10 Apr 2012 15:48:41 +0200

From: Gael UTARD <address@hidden>

Signed-off-by: Gael UTARD <address@hidden>
---
 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




reply via email to

[Prev in Thread] Current Thread [Next in Thread]