Add an overview page in the multi-page renderer.

* get the right bounding box
 * create the overview canvas
 * draw the map and the appropriate shade
 * draw boxes for each pages (OverwiewGrid)
 * add the overview to the list of pages to be rendered

Signed-off-by: Étienne Loks <etienne.loks@peacefrogs.net>
stable
Étienne Loks 2012-03-30 18:51:17 +02:00 zatwierdzone przez Thomas Petazzoni
rodzic a99fa35b03
commit 17298cd3fe
3 zmienionych plików z 176 dodań i 3 usunięć

Wyświetl plik

@ -28,7 +28,10 @@ import tempfile
import math
import sys
import cairo
import mapnik
try:
import mapnik2 as mapnik
except ImportError:
import mapnik
import coords
import locale
import pangocairo
@ -41,6 +44,7 @@ from abstract_renderer import Renderer
from ocitysmap2.maplib.map_canvas import MapCanvas
from ocitysmap2.maplib.grid import Grid
from ocitysmap2.maplib.overview_grid import OverviewGrid
from indexlib.indexer import StreetIndex
from indexlib.multi_page_renderer import MultiPageStreetIndexRenderer
@ -133,7 +137,7 @@ class MultiPageRenderer(Renderer):
self._usable_area_height_pt + (self._usable_area_height_pt - overlap_margin_pt) * (nb_pages_height - 1)
# Convert this paper area available in the number of Mercator
# meters that can we rendered on the map
# meters that can be rendered on the map
total_width_merc = \
commons.convert_pt_to_mm(total_width_pt_after_extension) * scale_denom / 1000
total_height_merc = \
@ -186,8 +190,45 @@ class MultiPageRenderer(Renderer):
# for i, (bb, bb_inner) in enumerate(bboxes):
# print bb.as_javascript(name="p%d" % i)
# Create the map canvas for each page
self.pages = []
# Create an overview map
# Create the gray shape around the map
first_bbox, last_bbox = bboxes[0][0], bboxes[-1][0]
overview_coord = list(first_bbox.get_top_left()) + \
list(last_bbox.get_bottom_right())
overview_bb = coords.BoundingBox(*overview_coord
).create_expanded(0.001, 0.001)
exterior = shapely.wkt.loads(overview_bb.as_wkt())
interior = shapely.wkt.loads(self.rc.polygon_wkt)
shade_wkt = exterior.difference(interior).wkt
shade = maplib.shapes.PolyShapeFile(self.rc.bounding_box,
os.path.join(self.tmpdir, 'shape_overview.shp'),
'shade-overview')
shade.add_shade_from_wkt(shade_wkt)
# Create the grid
map_grid = OverviewGrid(overview_bb,
[bb for bb, bb_inner in bboxes], self.rc.i18n.isrtl())
grid_shape = map_grid.generate_shape_file(
os.path.join(self.tmpdir, 'grid_overview.shp'))
# Create one canvas for the current page
map_canvas = MapCanvas(self.rc.stylesheet,
overview_bb, graphical_ratio=None)
map_canvas.add_shape_file(shade)
map_canvas.add_shape_file(grid_shape,
self.rc.stylesheet.grid_line_color,
self.rc.stylesheet.grid_line_alpha,
self.rc.stylesheet.grid_line_width)
map_canvas.render()
self.pages.append((map_canvas, map_grid))
# Create the map canvas for each page
indexes = []
for i, (bb, bb_inner) in enumerate(bboxes):

Wyświetl plik

@ -0,0 +1,103 @@
# -*- coding: utf-8 -*-
# ocitysmap, city map and street index generator from OpenStreetMap data
import logging
import math
import shapes
l = logging.getLogger('ocitysmap')
class OverviewGrid:
"""
The OverviewGrid class draw the grid overlayed on the overview map of a
multi-page render.
"""
def __init__(self, bounding_box, pages_bounding_boxes, rtl=False):
"""Creates a new grid for the given bounding boxes.
Args:
bounding_box (coords.BoundingBox): the map bounding box.
bounding_box (list of coords.BoundingBox): bounding boxes of the
pages.
rtl (boolean): whether the map is rendered in right-to-left mode or
not. Defaults to False.
"""
self._bbox = bounding_box
self._pages_bbox = pages_bounding_boxes
self.rtl = rtl
self._height_m, self._width_m = bounding_box.spheric_sizes()
l.info('Laying out of overview grid on %.1fx%.1fm area...' %
(self._width_m, self._height_m))
self._pages_wkt = [bb.as_wkt() for bb in self._pages_bbox]
self.horiz_count = 1
self.vert_count = 1
self.horizontal_labels = ['plouf']
self.vertical_labels = ['plouf']
def generate_shape_file(self, filename):
"""Generates the grid shapefile with all the horizontal and
vertical lines added.
Args:
filename (string): path to the temporary shape file that will be
generated.
Returns the ShapeFile object.
"""
# Use a slightly larger bounding box for the shape file to accomodate
# for the small imprecisions of re-projecting.
g = shapes.BoxShapeFile(self._bbox.create_expanded(0.001, 0.001),
filename, 'grid')
map(g.add_box, self._pages_bbox)
return g
def _gen_horizontal_square_label(self, x):
"""Generates a human-readable label for the given horizontal square
number. For example:
1 -> A
2 -> B
26 -> Z
27 -> AA
28 -> AB
...
"""
if self.rtl:
x = len(self._vertical_lines) - x
label = ''
while x != -1:
label = chr(ord('A') + x % 26) + label
x = x/26 - 1
return label
def _gen_vertical_square_label(self, x):
"""Generate a human-readable label for the given vertical square
number. Since we put numbers verticaly, this is simply x+1."""
return str(x + 1)
def get_location_str(self, lattitude, longitude):
"""
Translate the given lattitude/longitude (EPSG:4326) into a
string of the form "CA42"
"""
hdelta = min(abs(longitude - self._bbox.get_top_left()[1]),
self._horiz_angle_span)
hlabel = self.horizontal_labels[int(hdelta / self._horiz_unit_angle)]
vdelta = min(abs(lattitude - self._bbox.get_top_left()[0]),
self._vert_angle_span)
vlabel = self.vertical_labels[int(vdelta / self._vert_unit_angle)]
return "%s%s" % (hlabel, vlabel)
if __name__ == "__main__":
logging.basicConfig(level=logging.DEBUG)
pass

Wyświetl plik

@ -125,6 +125,35 @@ class LineShapeFile(_ShapeFile):
self._add_feature(line)
return self
class BoxShapeFile(LineShapeFile):
"""
Shape file for Box geometries.
"""
def add_box(self, box):
top_left, bottom_right = box.get_top_left(), box.get_bottom_right()
line = ogr.Geometry(type = ogr.wkbLineString)
line.AddPoint_2D(*list(reversed(top_left)))
line.AddPoint_2D(bottom_right[1], top_left[0])
self._add_feature(line)
line = ogr.Geometry(type = ogr.wkbLineString)
line.AddPoint_2D(bottom_right[1], top_left[0])
line.AddPoint_2D(*list(reversed(bottom_right)))
self._add_feature(line)
line = ogr.Geometry(type = ogr.wkbLineString)
line.AddPoint_2D(*list(reversed(bottom_right)))
line.AddPoint_2D(top_left[1], bottom_right[0])
self._add_feature(line)
line = ogr.Geometry(type = ogr.wkbLineString)
line.AddPoint_2D(top_left[1], bottom_right[0])
line.AddPoint_2D(*list(reversed(top_left)))
self._add_feature(line)
return self
class PolyShapeFile(_ShapeFile):
"""
Shape file for Polygon geometries.