maposmatic-dev
[Top][All Lists]
Advanced

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

[Maposmatic-dev] [PATCH] ocitysmap: get rid of oc itysmap v1


From: Thomas Petazzoni
Subject: [Maposmatic-dev] [PATCH] ocitysmap: get rid of oc itysmap v1
Date: Sat, 31 Mar 2012 00:37:23 +0200

OcitySMap2 has been in development for a while now, and has a much,
much larger feature set than the original ocitysmap. Let's keep only
ocitysmap2 in the Git repository. Those nostalgics of the old version
can always dig into the Git history.

Signed-off-by: Thomas Petazzoni <address@hidden>
---
 ocitysmap-render          |  158 -------
 ocitysmap.conf-template   |   40 --
 ocitysmap/.gitignore      |    1 -
 ocitysmap/__init__.py     |   32 --
 ocitysmap/coords.py       |   98 -----
 ocitysmap/draw_utils.py   |  244 -----------
 ocitysmap/grid.py         |  108 -----
 ocitysmap/i18n.py         |  817 -----------------------------------
 ocitysmap/map_canvas.py   |  398 -----------------
 ocitysmap/street_index.py | 1050 ---------------------------------------------
 ocitysmap/utils.py        |   34 --
 11 files changed, 0 insertions(+), 2980 deletions(-)
 delete mode 100755 ocitysmap-render
 delete mode 100644 ocitysmap.conf-template
 delete mode 100644 ocitysmap/.gitignore
 delete mode 100644 ocitysmap/__init__.py
 delete mode 100644 ocitysmap/coords.py
 delete mode 100644 ocitysmap/draw_utils.py
 delete mode 100644 ocitysmap/grid.py
 delete mode 100644 ocitysmap/i18n.py
 delete mode 100644 ocitysmap/map_canvas.py
 delete mode 100644 ocitysmap/street_index.py
 delete mode 100644 ocitysmap/utils.py

diff --git a/ocitysmap-render b/ocitysmap-render
deleted file mode 100755
index 881e0e9..0000000
--- a/ocitysmap-render
+++ /dev/null
@@ -1,158 +0,0 @@
-#!/usr/bin/env python
-# -*- coding: utf-8; mode: Python -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-__version__ = '0.1'
-
-import logging
-import optparse
-import sys, os
-
-from ocitysmap.street_index import OCitySMap, BaseOCitySMapError
-from ocitysmap.coords import BoundingBox
-
-
-def main():
-    logging.basicConfig(stream=sys.stdout, level=logging.DEBUG)
-
-    usage = '%prog [options] [-c <cityname>|-b <lat1,long1 
lat2,long2>|--polygon-osmid <osmid>]'
-    parser = optparse.OptionParser(usage=usage,
-                                   version='%%prog %s' % __version__)
-    parser.add_option('-p', '--prefix', dest='output_prefix', metavar='PREFIX',
-                      help='Specify the prefix of generated files. '
-                           'Defaults to "citymap"',
-                      default='citymap')
-    parser.add_option('-f', '--format', dest='output_format', metavar='FMT',
-                      help='Specify the output formats. Supported file '
-                           'formats: svg, svgz, pdf, ps, png, and csv for '
-                           'the index, xml for the map. Defaults to '
-                           'SVGZ. May be specified multiple times.',
-                      action='append')
-    parser.add_option('-t', '--title', dest='output_title', metavar='TITLE',
-                      help='Specify the title displayed in the output files',
-                      default=None)
-    parser.add_option('-c', '--city', dest='city_name', metavar='CITY_NAME',
-                      help='Specify the name of te city to map',
-                      default=None)
-    parser.add_option('-C', '--config', dest='config_file', metavar='FILE',
-                      help='Specify the location of the config file')
-    parser.add_option('--no-frame', dest='no_frame', action='store_true',
-                      default=False,
-                      help="Don't insert the map and index inside a frame")
-    parser.add_option('-z', '--zoom-factor',
-                      metavar='[0-18]', help='Zoom factor for the'
-                      'rendering (default=16)', type='int', default =16)
-    parser.add_option('-b', '--bounding-box', dest='bbox',  nargs=2,
-                      metavar='LAT1,LON1 LAT2,LON2', help='Bounding box')
-    parser.add_option('', '--polygon-osmid', dest='osmid', metavar='OSMID',
-                      help='OSM id representing the polygon of the city to 
render'),
-    parser.add_option('-l', '--language', dest='language',
-                      metavar='LANGUAGE_CODE',
-                      help='Language to use when generating the index' 
-                           ' (default=fr_FR.UTF-8)',
-                      default='fr_FR.UTF-8')
-
-    (options, args) = parser.parse_args()
-    if len(args):
-        parser.print_help()
-        return 1
-
-    # Make sure either -b or -c is given
-    optcnt = 0
-    for var in options.city_name, options.bbox, options.osmid:
-        if var:
-            optcnt += 1
-
-    if optcnt == 0:
-        parser.error("One of --city or --bounding-box or --osmid is mandatory")
-
-    if optcnt > 1:
-        parser.error("--city or --bounding-box or --osmid are exclusive")
-
-    # Determine title
-    if options.no_frame:
-        title = None
-    elif options.output_title is not None:
-        title = options.output_title
-    elif options.city_name is not None:
-        title = options.city_name
-    else:
-        title = "City's Map"
-
-    # Parse zoom factor
-    try:
-        options.zoom_factor = int(options.zoom_factor)
-    except ValueError:
-        parser.error("Invalid zoom factor: %s" % options.zoom_factor)
-    if options.zoom_factor < 0 or options.zoom_factor > 18:
-        parser.error("Invalid zoom factor: %s" % options.zoom_factor)
-
-    if not options.output_format:
-        options.output_format = ['svgz']
-    options.output_format = set(options.output_format)
-
-    # Parse bounding box arguments
-    boundingbox = None
-    if options.bbox:
-        try:
-            boundingbox = BoundingBox.parse(options.bbox)
-        except ValueError:
-            sys.stderr.write('ERROR: Invalid city bounding box!\n')
-            return 1
-
-    if options.city_name:
-        city_name = unicode(options.city_name.decode('utf-8'))
-    else:
-        city_name = None
-
-    osmid = None
-    if options.osmid:
-        try:
-            osmid = int(options.osmid)
-        except ValueError:
-            sys.stderr.write('ERROR: Invalid polygon OSM id!\n')
-            return 1
-
-    try:
-        prefix = 'ocitysmap_render_%d' % os.getpid()
-        renderer = OCitySMap(options.config_file, prefix, city_name,
-                             boundingbox, osmid, options.language)
-    except BaseOCitySMapError, e:
-        sys.stderr.write('ERROR: %s\n' % e)
-        return 1
-    except KeyboardInterrupt:
-        sys.stderr.write(' Aborting.\n')
-
-    _map = renderer.render_map_into_files(title,
-                                          options.output_prefix,
-                                          options.output_format,
-                                          "zoom:%d" % options.zoom_factor)
-
-    renderer.render_index(title, options.output_prefix,
-                          options.output_format,
-                          _map.width, _map.height)
-
-    return 0
-
-if __name__ == '__main__':
-    sys.exit(main())
diff --git a/ocitysmap.conf-template b/ocitysmap.conf-template
deleted file mode 100644
index 4673852..0000000
--- a/ocitysmap.conf-template
+++ /dev/null
@@ -1,40 +0,0 @@
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-# PostGIS datasource.
-[datasource]
-host: localhost
-user: maposmatic
-password: ereiamjh
-dbname: maposmatic
-# SQL request timeout, in minutes. Defaults to 15min.
-# request_timeout: 10
-
-[rendering]
-# List of available stylesheets, each needs to be described by an eponymous
-# configuration section in this file.
-available_stylesheets: stylesheet_osm
-
-# The default Mapnik stylesheet.
-[stylesheet_osm]
-name: Default
-description: The default OSM style
-path: /path/to/mapnik/osm.xml
diff --git a/ocitysmap/.gitignore b/ocitysmap/.gitignore
deleted file mode 100644
index 0d20b64..0000000
--- a/ocitysmap/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-*.pyc
diff --git a/ocitysmap/__init__.py b/ocitysmap/__init__.py
deleted file mode 100644
index fce3b38..0000000
--- a/ocitysmap/__init__.py
+++ /dev/null
@@ -1,32 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-"""OCitySMap.
-
-Provide documentation here.
-"""
-
-__author__ = 'The Hackfest2009 team'
-__version__ = '0.1'
-
-raise DeprecationWarning, 'OCitysmap v%s will soon disappear!' % __version__
diff --git a/ocitysmap/coords.py b/ocitysmap/coords.py
deleted file mode 100644
index 9d10f48..0000000
--- a/ocitysmap/coords.py
+++ /dev/null
@@ -1,98 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import math
-
-
-EARTH_RADIUS = 6370986 # meters
-
-
-class BoundingBox:
-    def __init__(self, lat1, long1, lat2, long2):
-        (self._lat1, self._long1) = float(lat1), float(long1)
-        (self._lat2, self._long2) = float(lat2), float(long2)
-
-        # make sure lat1/long1 is the upper left, and the others the btm right
-        if (self._lat1 < self._lat2):
-            self._lat1, self._lat2 = self._lat2, self._lat1
-        if (self._long1 > self._long2):
-            self._long1, self._long2 = self._long2, self._long1
-
-    @staticmethod
-    def parse_wkt(wkt):
-        coords = [p.split(' ') for p in wkt[9:].split(',')]
-        return BoundingBox(coords[1][1], coords[1][0],
-                           coords[3][1], coords[3][0])
-
-    @staticmethod
-    def parse(points):
-        (lat1, long1) = points[0].split(',')
-        (lat2, long2) = points[1].split(',')
-        return BoundingBox(lat1, long1, lat2, long2)
-
-    def get_top_left(self):
-        return (self._lat1, self._long1)
-
-    def get_bottom_right(self):
-        return (self._lat2, self._long2)
-
-    def ptstr(self, point):
-        return '%.4f,%.4f' % (point[0], point[1])
-
-    def __str__(self):
-        return '(%s %s)' % (self.ptstr(self.get_top_left()),
-                            self.ptstr(self.get_bottom_right()))
-
-    def spheric_sizes(self):
-        """Metric distances at the bounding box top latitude.
-        Returns the tuple (metric_size_lat, metric_size_long)
-        """
-        delta_lat = abs(self._lat1 - self._lat2)
-        delta_long = abs(self._long1 - self._long2)
-        radius_lat = EARTH_RADIUS * math.cos(math.radians(self._lat1))
-        return (EARTH_RADIUS * math.radians(delta_lat),
-                radius_lat * math.radians(delta_long))
-
-    def create_expanded(self, dlat, dlong):
-        """Return a new bbox of the same size + dlat/dlong added
-           on the top-left sides"""
-        return BoundingBox(self._lat1 + dlat, self._long1 - dlong,
-                           self._lat2, self._long2)
-
-    def get_pixel_size_for_zoom_factor(self, zoom = 17):
-        """Return the size in pixels (tuple width,height) needed to
-        render the bounding box at the given zoom factor"""
-        delta_long = abs(self._long1 - self._long2)
-        # 2^zoom tiles (1 tile = 256 pix) for the whole earth
-        pix_x = delta_long * (2 ** (zoom + 8)) / 360
-
-        # http://en.wikipedia.org/wiki/Mercator_projection
-        def yplan(lat):
-            return math.log(math.tan(math.pi/4. + math.radians(lat)/2.))
-
-        # OSM maps are drawn between -85 deg and + 85, the whole amplitude
-        # is 256*2^(zoom)
-        pix_y = (yplan(self._lat1) - yplan(self._lat2)) \
-                * (2 ** (zoom + 7)) / yplan(85)
-
-        return (int(math.ceil(pix_x)), int(math.ceil(pix_y)))
diff --git a/ocitysmap/draw_utils.py b/ocitysmap/draw_utils.py
deleted file mode 100644
index 095c311..0000000
--- a/ocitysmap/draw_utils.py
+++ /dev/null
@@ -1,244 +0,0 @@
-# -*- coding: utf-8; mode: Python -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-import cairo, logging, pango, pangocairo
-import datetime
-
-l = logging.getLogger('ocitysmap')
-
-
-def enclose_in_frame(renderer, insurf_w, insurf_h,
-                     title,
-                     outsurf, outsurf_w, outsurf_h, out_margin):
-    """
-    Fill the given surface with the contents of another one and a
-    frame around it
-    @param renderer (function : cairo_context -> None) Function
-    drawing inside the frame
-    @param insurf_w/h (int) width/height of the inside rendering
-    @param title (string) title to write on the frame
-    @param outsurf (cairo surface) surface to draw the whole thing into
-    @param outsurf_w/h (int) width/height of the resulting framed image
-    @param out_margin (int) size of the margin around the inner image
-    """
-
-    ctx = cairo.Context(outsurf)
-
-    ctx.save()
-
-    # Reset background
-    ctx.set_source_rgb (1, 1, 1)
-    ctx.set_operator (cairo.OPERATOR_OVER)
-    ctx.paint()
-
-    # Default pen color
-    ctx.set_source_rgb (0, 0, 0)
-
-    # Draw the surface with a margin around it
-    ctx.save()
-    ctx.translate(out_margin, out_margin)
-    indest_w = outsurf_w - 2.*out_margin
-    indest_h = outsurf_h - 2.*out_margin
-    ctx.scale(indest_w / insurf_w, indest_h / insurf_h)
-    renderer(ctx)
-    ctx.restore()
-
-    # Draw the title
-    ctx.save()
-
-    pc = pangocairo.CairoContext(ctx)
-    layout = pc.create_layout()
-    fd = pango.FontDescription("DejaVu")
-
-    # Do a first test with a font size of out_margin
-    fd.set_size(out_margin * pango.SCALE)
-    layout.set_font_description(fd)
-    layout.set_text(title)
-    width = layout.get_size()[0] / pango.SCALE
-    height = layout.get_size()[1] / pango.SCALE
-
-    # Compute the ratio to be applied on the font size to make the
-    # text fit in the available space
-    if height > out_margin:
-        hratio = float(out_margin) / height
-    else:
-        hratio = 1.
-
-    max_width = indest_w * .8
-    if width > max_width:
-        wratio = max_width / width
-    else:
-        wratio = 1.
-
-    ratio = min(wratio, hratio)
-
-    # Render the text at the appropriate size and location
-    fd.set_size(int(out_margin * ratio * pango.SCALE))
-    layout.set_font_description(fd)
-    width = layout.get_size()[0] / pango.SCALE
-    f = layout.get_context().load_font(fd)
-    fm = f.get_metrics()
-    ascent = fm.get_ascent() / pango.SCALE
-    ctx.move_to(out_margin * 2., out_margin * (.5 + .35 * ratio) - ascent)
-    pc.show_layout(layout)
-
-    ctx.restore()
-
-    # Draw the rounded rectangle
-    ctx.save()
-    ctx.set_line_width(max(out_margin/9., 2.))
-    ctx.move_to (out_margin * 2 + width + out_margin/2., out_margin / 2.)
-    ctx.line_to (outsurf_w - out_margin, out_margin / 2.)
-    ctx.rel_curve_to(0,0, out_margin/2., 0, out_margin/2., out_margin/2.)
-    ctx.rel_line_to (0, outsurf_h - 2*out_margin)
-    ctx.rel_curve_to(0,0, 0, out_margin/2., -out_margin/2., out_margin/2.)
-    ctx.rel_line_to(-(outsurf_w - 2*out_margin), 0)
-    ctx.rel_curve_to(0,0, -out_margin/2.,0, -out_margin/2., -out_margin/2.)
-    ctx.rel_line_to(0, -(outsurf_h - 2*out_margin))
-    ctx.rel_curve_to(0,0, 0,-out_margin/2., out_margin/2.,-out_margin/2.)
-    ctx.line_to(out_margin*1.5, out_margin/2.)
-    ctx.stroke()
-    ctx.restore()
-
-    ctx.restore()
-    return outsurf
-
-
-def add_logo(ctx, paperwidth, paperheight, logo_path, copyright_notice=None):
-    copyright_notice = copyright_notice or \
-        (u'© %(year)d MapOSMatic/ocitysmap authors. '
-         u'Map data © %(year)d OpenStreetMap.org '
-         u'and contributors (CC-BY-SA)' % {'year': datetime.date.today().year})
-
-    # Open logo file
-    png =  None
-    if logo_path:
-        try:
-            f = open(logo_path, 'rb')
-            png = cairo.ImageSurface.create_from_png(f)
-            l.debug('Using copyright logo: %s' % logo_path)
-            f.close()
-        except Exception, ex:
-            l.warning('Cannot open logo file: %s' % ex)
-        except:
-            l.warning('Cannot open logo file.')
-
-    # Create a virtual buffer containing the png and the copyright notice
-    ctx.push_group()
-    ctx.move_to(0,0)
-    xlat1, ylat1 = ctx.get_current_point()
-
-    # Draw the png in the buffer
-    if png:
-        ctx.set_source_surface(png)
-        ctx.paint()
-        ctx.rel_move_to(png.get_width(), 0)
-    else:
-        ctx.rel_move_to(0, font_size*1.5)
-
-    # Write the notice in the buffer
-    ctx.set_source_rgb(0, 0, 0)
-
-    # Set up a layout
-    pc = pangocairo.CairoContext(ctx)
-    fd = pango.FontDescription("DejaVu")
-    fd.set_size(14 * pango.SCALE)
-    layout = pc.create_layout()
-    layout.set_font_description(fd)
-
-    # Render copyright notice
-    layout.set_text(copyright_notice)
-    textwidth = layout.get_size()[0] / pango.SCALE
-    pc.show_layout(layout)
-
-    ctx.move_to(png.get_width(), png.get_height() * 0.33)
-
-    # Render date of rendering
-    today = datetime.date.today()
-    gendatetext = _("This map has been rendered on %s and may be incomplete or 
inaccurate.") % today.strftime("%d %b %Y")
-
-    layout.set_text(gendatetext)
-    textwidth = max(textwidth, layout.get_size()[0] / pango.SCALE)
-    pc.show_layout(layout)
-
-    # Render contribution text
-    ctx.move_to(png.get_width(), png.get_height() * 0.66)
-    contribute_text = _("You can contribute to improve this map. See 
http://wiki.openstreetmap.org";)
-
-    layout.set_text(contribute_text)
-    textwidth = max(textwidth, layout.get_size()[0] / pango.SCALE)
-    pc.show_layout(layout)
-
-    # Determine the size of the virtual buffer
-    if png:
-        vbufheight = png.get_height()
-    else:
-        vbufheight = font_size * 2.5
-
-    vbufwidth = png.get_width() + textwidth
-
-    grp = ctx.pop_group()
-    # Virtual buffer done.
-
-    # Display the buffer inside the surface, taking its size into account
-    ctx.translate(paperwidth - vbufwidth - 10,
-                  paperheight - vbufheight - 10)
-    ctx.set_source(grp)
-
-    # Make it transparent
-    ctx.paint_with_alpha(.5)
-
-
-if __name__ == "__main__":
-    inner_W, inner_H, margin = 1024, 768, 50
-
-    inside_area = cairo.ImageSurface(cairo.FORMAT_RGB24, inner_W,  inner_H)
-    ctx = cairo.Context(inside_area)
-
-    # Fill the inside with something
-    ctx.set_source_rgb (1, .1, .1)
-    ctx.set_operator (cairo.OPERATOR_OVER)
-    ctx.paint()
-
-    # Add the logo and save the result as inside.png
-    add_logo(ctx, inner_W, inner_H, "../Openstreetmap_logo.png")
-    f = open("inside.png", 'wb')
-    inside_area.write_to_png(f)
-    f.close()
-
-    # Add a frame and save the result as outside.png
-    def my_render(x):
-        x.set_source_surface(inside_area)
-        x.paint()
-
-    outside_area = cairo.ImageSurface(cairo.FORMAT_RGB24,
-                                      inner_W+2*margin,
-                                      inner_H+2*margin)
-    enclose_in_frame(my_render, inner_W,  inner_H, "badidonc",
-                     outside_area, inner_W+2*margin,
-                     inner_H+2*margin, margin)
-
-    f = open("outside.png", 'wb')
-    outside_area.write_to_png(f)
-    f.close()
diff --git a/ocitysmap/grid.py b/ocitysmap/grid.py
deleted file mode 100644
index 633de1e..0000000
--- a/ocitysmap/grid.py
+++ /dev/null
@@ -1,108 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-import math, logging
-import map_canvas, utils,  coords
-
-l = logging.getLogger('ocitysmap')
-
-class GridDescriptor:
-    def __init__(self, bbox, db):
-        self.bbox = bbox
-        height, width = bbox.spheric_sizes()
-
-        # Compute number of squares, assumming a size of 500 meters
-        # per square
-        self.width_square_count  = width / 500
-        self.height_square_count = height / 500
-
-        # Compute the size in angles of the squares
-        self.width_square_angle  = (abs(bbox.get_top_left()[1] -
-                                        bbox.get_bottom_right()[1]) /
-                                    self.width_square_count)
-        self.height_square_angle = (abs(bbox.get_top_left()[0] -
-                                        bbox.get_bottom_right()[0]) /
-                                    self.height_square_count)
-
-        # Compute the lists of longitudes and latitudes of the
-        # horizontal and vertical lines delimiting the square
-        self.vertical_lines   = [bbox.get_top_left()[1] +
-                                 x * self.width_square_angle
-                                 for x in xrange(0, 
int(math.floor(self.width_square_count )) + 1)]
-        self.horizontal_lines = [bbox.get_top_left()[0] -
-                                 x * self.height_square_angle
-                                 for x in xrange(0, 
int(math.floor(self.height_square_count)) + 1)]
-
-        # Compute the lists of labels
-        self.vertical_labels   = [utils.gen_vertical_square_label(x)
-                                  for x in xrange(0, 
int(math.ceil(self.width_square_count)))]
-        self.horizontal_labels = [utils.gen_horizontal_square_label(x)
-                                  for x in xrange(0, 
int(math.ceil(self.height_square_count)))]
-        l.debug("vertical lines: %s" % self.vertical_lines)
-        l.debug("horizontal lines: %s" % self.horizontal_lines)
-        l.debug("vertical labels: %s" % self.vertical_labels)
-        l.debug("horizontal labels: %s" % self.horizontal_labels)
-
-    def generate_shape_file(self, filename, bbox):
-        g = map_canvas.GridFile(bbox, filename)
-        for v in self.vertical_lines:
-            g.add_vert_line(v)
-        for h in self.horizontal_lines:
-            g.add_horiz_line(h)
-        g.flush()
-        return g
-
-    def generate_scale_shape_file(self, filename, base_lat):
-        """
-        Returns a tuple (gridfile, lat, long) of the scale widget, or
-        None when not enough room for scale
-        """
-        if len(self.horizontal_lines) < 2 or len(self.vertical_lines) < 2:
-            return None
-
-        height_lat = (self.horizontal_lines[-2] - self.horizontal_lines[-1])/30
-
-        # Make sure there is enough room between the last horiz line
-        # and the bottom:
-        if base_lat + (self.horizontal_lines[-1] - base_lat) / 3. \
-                + 2*height_lat < self.horizontal_lines[-1]:
-            line_lat = base_lat + (self.horizontal_lines[-1] - base_lat) / 3.
-        else:
-            # Nope...
-            line_lat = self.horizontal_lines[-1] \
-                + (self.horizontal_lines[-2] - self.horizontal_lines[-1]) \
-                / 5.
-
-        bbox = coords.BoundingBox(line_lat + height_lat,
-                                  self.vertical_lines[0]-1.e-5,
-                                  line_lat - height_lat,
-                                  self.vertical_lines[1]+1.e-5)
-
-        g = map_canvas.GridFile(bbox, filename) # bbox, filename)
-        g.add_horiz_line(line_lat)
-        g.add_vert_line(self.vertical_lines[0])
-        g.add_vert_line(self.vertical_lines[1])
-        g.flush()
-        return (g, line_lat + height_lat,
-                (self.vertical_lines[0] + self.vertical_lines[1]) / 2)
diff --git a/ocitysmap/i18n.py b/ocitysmap/i18n.py
deleted file mode 100644
index efafb4b..0000000
--- a/ocitysmap/i18n.py
+++ /dev/null
@@ -1,817 +0,0 @@
-# -*- coding: utf-8; mode: Python -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import re
-import gettext
-
-def _install_language(language, locale_path):
-    t = gettext.translation(domain='ocitysmap',
-                            localedir=locale_path,
-                            languages=[language],
-                            fallback=True)
-    t.install(unicode=True)
-
-class i18n:
-    """Functions needed to be implemented for a new language.
-       See i18n_fr_FR_UTF8 below for an example. """
-    def language_code(self):
-        pass
-
-    def user_readable_street(self, name):
-        pass
-
-    def first_letter_equal(self, a, b):
-        pass
-
-    def isrtl(self):
-        return False
-
-class i18n_template_code_CODE(i18n):
-    def __init__(self, language, locale_path):
-        """Install the _() function for the chosen locale other
-           object initialisation"""
-        self.language = str(language) # FIXME: why do we have unicode here?
-        _install_language(language, locale_path)
-
-    def language_code(self):
-        """returns the language code of the specific language
-           supported, e.g. fr_FR.UTF-8"""
-        return self.language
-
-    def user_readable_street(self, name):
-        """ transforms a street name into a suitable form for
-            the map index, e.g. Paris (Rue de) for French"""
-        return name
-
-    def first_letter_equal(self, a, b):
-        """returns True if the letters a and b are equal in the map index,
-           e.g. É and E are equals in French map index"""
-        return a == b
-
-    def isrtl(self):
-        return False
-
-
-class i18n_fr_generic(i18n):
-    APPELLATIONS = [ u"Accès", u"Allée", u"Allées", u"Autoroute", u"Avenue", 
u"Barrage",
-                     u"Boulevard", u"Carrefour", u"Chaussée", u"Chemin",
-                     u"Cheminement", u"Cale", u"Cales", u"Cavée", u"Cité",
-                     u"Clos", u"Coin", u"Côte", u"Cour", u"Cours", u"Descente",
-                     u"Degré", u"Escalier",
-                     u"Escaliers", u"Esplanade", u"Funiculaire",
-                     u"Giratoire", u"Hameau", u"Impasse", u"Jardin",
-                     u"Jardins", u"Liaison", u"Lotissement", u"Mail", 
u"Montée", u"Môle",
-                     u"Parc", u"Passage", u"Passerelle", u"Passerelles",
-                     u"Place", u"Placette", u"Pont", u"Promenade",
-                     u"Petite Avenue", u"Petite Rue", u"Quai",
-                     u"Rampe", u"Rang", u"Résidence", u"Rond-Point",
-                     u"Route forestière", u"Route", u"Rue", u"Ruelle",
-                     u"Square", u"Sente", u"Sentier", u"Sentiers", 
u"Terre-Plein",
-                     u"Télécabine", u"Traboule", u"Traverse", u"Tunnel",
-                     u"Venelle", u"Villa", u"Virage"
-                   ]
-    DETERMINANTS = [ u" des", u" du", u" de la", u" de l'",
-                     u" de", u" d'", u" aux", u""
-                   ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_it_generic(i18n):
-    APPELLATIONS = [ u"Via", u"Viale", u"Piazza", u"Scali", u"Strada", 
u"Largo",
-                     u"Corso", u"Viale", u"Calle", u"Sottoportico",
-                    u"Sottoportego", u"Vicolo", u"Piazzetta" ]
-    DETERMINANTS = [ u" delle", u" dell'", u" dei", u" degli",
-                     u" della", u" del", u" di", u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_es_generic(i18n):
-    APPELLATIONS = [ u"Avenida", u"Avinguda", u"Calle", u"Callejón",
-            u"Calzada", u"Camino", u"Camí", u"Carrer", u"Carretera",
-            u"Glorieta", u"Parque", u"Pasaje", u"Pasarela", u"Paseo", u"Plaza",
-            u"Plaça", u"Privada", u"Puente", u"Ronda", u"Salida", u"Travesia" ]
-    DETERMINANTS = [ u" de", u" de la", u" del", u" de las",
-                     u" dels", u" de los", u" d'", u" de l'", u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-    N_ACCENT = re.compile(ur"[ñ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        s = self.N_ACCENT.sub("n", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_ca_generic(i18n):
-
-    APPELLATIONS = [ # Catalan
-                     u"Autopista", u"Autovia", u"Avinguda",
-                     u"Baixada", u"Barranc", u"Barri", u"Barriada",
-                     u"Biblioteca", u"Carrer", u"Carreró", u"Carretera",
-                     u"Cantonada", u"Església", u"Estació", u"Hospital",
-                     u"Monestir", u"Monument", u"Museu", u"Passatge",
-                     u"Passeig", u"Plaça", u"Planta", u"Polígon",
-                     u"Pujada", u"Rambla", u"Ronda", u"Travessera",
-                     u"Travessia", u"Urbanització", u"Via",
-                     u"Avenida", u"Calle", u"Camino", u"Plaza",
-
-                     # Spanish (being distinct from Catalan)
-                     u"Acceso", u"Acequia", u"Alameda", u"Alquería",
-                     u"Andador", u"Angosta", u"Apartamentos", u"Apeadero",
-                     u"Arboleda", u"Arrabal", u"Arroyo", u"Autovía",
-                     u"Avenida", u"Bajada", u"Balneario", u"Banda",
-                     u"Barranco", u"Barranquil", u"Barrio", u"Bloque",
-                     u"Brazal", u"Bulevar", u"Calle", u"Calleja",
-                     u"Callejón", u"Callejuela", u"Callizo", u"Calzada",
-                     u"Camino", u"Camping", u"Cantera", u"Cantina",
-                     u"Cantón", u"Carrera", u"Carrero", u"Carreterín",
-                     u"Carretil", u"Carril", u"Caserío", u"Chalet",
-                     u"Cinturón", u"Circunvalación", u"Cobertizo",
-                     u"Colonia", u"Complejo", u"Conjunto", u"Convento",
-                     u"Cooperativa", u"Corral", u"Corralillo", u"Corredor",
-                     u"Cortijo", u"Costanilla", u"Costera", u"Cuadra",
-                     u"Cuesta", u"Dehesa", u"Demarcación", u"Diagonal",
-                     u"Diseminado", u"Edificio", u"Empresa", u"Entrada",
-                     u"Escalera", u"Escalinata", u"Espalda", u"Estación",
-                     u"Estrada", u"Explanada", u"Extramuros", u"Extrarradio",
-                     u"Fábrica", u"Galería", u"Glorieta", u"Gran Vía",
-                     u"Granja", u"Hipódromo", u"Jardín", u"Ladera",
-                     u"Llanura", u"Malecón", u"Mercado", u"Mirador",
-                     u"Monasterio", u"Muelle", u"Núcleo", u"Palacio",
-                     u"Pantano", u"Paraje", u"Parque", u"Particular",
-                     u"Partida", u"Pasadizo", u"Pasaje", u"Paseo",
-                     u"Paseo marítimo", u"Pasillo", u"Plaza", u"Plazoleta",
-                     u"Plazuela", u"Poblado", u"Polígono", u"Polígono 
industrial",
-                     u"Portal", u"Pórtico", u"Portillo", u"Prazuela",
-                     u"Prolongación", u"Pueblo", u"Puente", u"Puerta",
-                     u"Puerto", u"Punto kilométrico", u"Rampla",
-                     u"Residencial", u"Ribera", u"Rincón", u"Rinconada",
-                     u"Sanatorio", u"Santuario", u"Sector", u"Sendera",
-                     u"Sendero", u"Subida", u"Torrente", u"Tránsito",
-                     u"Transversal", u"Trasera", u"Travesía", u"Urbanización",
-                     u"Vecindario", u"Vereda", u"Viaducto", u"Viviendas",
-
-                     # French (being distinct from Catalan and Spanish)
-                     u"Accès", u"Allée", u"Allées", u"Autoroute", u"Avenue", 
u"Barrage",
-                     u"Boulevard", u"Carrefour", u"Chaussée", u"Chemin",
-                     u"Cheminement", u"Cale", u"Cales", u"Cavée", u"Cité",
-                     u"Clos", u"Coin", u"Côte", u"Cour", u"Cours", u"Descente",
-                     u"Degré", u"Escalier",
-                     u"Escaliers", u"Esplanade", u"Funiculaire",
-                     u"Giratoire", u"Hameau", u"Impasse", u"Jardin",
-                     u"Jardins", u"Liaison", u"Mail", u"Montée", u"Môle",
-                     u"Parc", u"Passage", u"Passerelle", u"Passerelles",
-                     u"Place", u"Placette", u"Pont", u"Promenade",
-                     u"Petite Avenue", u"Petite Rue", u"Quai",
-                     u"Rampe", u"Rang", u"Résidence", u"Rond-Point",
-                     u"Route forestière", u"Route", u"Rue", u"Ruelle",
-                     u"Square", u"Sente", u"Sentier", u"Sentiers", 
u"Terre-Plein",
-                     u"Télécabine", u"Traboule", u"Traverse", u"Tunnel",
-                     u"Venelle", u"Villa", u"Virage"
-                   ]
-
-    DETERMINANTS = [ # Catalan
-                     u" de", u" de la", u" del", u" dels", u" d'",
-                     u" de l'", u" de sa", u" de son", u" de s'",
-                     u" de ses", u" d'en", u" de na", u" de n'",
-
-                     # Spanish (being distinct from Catalan)
-                     u" de las",  u" de los",
-
-                     # French (being distinct from Catalan and Spanish)
-                     u" du",
-                     u""]
-
-
-    DETERMINANTS = [ u" de", u" de la", u" del", u" de las",
-                     u" dels", u" de los", u" d'", u" de l'", u"de sa", u"de 
son", u"de s'",
-                     u"de ses", u"d'en", u"de na", u"de n'", u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-    N_ACCENT = re.compile(ur"[ñ]", re.IGNORECASE | re.UNICODE)
-    C_ACCENT = re.compile(ur"[ç]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        s = self.N_ACCENT.sub("n", s)
-        s = self.C_ACCENT.sub("c", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_pt_br_generic(i18n):
-    APPELLATIONS = [ u"Aeroporto", u"Alameda", u"Área", u"Avenida",
-                     u"Campo", u"Chácara", u"Colônia",
-                     u"Condomínio", u"Conjunto", u"Distrito", u"Esplanada", 
u"Estação",
-                     u"Estrada", u"Favela", u"Fazenda",
-                     u"Feira", u"Jardim", u"Ladeira", u"Lago",
-                     u"Lagoa", u"Largo", u"Loteamento", u"Morro", u"Núcleo",
-                     u"Parque", u"Passarela", u"Pátio", u"Praça", u"Quadra",
-                     u"Recanto", u"Residencial", u"Rua",
-                     u"Setor", u"Sítio", u"Travessa", u"Trecho", u"Trevo",
-                     u"Vale", u"Vereda", u"Via", u"Viaduto", u"Viela",
-                     u"Vila" ]
-    DETERMINANTS = [ u" do", u" da", u" dos", u" das", u"" ]
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_ar_generic(i18n):
-    APPELLATIONS = [ u"شارع", u"طريق", u"زقاق", u"نهج", u"جادة",
-                     u"ممر", u"حارة",
-                     u"كوبري", u"كوبرى", u"جسر", u"مطلع", u"منزل",
-                     u"مفرق", u"ملف", u"تقاطع",
-                     u"ساحل",
-                     u"ميدان", u"ساحة", u"دوار" ]
-
-    DETERMINANTS = [ u" ال", u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    A_ACCENT = re.compile(ur"[اإآ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.A_ACCENT.sub("أ", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-    def isrtl(self):
-        return True
-
-class i18n_ru_generic(i18n):
-    APPELLATIONS = [ u"ул", u"бул", u"пер", u"пр", u"улица", u"бульвар", 
u"проезд",
-                     u"проспект", u"площадь", u"сквер", u"парк" ]
-    # only "ул." and "пер." are recommended shortenings, however other words 
can 
-    # occur shortened.
-    #
-    # http://bit.ly/6ASISp (OSM wiki)
-    #
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)\.?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        # usually, there are no accents in russian names, only "ё" sometimes, 
but
-        # not as first letter
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_nl_generic(i18n):
-    #
-    # Dutch streets are often named after people and include a title.
-    # The title will be captured as part of the <prefix>
-    #
-    APPELLATIONS = [ u"St.", u"Sint", u"Ptr.", u"Pater",
-                     u"Prof.", u"Professor", u"Past.", u"Pastoor",
-                     u"Pr.", u"Prins", u"Prinses", u"Gen.", u"Generaal",
-                     u"Mgr.", u"Monseigneur", u"Mr.", u"Meester",
-                     u"Burg.", u"Burgermeester", u"Dr.", u"Dokter",
-                     u"Ir.", u"Ingenieur", u"Ds.", u"Dominee", u"Deken",
-                     u"Drs.",
-                     # counting words before street name,
-                     # e.g. "1e Walstraat" => "Walstraat (1e)"
-                     u"\d+e",
-                     u"" ]
-    #
-    # Surnames in Dutch streets named after people tend to have the middle name
-    # listed after the rest of the surname,
-    # e.g. "Prins van Oranjestraat" => "Oranjestraat (Prins van)"
-    # Likewise, articles are captured as part of the prefix,
-    # e.g. "Den Urling" => "Urling (Den)"
-    #
-    DETERMINANTS = [ u"\s?van der", u"\s?van den", u"\s?van de", u"\s?van",
-                     u"\s?Den", u"\s?D'n", u"\s?D'", u"\s?De", u"\s?'T", 
u"\s?Het",
-                     u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)),
-                                      re.IGNORECASE | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        #
-        # Make sure name actually contains something,
-        # the PREFIX_REGEXP.match fails on zero-length strings
-        #
-        if len(name) == 0:
-            return name
-
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        matches = self.PREFIX_REGEXP.match(name)
-        #
-        # If no prefix was captured, that's okay. Don't substitute
-        # the name however, "<name> ()" looks silly
-        #
-        if matches == None:
-            return name
-
-        if matches.group('prefix'):
-            name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_hr_HR(i18n):
-    # for _upper_unaccent_string
-    C_ACCENT = re.compile(ur"[ćč]", re.IGNORECASE | re.UNICODE)
-    D_ACCENT = re.compile(ur"đ|dž", re.IGNORECASE | re.UNICODE)
-    N_ACCENT = re.compile(ur"nj", re.IGNORECASE | re.UNICODE)
-    L_ACCENT = re.compile(ur"lj", re.IGNORECASE | re.UNICODE)
-    S_ACCENT = re.compile(ur"š", re.IGNORECASE | re.UNICODE)
-    Z_ACCENT = re.compile(ur"ž", re.IGNORECASE | re.UNICODE)
-
-    def _upper_unaccent_string(self, s):
-        s = self.C_ACCENT.sub("c", s)
-        s = self.D_ACCENT.sub("d", s)
-        s = self.N_ACCENT.sub("n", s)
-        s = self.L_ACCENT.sub("l", s)
-        s = self.S_ACCENT.sub("s", s)
-        s = self.Z_ACCENT.sub("z", s)
-        return s.upper()
-
-    def __init__(self, language, locale_path):
-        """Install the _() function for the chosen locale other
-           object initialisation"""
-        self.language = str(language) # FIXME: why do we have unicode here?
-        _install_language(language, locale_path)
-
-    def language_code(self):
-        """returns the language code of the specific language
-           supported, e.g. fr_FR.UTF-8"""
-        return self.language
-
-    def user_readable_street(self, name):
-        """ transforms a street name into a suitable form for
-            the map index, e.g. Paris (Rue de) for French"""
-        return name
-
-    ## FIXME: only first letter does not work for Croatian digraphs (dž, lj, 
nj)
-    def first_letter_equal(self, a, b):
-        """returns True if the letters a and b are equal in the map index,
-           e.g. É and E are equals in French map index"""
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_pl_generic(i18n):
-
-    APPELLATIONS = [ u"Dr.", u"Doktora", u"Ks.", u"Księdza",
-                     u"Generała", u"Gen.",
-                     u"Aleja", u"Plac", u"Pl.",
-                     u"Rondo", u"rondo", u"Profesora",
-                     u"Prof.",
-                     u"" ]
-
-    DETERMINANTS = [ u"\s?im.", u"\s?imienia", u"\s?pw.",
-                     u"" ]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)),
-                                      re.IGNORECASE | re.UNICODE)
-
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        #
-        # Make sure name actually contains something,
-        # the PREFIX_REGEXP.match fails on zero-length strings
-        #
-        if len(name) == 0:
-            return name
-
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        matches = self.PREFIX_REGEXP.match(name)
-        #
-        # If no prefix was captured, that's okay. Don't substitute
-        # the name however, "<name> ()" looks silly
-        #
-        if matches == None:
-            return name
-
-        if matches.group('prefix'):
-            name = self.PREFIX_REGEXP.sub(r"\g<name>, \g<prefix>", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return a == b
-
-
-class i18n_de_generic(i18n):
-    #
-    # German streets are often named after people and include a title.
-    # The title will be captured as part of the <prefix>
-       # Covering airport names and "New"/"Old" as prefixes as well
-    #
-    APPELLATIONS = [ u"Alte", u"Alter", u"Doktor", u"Dr.",
-                     u"Flughafen", u"Flugplatz", u"Gen.,", u"General",
-                     u"Neue", u"Neuer", u"Platz",
-                     u"Prinz", u"Prinzessin", u"Prof.",
-                     u"Professor" ]
-    #
-    # Surnames in german streets named after people tend to have the middle 
name
-    # listed after the rest of the surname,
-    # e.g. "Platz der deutschen Einheit" => "deutschen Einheit (Platz der)"
-    # Likewise, articles are captured as part of the prefix,
-    # e.g. "An der Märchenwiese" => "Märchenwiese (An der)"
-    #
-    DETERMINANTS = [ u"\s?An den", u"\s?An der", u"\s?Am",
-                     u"\s?Auf den" , u"\s?Auf der"
-                     u" an", u" des", u" der", u" von", u" vor"]
-
-    SPACE_REDUCE = re.compile(r"\s+")
-    PREFIX_REGEXP = re.compile(r"^(?P<prefix>(%s)(%s)?)\s?\b(?P<name>.+)" %
-                                    ("|".join(APPELLATIONS),
-                                     "|".join(DETERMINANTS)), re.IGNORECASE
-                                                                 | re.UNICODE)
-
-    # for IndexPageGenerator._upper_unaccent_string
-    E_ACCENT = re.compile(ur"[éèêëẽ]", re.IGNORECASE | re.UNICODE)
-    I_ACCENT = re.compile(ur"[íìîïĩ]", re.IGNORECASE | re.UNICODE)
-    A_ACCENT = re.compile(ur"[áàâäã]", re.IGNORECASE | re.UNICODE)
-    O_ACCENT = re.compile(ur"[óòôöõ]", re.IGNORECASE | re.UNICODE)
-    U_ACCENT = re.compile(ur"[úùûüũ]", re.IGNORECASE | re.UNICODE)
-
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def _upper_unaccent_string(self, s):
-        s = self.E_ACCENT.sub("e", s)
-        s = self.I_ACCENT.sub("i", s)
-        s = self.A_ACCENT.sub("a", s)
-        s = self.O_ACCENT.sub("o", s)
-        s = self.U_ACCENT.sub("u", s)
-        return s.upper()
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        #
-        # Make sure name actually contains something,
-        # the PREFIX_REGEXP.match fails on zero-length strings
-        #
-        if len(name) == 0:
-            return name
-
-        name = name.strip()
-        name = self.SPACE_REDUCE.sub(" ", name)
-        name = self.PREFIX_REGEXP.sub(r"\g<name> (\g<prefix>)", name)
-        return name
-
-    def first_letter_equal(self, a, b):
-        return self._upper_unaccent_string(a) == self._upper_unaccent_string(b)
-
-class i18n_generic(i18n):
-    def __init__(self, language, locale_path):
-        self.language = str(language)
-        _install_language(language, locale_path)
-
-    def language_code(self):
-        return self.language
-
-    def user_readable_street(self, name):
-        return name
-
-    def first_letter_equal(self, a, b):
-        return a == b
-
-# When not listed in the following map, default language class will be
-# i18n_generic
-language_class_map = {
-    'fr_BE.UTF-8': i18n_fr_generic,
-    'fr_FR.UTF-8': i18n_fr_generic,
-    'fr_CA.UTF-8': i18n_fr_generic,
-    'fr_CH.UTF-8': i18n_fr_generic,
-    'fr_LU.UTF-8': i18n_fr_generic,
-    'en_AG': i18n_generic,
-    'en_AU.UTF-8': i18n_generic,
-    'en_BW.UTF-8': i18n_generic,
-    'en_CA.UTF-8': i18n_generic,
-    'en_DK.UTF-8': i18n_generic,
-    'en_GB.UTF-8': i18n_generic,
-    'en_HK.UTF-8': i18n_generic,
-    'en_IE.UTF-8': i18n_generic,
-    'en_IN': i18n_generic,
-    'en_NG': i18n_generic,
-    'en_NZ.UTF-8': i18n_generic,
-    'en_PH.UTF-8': i18n_generic,
-    'en_SG.UTF-8': i18n_generic,
-    'en_US.UTF-8': i18n_generic,
-    'en_ZA.UTF-8': i18n_generic,
-    'en_ZW.UTF-8': i18n_generic,
-    'nb_NO.UTF-8': i18n_generic,
-    'nl_BE.UTF-8': i18n_nl_generic,
-    'nl_NL.UTF-8': i18n_nl_generic,
-    'it_IT.UTF-8': i18n_it_generic,
-    'it_CH.UTF-8': i18n_it_generic,
-    'de_AT.UTF-8': i18n_de_generic,
-    'de_BE.UTF-8': i18n_de_generic,
-    'de_DE.UTF-8': i18n_de_generic,
-    'de_LU.UTF-8': i18n_de_generic,
-    'de_CH.UTF-8': i18n_de_generic,
-    'es_ES.UTF-8': i18n_es_generic,
-    'es_AR.UTF-8': i18n_es_generic,
-    'es_BO.UTF-8': i18n_es_generic,
-    'es_CL.UTF-8': i18n_es_generic,
-    'es_CR.UTF-8': i18n_es_generic,
-    'es_DO.UTF-8': i18n_es_generic,
-    'es_EC.UTF-8': i18n_es_generic,
-    'es_SV.UTF-8': i18n_es_generic,
-    'es_GT.UTF-8': i18n_es_generic,
-    'es_HN.UTF-8': i18n_es_generic,
-    'es_MX.UTF-8': i18n_es_generic,
-    'es_NI.UTF-8': i18n_es_generic,
-    'es_PA.UTF-8': i18n_es_generic,
-    'es_PY.UTF-8': i18n_es_generic,
-    'es_PE.UTF-8': i18n_es_generic,
-    'es_PR.UTF-8': i18n_es_generic,
-    'es_US.UTF-8': i18n_es_generic,
-    'es_UY.UTF-8': i18n_es_generic,
-    'es_VE.UTF-8': i18n_es_generic,
-    'ca_ES.UTF-8': i18n_ca_generic,
-    'ca_AD.UTF-8': i18n_ca_generic,
-    'ca_FR.UTF-8': i18n_ca_generic,
-    'pt_BR.UTF-8': i18n_pt_br_generic,
-    'da_DK.UTF-8': i18n_generic,
-    'ar_AE.UTF-8': i18n_ar_generic,
-    'ar_BH.UTF-8': i18n_ar_generic,
-    'ar_DZ.UTF-8': i18n_ar_generic,
-    'ar_EG.UTF-8': i18n_ar_generic,
-    'ar_IN': i18n_ar_generic,
-    'ar_IQ.UTF-8': i18n_ar_generic,
-    'ar_JO.UTF-8': i18n_ar_generic,
-    'ar_KW.UTF-8': i18n_ar_generic,
-    'ar_LB.UTF-8': i18n_ar_generic,
-    'ar_LY.UTF-8': i18n_ar_generic,
-    'ar_MA.UTF-8': i18n_ar_generic,
-    'ar_OM.UTF-8': i18n_ar_generic,
-    'ar_QA.UTF-8': i18n_ar_generic,
-    'ar_SA.UTF-8': i18n_ar_generic,
-    'ar_SD.UTF-8': i18n_ar_generic,
-    'ar_SY.UTF-8': i18n_ar_generic,
-    'ar_TN.UTF-8': i18n_ar_generic,
-    'ar_YE.UTF-8': i18n_ar_generic,
-    'hr_HR.UTF-8': i18n_hr_HR,
-    'ru_RU.UTF-8': i18n_ru_generic,
-    'pl_PL.UTF-8': i18n_pl_generic,
-}
-
-def install_translation(locale_name, locale_path):
-    """Return a new i18n class instance, depending on the specified
-    locale name (eg. "fr_FR.UTF-8"). See output of "locale -a" for a
-    list of system-supported locale names. When none matching, default
-    class is i18n_generic"""
-    language_class = language_class_map.get(locale_name, i18n_generic)
-    return language_class(locale_name, locale_path)
diff --git a/ocitysmap/map_canvas.py b/ocitysmap/map_canvas.py
deleted file mode 100644
index d606ab8..0000000
--- a/ocitysmap/map_canvas.py
+++ /dev/null
@@ -1,398 +0,0 @@
-#! /usr/bin/env python
-# -*- coding: utf-8 -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-import os, mapnik, logging, locale, gzip
-
-# The ogr module is now known as osgeo.ogr in recent versions of the
-# module, but we want to keep compatibility with older versions
-try:
-    from osgeo import ogr
-except ImportError:
-    import ogr
-
-from coords import BoundingBox
-import draw_utils
-
-try:
-    import cairo
-except ImportError:
-    cairo = None
-
-l = logging.getLogger('ocitysmap')
-
-class GLOBALS:
-    MAIN_PROJECTION = "+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 
+x_0=0.0 +y_0=0 +k=1.0 +units=m address@hidden +no_defs +over"
-
-
-class GridFile:
-    """
-    Class to generate a shape_file containing vertical/horizontal lines.
-    Call flush() to commit the final rendering to disk. Afterwards,
-    any attempt to add grid lines will fail (exception).
-    The coordinates are not related to any projection
-    """
-    def __init__(self, envelope, out_filename, layer_name = "Grid"):
-        """
-        @param envelope (BoundingBox) envelope of the grid lines
-        @param out_filename (string) path to the output shape file we generate
-        @param layer_name (string) layer name in the shape file
-        """
-        self._envelope = envelope
-        self._filepath = out_filename
-        driver = ogr.GetDriverByName('ESRI Shapefile')
-        if os.path.exists(out_filename):
-            # Delete the detination file first
-            driver.DeleteDataSource(out_filename)
-        self._ds = driver.CreateDataSource(out_filename)
-        self._layer = self._ds.CreateLayer(layer_name,
-                                           geom_type=ogr.wkbLineString)
-
-    def add_horiz_line(self, y):
-        """
-        Add a new latitude line at the given latitude
-        """
-        line = ogr.Geometry(type = ogr.wkbLineString)
-        line.AddPoint_2D(self._envelope.get_top_left()[1], y)
-        line.AddPoint_2D(self._envelope.get_bottom_right()[1], y)
-        f = ogr.Feature(feature_def = self._layer.GetLayerDefn())
-        f.SetGeometryDirectly(line)
-        self._layer.CreateFeature(f)
-        f.Destroy()
-
-    def add_vert_line(self, x):
-        """
-        Add a new longitude line at the given longitude
-        """
-        line = ogr.Geometry(type = ogr.wkbLineString)
-        line.AddPoint_2D(x, self._envelope.get_top_left()[0])
-        line.AddPoint_2D(x, self._envelope.get_bottom_right()[0])
-        f = ogr.Feature(feature_def = self._layer.GetLayerDefn())
-        f.SetGeometryDirectly(line)
-        self._layer.CreateFeature(f)
-        f.Destroy()
-
-    def flush(self):
-        """
-        Commit the file to disk and prevent any further addition of
-        new longitude/latitude lines
-        """
-        self._ds.Destroy()
-        self._ds = None
-
-    def get_filepath(self):
-        """
-        Return the path to the destination shape file
-        """
-        return self._filepath
-
-    def __str__(self):
-        return "GridFile(%s)" % self._filepath
-
-
-def create_shapefile_polygon_from_wkt(out_fname, wkt):
-    driver = ogr.GetDriverByName('ESRI Shapefile')
-    if os.path.exists(out_fname):
-        driver.DeleteDataSource(out_fname)
-    ds = driver.CreateDataSource(out_fname)
-    layer = ds.CreateLayer('poly', geom_type=ogr.wkbPolygon)
-
-    prev_locale = locale.getlocale(locale.LC_ALL)
-    locale.setlocale(locale.LC_ALL, "C")
-    try:
-        poly = ogr.CreateGeometryFromWkt(wkt)
-    finally:
-        locale.setlocale(locale.LC_ALL, prev_locale)
-
-    f = ogr.Feature(feature_def = layer.GetLayerDefn())
-    f.SetGeometryDirectly(poly)
-    layer.CreateFeature(f)
-    f.Destroy()
-    ds.Destroy()
-
-
-def _project_envelope(proj, envelope):
-    """
-    Returns a new envelop, projected along the given projection object.
-    @param proj mapnik.Projection object
-    @param envelope mapnik.Envelope object
-    """
-    c0 = proj.forward(mapnik.Coord(envelope.minx, envelope.miny))
-    c1 = proj.forward(mapnik.Coord(envelope.maxx, envelope.maxy))
-    return mapnik.Envelope(c0.x, c0.y, c1.x, c1.y)
-
-
-class MapCanvas:
-    """
-    OSM in the background of a canvas used to draw grids and text.
-    """
-    def __init__(self, mapfile_path, geographic_bbox, graph_bbox = None):
-        """
-        @param mapfile_path (string) path the the osm.xml map file
-        @param geographic_bbox (BoundingBox) bounding box to render, in
-        latlong (4326) coordinates
-        @param graph_bbox (int) graphical width/height of the
-        rendered area for raster output (None = auto)
-        """
-        self._projname    = GLOBALS.MAIN_PROJECTION
-        self._proj        = mapnik.Projection(self._projname)
-        if graph_bbox is None:
-            graph_bbox = geographic_bbox.get_pixel_size_for_zoom_factor()
-        elif str(graph_bbox).startswith('zoom:'):
-            graph_bbox = 
geographic_bbox.get_pixel_size_for_zoom_factor(int(graph_bbox[5:]))
-        self._envelope    = mapnik.Envelope(geographic_bbox.get_top_left()[1],
-                                            geographic_bbox.get_top_left()[0],
-                                            
geographic_bbox.get_bottom_right()[1],
-                                            
geographic_bbox.get_bottom_right()[0])
-        # Determine the size of a meter in pixels (float)
-        ymeters, xmeters = geographic_bbox.spheric_sizes()
-        xpixels = graph_bbox[0] / xmeters
-        ypixels = graph_bbox[1] / ymeters
-        self.one_meter_in_pixels = min(xpixels, ypixels)
-        l.debug('Geo size: %sx%s, pixels=%sx%s, 1m=%s|%s' \
-                    % (xmeters, ymeters,
-                       graph_bbox[0], graph_bbox[1],
-                       xpixels, ypixels))
-
-        self._map         = mapnik.Map(graph_bbox[0],
-                                       graph_bbox[1],
-                                       self._projname)
-        mapnik.load_map(self._map, mapfile_path)
-
-        # Keep geographic bounding box, ignoring one dimension of the
-        # specified grwidth/grheight constraints
-        self._map.aspect_fix_mode = mapnik.aspect_fix_mode.SHRINK_CANVAS
-
-        # The data to render in the resulting scene
-        self._labels      = mapnik.PointDatasource()
-        self._labelstyles = set() # Set of label styles, used to
-                                  # define the sets of layers
-        self._shapes      = []    # Data from the shape files
-        self._dirty       = True  # Rendering needed because data have
-                                  # been added
-
-    def add_label(self, x, y, str_label,
-                  str_color = "red", alpha = 0.5,
-                  font_size = 11,
-                  font_family = "DejaVu Sans Book"):
-        """
-        Add a label on top of the map.
-        @param x,y Coordinates of the label, in latlong coordinates (4326)
-        @param str_label (string) Text to display
-        @param str_color (string) Color definition (html)
-        @param alpha (float 0..1) Color opacity
-        @param font_size (int) Font size of the label
-        @param font_family (string) Name of the font
-        """
-        pt = self._proj.forward(mapnik.Coord(x,  y))
-        labelstyle = (str_color, alpha, font_size, font_family)
-        self._labels.add_point(pt.x, pt.y,
-                               'style_%x' % hash(labelstyle),
-                               str_label)
-        self._labelstyles.add(labelstyle)
-        self._dirty = True
-
-    def _render_label_style(self, str_color, alpha, font_size, font_family):
-        labelstyle = (str_color, alpha, font_size, font_family)
-        H = hash(labelstyle)
-
-        s = mapnik.Style()
-        r = mapnik.Rule()
-        c = mapnik.Color(str_color)
-        c.a = int(255 * alpha)
-        symb = mapnik.TextSymbolizer('style_%x' % H,
-                                     font_family,
-                                     int(font_size),
-                                     c)
-        symb.allow_overlap       = True
-        symb.set_label_placement = mapnik.label_placement.POINT_PLACEMENT
-        r.symbols.append(symb)
-        s.rules.append(r)
-
-        lyr = mapnik.Layer('Labels_%x' % H, self._projname)
-        lyr.datasource = self._labels
-        self._map.append_style('labels_%x' % H, s)
-        lyr.styles.append('labels_%x' % H)
-        self._map.layers.append(lyr)
-
-    def add_shapefile(self, path_shpfile, str_color = 'grey', alpha = 0.5,
-                      line_width = 1.):
-        """
-        Add a shape file to display on top of the map
-        @param path_shpfile (string) path to the shape file to render
-        @param str_color (string) Color definition (html)
-        @param alpha (float 0..1) Color opacity
-        @param line_width (float) line width in raster pixels
-        """
-        col = mapnik.Color(str_color)
-        col.a = int(255 * alpha)
-        self._shapes.append(['SHPFILE', (path_shpfile, col, line_width)])
-        self._dirty = True
-
-    def _render_shp(self, path_shpfile, obj_color, line_width):
-        shpid = os.path.basename(path_shpfile)
-        s,r = mapnik.Style(), mapnik.Rule()
-        r.symbols.append(mapnik.PolygonSymbolizer(obj_color))
-        r.symbols.append(mapnik.LineSymbolizer(obj_color, line_width))
-        s.rules.append(r)
-        self._map.append_style('style_' + shpid, s)
-        lyr = mapnik.Layer(shpid)
-        lyr.datasource = mapnik.Shapefile(file=path_shpfile)
-        lyr.styles.append("style_" + shpid)
-        self._map.layers.append(lyr)
-
-    def render_map(self):
-        """
-        Render map in memory. Automatically called by save_map(), only
-        when needed.
-        @return the mapnik map object
-        """
-        for lyrtype, lyrparms in self._shapes:
-            self._render_shp(*lyrparms)
-
-        for labelstyle in self._labelstyles:
-            self._render_label_style(*labelstyle)
-
-        l.debug("rendering to bbox %s as %sx%s..."
-                % (self._envelope, self._map.height, self._map.width))
-        bbox = _project_envelope(self._proj, self._envelope)
-        self._map.zoom_to_box(bbox)
-        l.debug("rendered to bbox %s as %sx%s." \
-                    % (bbox, self._map.height, self._map.width))
-        self._dirty = False
-        return self._map
-
-    def save_map(self, output_filename,
-                 title = "City's map",
-                 file_type = None,
-                 copyright_logo_png = None,
-                 force = False):
-        """
-        Save the map as an image. By default, the format is inferred
-        from the filename (its extension). It can be forced with the
-        'file_type' parameter.
-        @param output_filename (string) file to generate
-        @param file_type (string) None, or 'xml', 'png', 'ps',
-        'pdf', 'svg' or 'svgz'
-        @param force (bool) fore render_map() to be called, even if it
-        does not appear to have changed since last render_map()
-        """
-        if self._dirty or force:
-            self.render_map()
-
-        if file_type is None:
-            file_type = output_filename.split('.')[-1]
-        
-        file_type = file_type.lower()
-        cairo_factory = None
-
-        if file_type == 'xml':
-            mapnik.save_map(self._map, output_filename)
-            return
-        
-        elif file_type == 'csv':
-            l.debug('not rendering map as csv (not supported)')
-            return
-
-        elif file_type in ('png', 'png24'): # 24-bits, the default
-            if (title is None) or (cairo is None):
-                mapnik.render_to_file(self._map, output_filename, 'png')
-                return
-            else:
-                cairo_factory = \
-                    lambda w,h: cairo.ImageSurface(cairo.FORMAT_RGB24, w, h)
-
-        elif file_type == 'svg' and cairo is not None:
-            cairo_factory = lambda w,h: cairo.SVGSurface(output_filename, w, h)
-
-        elif file_type == 'svgz' and cairo is not None:
-            def cairo_factory(w,h):
-                gz = gzip.GzipFile(output_filename, 'wb')
-                return cairo.SVGSurface(gz, w, h)
-
-        elif file_type == 'pdf' and cairo is not None:
-            cairo_factory = lambda w,h: cairo.PDFSurface(output_filename, w, h)
-
-        elif file_type == 'ps' and cairo is not None:
-            cairo_factory = lambda w,h: cairo.PSSurface(output_filename, w, h)
-
-        else:
-            raise ValueError('Unsupported output format: %s' % file_type)
-
-        # Cairo reendering
-        if title is not None:
-            frame_width = int(max(self._map.height / 20., 30))
-
-            surface = cairo_factory(self._map.width + frame_width*2,
-                                    self._map.height + frame_width*2)
-
-            def my_render(ctx):
-                mapnik.render(self._map,
-                              ctx)
-                draw_utils.add_logo(ctx, self._map.width,
-                                    self._map.height,
-                                    copyright_logo_png)
-
-            draw_utils.enclose_in_frame(my_render,
-                                        self._map.width, self._map.height,
-                                        title,
-                                        surface,
-                                        self._map.width + frame_width*2,
-                             self._map.height + frame_width*2, frame_width)
-        else:
-            surface = cairo_factory(self._map.width, self._map.height)
-            ctx = cairo.Context(surface)
-            mapnik.render(self._map, ctx)
-
-        surface.flush()
-
-        # png rendering with cairo...
-        if file_type in ('png', 'png24'):
-            surface.write_to_png(output_filename)
-
-        surface.finish()
-
-
-if __name__ == "__main__":
-    # A few tests
-
-    # Create the grid shape file
-    g = GridFile("mygrid.shp")
-    g.add_horiz_line(44.48)
-    g.add_vert_line(-1.08)
-    g.flush()
-    
-    # Declare a map with a grid and some text
-    sanguinet = MapCanvas("/home/decot/downloads/svn/mapnik-osm/osm.xml",
-                          BoundingBox(44.4883, -1.0901,
-                                      44.4778, -1.0637))
-    sanguinet.add_label(-1.075, 44.483, "Toto")
-    sanguinet.add_label(-1.075, 44.479, "Titi", '#ff00ff', 30)
-    sanguinet.add_shapefile(g.get_filepath())
-
-    # Save the rendered map into different file formats
-    for fname in ('sanguinet.xml', 'sanguinet.png',
-                  'sanguinet.svg', 'sanguinet.pdf',
-                  'sanguinet.ps', 'sanguinet.jpg'):
-        sanguinet.save_map(fname)
diff --git a/ocitysmap/street_index.py b/ocitysmap/street_index.py
deleted file mode 100644
index 9de5322..0000000
--- a/ocitysmap/street_index.py
+++ /dev/null
@@ -1,1050 +0,0 @@
-# -*- coding: utf-8; mode: Python -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-import cairo
-import ConfigParser
-import csv
-import datetime
-import gzip
-import locale
-import logging
-import math
-import os
-import pango
-import pangocairo
-import psycopg2
-import re
-import sys
-import tempfile
-import traceback
-
-import grid
-import i18n
-import map_canvas
-import utils
-
-from coords import BoundingBox
-from draw_utils import enclose_in_frame
-
-import psycopg2.extensions
-# compatibility with django: see http://code.djangoproject.com/ticket/5996
-psycopg2.extensions.register_type(psycopg2.extensions.UNICODE)
-# SQL string escaping routine
-sql_escape_unicode = lambda s: psycopg2.extensions.adapt(s.encode('utf-8'))
-
-LOG = logging.getLogger('maposmatic')
-STATEMENT_TIMEOUT_MINUTES = 18
-
-class BaseOCitySMapError(Exception):
-    """Base class for exceptions thrown by OCitySMap."""
-
-class UnsufficientDataError(BaseOCitySMapError):
-    """Not enough data in the OSM database to proceed."""
-
-def _user_readable_label(squares):
-    """Creates a label usable in the street index adjacent to the map
-       from a square list."""
-
-    def couple_compare(x,y):
-        a = y[0] - x[0]
-        if a:
-            return a
-        return y[1] - x[1]
-
-    def distance(a,b):
-        return (b[0]-a[0])**2 + (b[1]-a[1])**2
-
-    minx = min([x[0] for x in squares])
-    maxx = max([x[0] for x in squares])
-    miny = min([x[1] for x in squares])
-    maxy = max([x[1] for x in squares])
-    if len(squares) == 1:
-        label = (utils.gen_vertical_square_label(squares[0][0]) +
-                 utils.gen_horizontal_square_label(squares[0][1]))
-    elif minx == maxx:
-        label = ('%s%s-%s' % (utils.gen_vertical_square_label(minx),
-                              utils.gen_horizontal_square_label(miny),
-                              utils.gen_horizontal_square_label(maxy)))
-    elif miny == maxy:
-        label = ('%s-%s%s' % (utils.gen_vertical_square_label(minx),
-                              utils.gen_vertical_square_label(maxx),
-                              utils.gen_horizontal_square_label(miny)))
-    elif (maxx - minx + 1) * (maxy - miny + 1) == len(squares):
-        label = ('%s-%s%s-%s' % (utils.gen_vertical_square_label(minx),
-                                 utils.gen_vertical_square_label(maxx),
-                                 utils.gen_horizontal_square_label(miny),
-                                 utils.gen_horizontal_square_label(maxy)))
-    else:
-        squares_x_first = sorted(squares, couple_compare)
-        squares_y_first = sorted(squares, lambda x,y: couple_compare(y,x))
-        if (distance(squares_x_first[0], squares_x_first[-1]) >
-            distance(squares_y_first[0], squares_y_first[-1])):
-            first = squares_x_first[0]
-            last = squares_x_first[-1]
-        else:
-            first = squares_y_first[0]
-            last = squares_y_first[-1]
-
-        label = '%s%s...%s%s' % (utils.gen_vertical_square_label(first[0]),
-                                 utils.gen_horizontal_square_label(first[1]),
-                                 utils.gen_vertical_square_label(last[0]),
-                                 utils.gen_horizontal_square_label(last[1]))
-    return label
-
-class IndexPageGenerator:
-    def __init__(self, streets, i18n):
-        self.streets = streets
-        self.i18n = i18n
-
-    def _street_label_width(self, street, layout):
-        (firstletter, label, location) = street
-        layout.set_text(label)
-        width = layout.get_size()[0] / pango.SCALE
-        layout.set_text(location)
-        width += layout.get_size()[0] / pango.SCALE
-        return width
-
-    def _get_font_parameters(self, cr, pc, fontsize):
-        layout = pc.create_layout()
-        fd = pango.FontDescription("DejaVu")
-        fd.set_size(int(fontsize * 1.2 * pango.SCALE))
-        f = layout.get_context().load_font(fd)
-        heading_fm = f.get_metrics()
-
-        fd.set_size(fontsize * pango.SCALE)
-        layout.set_font_description(fd)
-        f = layout.get_context().load_font(fd)
-        fm = f.get_metrics()
-
-        em = fm.get_approximate_char_width() / pango.SCALE
-        widths = map(lambda x: self._street_label_width(x, layout), 
self.streets)
-        maxwidth = max(widths)
-        colwidth = maxwidth + 3 * em
-
-        return {
-            'colwidth' : colwidth,
-            'heading_fascent': heading_fm.get_ascent() / pango.SCALE,
-            'heading_fheight' : (heading_fm.get_ascent() + 
heading_fm.get_descent()) / pango.SCALE,
-            'fascent': fm.get_ascent() / pango.SCALE,
-            'fheight' : (fm.get_ascent() + fm.get_descent()) / pango.SCALE,
-            'em' : em,
-            }
-
-    def _fits_in_page(self, cr, pc, paperwidth, paperheight, fontsize):
-        fp = self._get_font_parameters(cr, pc, fontsize)
-
-        prevletter = u''
-        heading_letter_count = 0
-        for street in self.streets:
-            if not self.i18n.first_letter_equal(street[0], prevletter):
-                heading_letter_count += 1
-                prevletter = street[0]
-
-        colheight = len(self.streets) * fp['fheight'] + heading_letter_count * 
fp['heading_fheight']
-
-        paperncols = math.floor(paperwidth / fp['colwidth'])
-        if paperncols == 0:
-            return False
-        # Add a small space before/after each column
-        colheight += paperncols * fp['fheight']
-        colheight /= paperncols
-        return colheight < paperheight
-
-    def _compute_font_size(self, cr, pc, paperwidth, paperheight):
-        minfontsize = 6
-        maxfontsize = 128
-
-        if not self._fits_in_page(cr, pc, paperwidth, paperheight, 
minfontsize):
-            print "Index does not fit even with font size %d" % minfontsize
-            sys.exit(1)
-
-        while maxfontsize - minfontsize != 1:
-            meanfontsize = int((maxfontsize + minfontsize) / 2)
-            if self._fits_in_page(cr, pc, paperwidth, paperheight, 
meanfontsize):
-                minfontsize = meanfontsize
-            else:
-                maxfontsize = meanfontsize
-
-        return minfontsize
-
-    def render(self, cr, paperwidth, paperheight):
-        pc = pangocairo.CairoContext(cr)
-
-        cr.set_source_rgb(1, 1, 1)
-        cr.paint()
-        cr.set_source_rgb(0.0, 0.0, 0.0)
-
-        fontsize = self._compute_font_size(cr, pc, paperwidth, paperheight)
-
-        fp = self._get_font_parameters(cr, pc, fontsize)
-        heading_fheight = fp['heading_fheight']
-        heading_fascent = fp['heading_fascent']
-        fheight = fp['fheight']
-        fascent = fp['fascent']
-        colwidth = fp['colwidth']
-        em = fp['em']
-
-        remaining = paperwidth % colwidth
-        colwidth += (remaining / int(paperwidth / colwidth))
-
-        y = 0
-
-        if self.i18n.isrtl():
-            x = paperwidth - colwidth + em
-        else:
-            x = em
-
-        prevletter = u''
-        for street in self.streets:
-            # Letter label
-            firstletter = street[0]
-            if not self.i18n.first_letter_equal(firstletter, prevletter):
-                # Make sure we have no orphelin heading letter label at the
-                # end of a column
-                if y + heading_fheight + fheight > paperheight:
-                    y = 0
-
-                    if self.i18n.isrtl():
-                        x -= colwidth
-                    else:
-                        x += colwidth
-
-                # Reserve height for the heading letter label
-                y += heading_fheight
-
-                cr.set_source_rgb(0.9, 0.9, 0.9)
-                cr.rectangle(x, y - heading_fascent, colwidth - em, 
heading_fheight)
-                cr.fill()
-
-                cr.set_source_rgb(0, 0, 0)
-
-                # Draw the heading letter label
-                layout = pc.create_layout()
-                fd = pango.FontDescription("DejaVu")
-                fd.set_size(int(fontsize * 1.2 * pango.SCALE))
-                layout.set_font_description(fd)
-                layout.set_text(firstletter)
-                w = layout.get_size()[0] / pango.SCALE
-                indent = (colwidth - 2 * em - w) / 2
-                cr.move_to(x + indent, y - heading_fascent)
-                pc.show_layout(layout)
-                prevletter = firstletter
-
-            # Reserve height for the street
-            y += fheight
-            layout = pc.create_layout()
-            fd = pango.FontDescription("DejaVu")
-            fd.set_size(int(fontsize * pango.SCALE))
-            layout.set_font_description(fd)
-
-            # Compute length of the dashed line between the street name and
-            # the squares label
-            layout.set_text(street[1])
-            street_name_width = layout.get_size()[0] / pango.SCALE
-            layout.set_text(street[2])
-            squares_label_width = layout.get_size()[0] / pango.SCALE
-            line_width = colwidth - street_name_width - squares_label_width - 
2 * em
-
-            if self.i18n.isrtl():
-                # Draw squares label
-                cr.move_to(x, y - fascent)
-                layout.set_text(street[2])
-                pc.show_layout(layout)
-                # Draw dashed line
-                strokewidth = max(fontsize / 12, 1)
-                cr.set_line_width(strokewidth)
-                cr.set_dash([ strokewidth, strokewidth * 2 ])
-                cr.move_to(x + squares_label_width + em / 2, y - 0.1 * em)
-                cr.rel_line_to(line_width, 0)
-                cr.stroke()
-                # Draw street label
-                cr.move_to(x + colwidth - em - street_name_width, y - fascent)
-                layout.set_text(street[1])
-                pc.show_layout(layout)
-            else:
-                # Draw street name
-                cr.move_to(x, y - fascent)
-                layout.set_text(street[1])
-                pc.show_layout(layout)
-                # Draw dashed line
-                strokewidth = max(fontsize / 12, 1)
-                cr.set_line_width(strokewidth)
-                cr.set_dash([ strokewidth, strokewidth * 2 ])
-                cr.move_to(x + street_name_width + em / 2, y - 0.1 * em)
-                cr.rel_line_to(line_width, 0)
-                cr.stroke()
-                # Draw squares label
-                cr.move_to(x + colwidth - em - squares_label_width, y - 
fascent)
-                layout.set_text(street[2])
-                pc.show_layout(layout)
-
-            if y + fheight > paperheight:
-                y = 0
-
-                if self.i18n.isrtl():
-                    x -= colwidth
-                else:
-                    x += colwidth
-
-class OCitySMap:
-    def __init__(self, config_file=None, map_areas_prefix=None,
-                 city_name=None, boundingbox=None, osmid=None, language=None):
-        """Creates a new OCitySMap renderer instance for the given city.
-
-        Args:
-            config_file (string): location of the config file
-            map_areas_prefix (string): map_areas table name prefix
-            city_name (string): The name of the city we're created the map of.
-            boundingbox (BoundingBox): An optional BoundingBox object defining
-                the city's bounding box. If not given, OCitySMap will try to
-                guess the bounding box from the OSM data. An 
UnsufficientDataError
-                exception will be raised in the bounding box can't be guessed.
-            osmid (integer): The OSM id of the polygon of the city to render
-        """
-
-        optcnt = 0
-        for var in city_name, boundingbox, osmid:
-            if var:
-                optcnt += 1
-
-        assert optcnt == 1
-
-        (self.city_name, self.boundingbox, self.osmid) = (city_name, 
boundingbox, osmid)
-
-        if self.city_name:
-            LOG.info('OCitySMap renderer for %s.' % self.city_name)
-        elif self.boundingbox:
-            LOG.info('OCitySMap renderer for bounding box %s.' % 
self.boundingbox)
-        else:
-            LOG.info('OCitySMap renderer for OSMID %s.' % self.osmid)
-
-
-        if config_file:
-            config_files = [config_file]
-        else:
-            config_files = ['/etc/ocitysmap.conf',
-                            os.getenv('HOME') + '/.ocitysmap.conf']
-
-        LOG.info('Reading configuration from %s...' % ', '.join(config_files))
-        self.parser = ConfigParser.RawConfigParser()
-        if not self.parser.read(config_files):
-            raise IOError, 'Failed to load the config file'
-
-        locale_path = self.parser.get('ocitysmap', 'locale_path')
-        self.i18n = i18n.install_translation(language, locale_path)
-        LOG.info('Rendering language: ' + self.i18n.language_code())
-
-        # Create the map_areas table name string using the provided prefix
-        map_areas_prefix = map_areas_prefix or ''
-        self._map_areas_table_name = '%smap_areas' % map_areas_prefix
-
-        self.SELECTED_AMENITIES = [
-            (_(u"Places of worship"), "place_of_worship", _(u"Place of 
worship")),
-            (_(u"Education"), "kindergarten", _(u"Kindergarten")),
-            (_(u"Education"), "school", _(u"School")),
-            (_(u"Education"), "college", _(u"College")),
-            (_(u"Education"), "university", _(u"University")),
-            (_(u"Education"), "library", _(u"Library")),
-            (_(u"Public buildings"), "townhall", _(u"Town hall")),
-            (_(u"Public buildings"), "post_office", _(u"Post office")),
-            (_(u"Public buildings"), "public_building", _(u"Public building")),
-            (_(u"Public buildings"), "police", _(u"Police"))]
-
-        datasource = dict(self.parser.items('datasource'))
-
-        LOG.info('Connecting to database %s at %s (user: %s)...' %
-                 (datasource['dbname'], datasource['host'], 
datasource['user']))
-        db = psycopg2.connect(user=datasource['user'],
-                              password=datasource['password'],
-                              host=datasource['host'],
-                              database=datasource['dbname'])
-
-        # Force everything to be unicode-encoded, in case we run along
-        # django (which loads the unicode extensions for psycopg2)
-        db.set_client_encoding('utf8')
-
-        # Set session timeout parameter (18mn)
-        cursor = db.cursor()
-        cursor.execute("show statement_timeout;")
-        LOG.debug("Initial statement timeout: %s" % cursor.fetchall()[0][0])
-        cursor.execute("set session statement_timeout=%d;"
-                       % (STATEMENT_TIMEOUT_MINUTES*60*1000))
-        cursor.execute("show statement_timeout;")
-        LOG.debug("Configured statement timeout: %s" % cursor.fetchall()[0][0])
-        del cursor
-
-        if self.city_name:
-            self.boundingbox = self.find_bounding_box_by_name(db, 
self.city_name)
-        elif self.osmid:
-            self.boundingbox = self.find_bounding_box_by_osmid(db, self.osmid)
-
-        self.griddesc = grid.GridDescriptor(self.boundingbox, db)
-
-        try:
-            self._gen_map_areas(db)
-
-            self.contour = None
-            self.polygon = None
-
-            if self.city_name:
-                self.contour, self.polygon = \
-                        self.get_city_contour_by_name(db, self.city_name)
-            elif self.osmid:
-                self.contour, self.polygon = \
-                        self.get_city_contour_by_osmid(db, self.osmid)
-
-            self.streets = self.get_streets(db, self.polygon)
-            self.amenities = self.get_amenities(db, self.polygon)
-        finally:
-            LOG.debug('Restoring database state...')
-            db.rollback()
-            self._del_map_areas(db)
-
-        LOG.info('City bounding box is %s.' % str(self.boundingbox))
-
-
-    def find_bounding_box_by_name(self, db, name):
-        """Find the bounding box of a city from its name.
-
-        Args:
-            db: connection to the database
-            name (string): The city name.
-        Returns a BoundingBox object describing the bounding box around
-        the given city.
-        """
-
-        LOG.info("Looking for rendering bounding box around %s..." % name)
-
-        cursor = db.cursor()
-        cursor.execute("""select osm_id, 
st_astext(st_transform(st_envelope(way), 4002))
-                          from planet_osm_line
-                          where boundary='administrative' and
-                                admin_level='8' and
-                                name=%s;""" % \
-                           sql_escape_unicode(name))
-        records = cursor.fetchall()
-        if not records:
-            raise UnsufficientDataError, "Wrong city name (%s) or missing 
administrative boundary in database!" % repr(name)
-
-        osm_id, wkt = records[0]
-        LOG.info("Found matching OSMID %s with bounding box %s." % (osm_id, 
wkt))
-        return BoundingBox.parse_wkt(wkt)
-
-    def find_bounding_box_by_osmid(self, db, osmid):
-        """Find the bounding box of a city from its OSM id.
-
-        Args:
-            db: connection to the database
-            osmid (integer): The city OSM id.
-        Returns a BoundingBox object describing the bounding box around
-        the given city.
-        """
-
-        LOG.info('Looking for rendering bounding box around OSMID %s...' % 
osmid)
-
-        cursor = db.cursor()
-        cursor.execute("""select st_astext(st_transform(st_envelope(way), 
4002))
-                          from planet_osm_polygon
-                          where osm_id=%d;""" % \
-                           osmid)
-        records = cursor.fetchall()
-        if not records:
-            raise UnsufficientDataError, "OSMID %s not found in the database!" 
% repr(osmid)
-
-        LOG.info("Found bounding box: %s" % records[0][0])
-        return BoundingBox.parse_wkt(records[0][0])
-
-    _regexp_contour = re.compile('^POLYGON\(\(([^)]*)\)\)$')
-    _regexp_coords  = re.compile('^(\S*)\s+(\S*)$')
-
-    def parse_city_contour(self, data):
-        try:
-            contour = data[0][0].strip()
-            polygon = data[0][1].strip()
-        except (KeyError,IndexError,AttributeError):
-            LOG.error("Invalid DB row structure")
-            return None
-
-        # Got nothing usable
-        if not contour or not polygon:
-            return None
-
-        # Parse the answer, in order to add a margin around the area
-        prev_locale = locale.getlocale(locale.LC_ALL)
-        locale.setlocale(locale.LC_ALL, "C")
-        try:
-            matches = self._regexp_contour.match(contour)
-            if not matches:
-                LOG.error("Area not conformant")
-                return None
-            bbox_coords = matches.groups()[0].split(',')
-
-            # Determine bbox envelope
-            if len(bbox_coords) != 5:
-                LOG.error("Coords look atypical: %s", bbox_coords)
-                return None
-
-            # Find the four corners
-            xmin, xmax, ymin, ymax = (None,)*4
-            for point in bbox_coords:
-                matches = self._regexp_coords.match(point)
-                y,x = map(float,matches.groups())
-                if (xmax is None) or xmax < x: xmax = x
-                if (xmin is None) or xmin > x: xmin = x
-                if (ymax is None) or ymax < y: ymax = y
-                if (ymin is None) or ymin > y: ymin = y
-
-            # Add one degree around the area
-            xmin -= 1. ; xmax += 1.
-            ymin -= 1. ; ymax += 1.
-
-            matches = self._regexp_contour.match(polygon)
-            if not matches:
-                LOG.error("Administrative boundary looks invalid")
-                return None
-            inside = matches.groups()[0]
-
-            l = "MULTIPOLYGON(((%f %f, %f %f, %f %f, %f %f, %f %f)),((%s)))" \
-                % (ymin, xmin, ymin, xmax, ymax, xmax, ymax, xmin, ymin, xmin,
-                  inside)
-            return (l, polygon)
-        except:
-            # Regexp error: area is not a "simple" polygon
-            LOG.exception("Unexpected exception")
-            return None
-        finally:
-            locale.setlocale(locale.LC_ALL, prev_locale)
-
-    def get_city_contour_by_name(self, db, city):
-        assert city is not None
-        LOG.info('Looking for contour around %s...' % repr(city))
-        cursor = db.cursor()
-        cursor.execute("""select st_astext(st_transform(st_envelope(way), 
4002))
-                                   as contour,
-                                 st_astext(st_transform(st_buildarea(way), 
4002))
-                                   as polygon
-                              from planet_osm_line
-                              where boundary='administrative'
-                                 and admin_level='8' and name=%s;""" % \
-                               sql_escape_unicode(city))
-        data = cursor.fetchall()
-        LOG.debug('Got contour.')
-        return self.parse_city_contour(data)
-
-    def get_city_contour_by_osmid(self, db, osmid):
-        LOG.info('Looking for contour around OSMID %s...' % repr(osmid))
-        cursor = db.cursor()
-        cursor.execute("""select st_astext(st_transform(st_envelope(way), 
4002))
-                                   as contour,
-                                 st_astext(st_transform(st_buildarea(way), 
4002))
-                                   as polygon
-                              from planet_osm_polygon
-                              where osm_id=%d;""" % \
-                           osmid)
-        data = cursor.fetchall()
-        LOG.debug('Got contour.')
-        return self.parse_city_contour(data)
-
-    # This function creates a map_areas table that contains the list
-    # of the squares used to divide the global city map. Each entry of
-    # this table represent one of these square, with x, y being the
-    # square identifiers, and geom being its geographical
-    # geometry. This temporary table allows to conveniently perform a
-    # joint with the planet_osm_line or planet_osm_polygon tables, so
-    # that getting the list of squares for a given set of streets can
-    # be performed in a single query
-    def _gen_map_areas(self, db):
-        cursor = db.cursor()
-        LOG.info("Generating map grid in table %s..."
-                 % self._map_areas_table_name)
-
-        # Make sure our map_areas table does not exist already. We don't call
-        # _del_map_areas here because we want this to be part of the local
-        # DB transaction.
-        LOG.debug('drop %s...' % self._map_areas_table_name)
-        cursor.execute("drop table if exists %s" % self._map_areas_table_name)
-
-        LOG.debug('create table %s...' % self._map_areas_table_name)
-        cursor.execute("create table %s (x integer, y integer)"
-                       % self._map_areas_table_name)
-        LOG.debug('addgeometrycolumn...')
-        cursor.execute("select addgeometrycolumn('%s', 'geom', 4002, 
'POLYGON', 2)" % self._map_areas_table_name)
-        for i in xrange(0, int(math.ceil(self.griddesc.width_square_count))):
-            for j in xrange(0, 
int(math.ceil(self.griddesc.height_square_count))):
-                LOG.debug('add square %d,%d...' % (i,j))
-                lon1 = (self.boundingbox.get_top_left()[1] +
-                        i * self.griddesc.width_square_angle)
-                lon2 = (self.boundingbox.get_top_left()[1] +
-                        (i + 1) * self.griddesc.width_square_angle)
-                lat1 = (self.boundingbox.get_top_left()[0] -
-                        j * self.griddesc.height_square_angle)
-                lat2 = (self.boundingbox.get_top_left()[0] -
-                        (j + 1) * self.griddesc.height_square_angle)
-                poly = ("POLYGON((%f %f, %f %f, %f %f, %f %f, %f %f))" %
-                        (lon1, lat1, lon1, lat2, lon2,
-                         lat2, lon2, lat1, lon1, lat1))
-                cursor.execute("""insert into %s (x, y, geom)
-                                  values (%d, %d, st_geomfromtext('%s', 
4002))""" %
-                               (self._map_areas_table_name, i, j, poly))
-
-        LOG.debug('Commit gen_map_areas...')
-        db.commit()
-        LOG.debug('Done with gen_map_areas for %s.'
-                  % self._map_areas_table_name)
-
-    def _del_map_areas(self, db):
-        """Destroys the map_areas table used by this OCitySMap instance
-        (parametrized by its prefix)."""
-
-        cursor = db.cursor()
-        LOG.debug('drop %s...' % self._map_areas_table_name)
-        cursor.execute("drop table if exists %s" % self._map_areas_table_name)
-        db.commit()
-
-    # Given a list of street and their corresponding squares, do some
-    # cleanup and pass it through the internationalization layer to
-    # get proper sorting, filtering of common prefixes, etc. Returns a
-    # updated street list.
-    def humanize_street_list(self, sl):
-        # We transform the string representing the squares list into a
-        # Python list
-        sl = [( street[0],
-                [ map(int, x.split(',')) for x in street[1].split(';')[:-1] ] )
-              for street in sl]
-
-        # Street prefixes are postfixed, a human readable label is
-        # built to represent the list of squares, and the list is
-        # alphabetically-sorted.
-        prev_locale = locale.getlocale(locale.LC_COLLATE)
-        locale.setlocale(locale.LC_COLLATE, self.i18n.language_code())
-
-        def _humanize_street_label(street):
-            return (self.i18n.user_readable_street(street[0]),
-                    _user_readable_label(street[1]))
-
-        try:
-            sl = sorted(map(_humanize_street_label, sl),
-                        lambda x, y: locale.strcoll(x[0].lower(), 
y[0].lower()))
-        finally:
-            locale.setlocale(locale.LC_COLLATE, prev_locale)
-
-        # Add the first letter of the street name as category
-        sl = [(street[0][0], street[0], street[1]) for street in sl]
-
-        return sl
-
-    def get_streets(self, db, contour=None):
-        """Get the list of streets in the administrative area if city is
-        defined or in the bounding box otherwise, and for each
-        street, the list of squares that it intersects.
-
-        Returns a list of the form [(street_name, 'A-B1'),
-                                    (street2_name, 'B3')]
-        """
-
-        cursor = db.cursor()
-        LOG.info("Getting streets...")
-
-        # The inner select query creates the list of (street, square)
-        # for all the squares in the temporary map_areas table. The
-        # left_join + the test on cities_area is used to filter out
-        # the streets outside the city administrative boundaries. The
-        # outer select builds an easy to parse list of the squares for
-        # each street.
-        #
-        # A typical result entry is:
-        #  [ "Rue du Moulin", "0,1;1,2;1,3" ]
-        #
-        # REMARKS:
-        #
-        #  * The cities_area view is created once for all at
-        #    installation. It associates the name of a city with the
-        #    area covering it. As of today, only parts of the french
-        #    cities have these administrative boundaries available in
-        #    OSM. When available, this boundary is used to filter out
-        #    the streets that are not inside the selected city but
-        #    still in the bounding box rendered on the map. So these
-        #    streets will be shown but not listed in the street index.
-        #
-        #  * The textcat_all() aggregate must also be installed in the
-        #    database
-        #
-        # See ocitysmap-init.sql for details
-
-        intersect = 'true'
-        if contour:
-            intersect = """st_intersects(way, st_transform(
-                                GeomFromText('%s', 4002), 900913))""" % contour
-
-        cursor.execute("""select name, textcat_all(x || ',' || y || ';')
-                          from (select distinct name, x, y
-                                from planet_osm_line
-                                join %s
-                                on st_intersects(way, st_transform(geom, 
900913))
-                                where trim(name) != '' and highway is not null
-                                and %s)
-                          as foo
-                          group by name
-                          order by name;""" % \
-                           (self._map_areas_table_name,
-                            intersect))
-
-        sl = cursor.fetchall()
-        LOG.debug("Got streets (%d)." % len(sl))
-        return self.humanize_street_list(sl)
-
-    # Given a list of amenities and their corresponding squares, do some
-    # cleanup and pass it through the internationalization layer to
-    # get proper sorting, filtering of common prefixes, etc. Returns a
-    # updated amenity list.
-    def humanize_amenity_list(self, am):
-        # We transform the string representing the squares list into a
-        # Python list
-        am = [( amenity[0], amenity[1],
-                [ map(int, x.split(',')) for x in amenity[2].split(';')[:-1] ] 
)
-              for amenity in am]
-
-        # Street prefixes are postfixed and a human readable label is
-        # built to represent the list of squares.
-        def _humanize_amenity_label(amenity):
-            return (amenity[0], amenity[1],
-                    _user_readable_label(amenity[2]))
-
-        am = map(_humanize_amenity_label, am)
-
-        return am
-
-    def get_amenities(self, db, contour=None):
-        """Get the list of amenities in the administrative area if city is
-        defined or in the bounding box otherwise, and for each
-        amenity, the list of squares that it intersects.
-
-        Returns a list of the form [(category, name, 'A-B1'),
-                                    (category, name, 'B3')]
-        """
-
-        cursor = db.cursor()
-
-        # The inner select query creates the list of (amenity, square)
-        # for all the squares in the temporary map_areas table. The
-        # left_join + the test on cities_area is used to filter out
-        # the amenities outside the city administrative boundaries. The
-        # outer select builds an easy to parse list of the squares for
-        # each amenity.
-        #
-        # A typical result entry is:
-        #  [ "Places of worship", "Basilique Sainte Germaine", "0,1;1,2;1,3" ]
-        #
-        # REMARKS:
-        #
-        #  * The cities_area view is created once for all at
-        #    installation. It associates the name of a city with the
-        #    area covering it. As of today, only parts of the french
-        #    cities have these administrative boundaries available in
-        #    OSM. When available, this boundary is used to filter out
-        #    the streets that are not inside the selected city but
-        #    still in the bounding box rendered on the map. So these
-        #    streets will be shown but not listed in the street index.
-        #
-        #  * The textcat_all() aggregate must also be installed in the
-        #    database
-        #
-        # See ocitysmap-init.sql for details
-        intersect = 'true'
-        if contour:
-            intersect = """st_intersects(way, st_transform(
-                                GeomFromText('%s', 4002), 900913))""" % contour
-
-        al = []
-        for cat, amenity, human in self.SELECTED_AMENITIES:
-            LOG.info("Getting amenities: %s..." % amenity)
-            cursor.execute("""select %(category)s, name, textcat_all(x || ',' 
|| y || ';')
-                              from (select distinct amenity, name, x, y, osm_id
-                                    from planet_osm_point join %(tmp_tblname)s
-                                    on st_intersects(way, st_transform(geom, 
900913))
-                                    where amenity = %(amenity)s and 
%(intersect)s
-                                  union
-                                    select distinct amenity, name, x, y, osm_id
-                                    from planet_osm_polygon join 
%(tmp_tblname)s
-                                    on st_intersects(way, st_transform(geom, 
900913))
-                                    where amenity = %(amenity)s and 
%(intersect)s)
-                              as foo
-                              group by amenity, osm_id, name
-                              order by amenity, name
-                              """ % dict(category=sql_escape_unicode(cat),
-                                         
tmp_tblname=self._map_areas_table_name,
-                                         amenity=sql_escape_unicode(amenity),
-                                         intersect=intersect))
-            sub_al = [(c,a or human,h) for c,a,h in cursor.fetchall()]
-            sub_al = self.humanize_amenity_list(sub_al)
-            LOG.debug("Got amenities: %s (%d)." % (amenity, len(sub_al)))
-            al.extend(sub_al)
-        return al
-
-    def _render_one_prefix(self, title, output_prefix, file_type,
-                           paperwidth, paperheight):
-        file_type   = file_type.lower()
-        frame_width = int(max(paperheight / 20., 30))
-
-        output_filename = "%s_index.%s" % (output_prefix, file_type)
-
-        generator = IndexPageGenerator(self.streets + self.amenities, 
self.i18n)
-
-        if file_type == 'xml':
-            LOG.debug('not rendering index as xml (not supported)')
-            return
-
-        elif file_type == 'csv':
-            try:
-                writer = csv.writer(open(output_filename, 'w'))
-            except Exception,ex:
-                LOG.warning('error while opening destination file %s: %s'
-                          % (output_filename, ex))
-            else:
-                # Try to treat indifferently unicode and str in CSV rows
-                def csv_writerow(row):
-                    _r = []
-                    for e in row:
-                        if type(e) is unicode:
-                            _r.append(e.encode('UTF-8'))
-                        else:
-                            _r.append(e)
-                    return writer.writerow(_r)
-
-                copyright_notice = (u'© %(year)d MapOSMatic/ocitysmap authors. 
'
-                                    u'Map data © %(year)d OpenStreetMap.org '
-                                    u'and contributors (CC-BY-SA)' %
-                                    {'year': datetime.date.today().year})
-                if title is not None:
-                    csv_writerow(['# (UTF-8)', title, copyright_notice])
-                else:
-                    csv_writerow(['# (UTF-8)', '', copyright_notice])
-
-                for entry in self.streets + self.amenities:
-                    csv_writerow(entry)
-            return
-
-        if file_type in ('png', 'png24'):
-            cairo_factory = \
-                lambda w,h: cairo.ImageSurface(cairo.FORMAT_RGB24, w, h)
-
-        elif file_type == 'svg':
-            cairo_factory = lambda w,h: cairo.SVGSurface(output_filename, w, h)
-
-        elif file_type == 'svgz':
-            def cairo_factory(w,h):
-                gz = gzip.GzipFile(output_filename, 'wb')
-                return cairo.SVGSurface(gz, w, h)
-
-        elif file_type == 'pdf':
-            cairo_factory = lambda w,h: cairo.PDFSurface(output_filename, w, h)
-
-        elif file_type == 'ps':
-            cairo_factory = lambda w,h: cairo.PSSurface(output_filename, w, h)
-
-        else:
-            raise ValueError('Unsupported output format: %s' % file_type)
-
-        if title is not None:
-            surface = cairo_factory(paperwidth + frame_width*2,
-                                    paperheight + frame_width*2)
-            enclose_in_frame(lambda ctx: generator.render(ctx, paperwidth,
-                                                          paperheight),
-                             paperwidth, paperheight,
-                             title, surface,
-                             paperwidth + frame_width*2,
-                             paperheight + frame_width*2, frame_width)
-        else:
-            surface = cairo_factory(paperwidth, paperheight)
-            ctx = cairo.Context(surface)
-            generator.render(ctx, paperwidth, paperheight)
-
-        surface.flush()
-
-        if file_type in ('png', 'png24'):
-            surface.write_to_png(output_filename)
-
-        surface.finish()
-
-    def render_index(self, title, output_prefix, output_format,
-                     paperwidth, paperheight):
-
-        if not self.streets:
-            LOG.warning('No street to write to index')
-            return
-
-        for fmt in output_format:
-            LOG.debug('saving %s.%s...' % (output_prefix, fmt))
-            try:
-                self._render_one_prefix(title, output_prefix, fmt,
-                                        paperwidth, paperheight)
-            except:
-                print >>sys.stderr, \
-                    "Error while rendering %s:" % (fmt)
-                traceback.print_exc()
-                # Not fatal !
-
-
-    def render_map_into_files(self, title,
-                              out_prefix, out_formats,
-                              zoom_factor):
-        """
-        Render the current boundingbox into the destination files.
-        @param title (string/None) title of the map, or None: no frame
-        @param out_prefix (string) prefix to use for generated files
-        @param out_formats (iterable of strings) format of image files
-        to generate
-        @param zoom_factor None, a tuple (pixels_x, pixel_y) or
-        'zoom:X' with X an integer [1..18]
-        returns the MApnik map object used to render the map
-        """
-        # Create a temporary dir for the shapefiles and call _render_into_files
-
-        osm_map_file = self.parser.get('mapnik', 'map')
-        if not os.path.exists(osm_map_file):
-            raise IOError, 'Invalid path to the osm.xml file (%s)' % 
osm_map_file
-
-        tmpdir = tempfile.mkdtemp(prefix='ocitysmap')
-        LOG.debug('rendering tmp dir: %s' % tmpdir)
-        try:
-            return self._render_map_into_files(tmpdir, osm_map_file,
-                                               title,
-                                               out_prefix, out_formats,
-                                               zoom_factor)
-        finally:
-            for root, dirs, files in os.walk(tmpdir, topdown=False):
-                for name in files:
-                    os.remove(os.path.join(root, name))
-                for name in dirs:
-                    os.rmdir(os.path.join(root, name))
-            os.rmdir(tmpdir)
-
-    def _render_map_into_files(self, tmpdir,
-                               osm_map_file, title, out_prefix, out_formats,
-                               zoom_factor):
-        # Does the real job of rendering the map
-        GRID_COLOR = '#8BB381'
-        LOG.debug('rendering from %s to %s.%s...' % (osm_map_file,
-                                                   out_prefix,
-                                                   out_formats))
-        bbox = 
self.boundingbox.create_expanded(self.griddesc.height_square_angle*.7,
-                                                
self.griddesc.width_square_angle*.7)
-        LOG.debug('bbox is: %s' % bbox)
-        city = map_canvas.MapCanvas(osm_map_file, bbox, zoom_factor)
-        LOG.debug('adding labels...')
-
-        # Add the greyed-out area
-        if self.contour is not None:
-            path_contour = os.path.join(tmpdir, 'contour.shp')
-            map_canvas.create_shapefile_polygon_from_wkt(path_contour,
-                                                         self.contour)
-            city.add_shapefile(path_contour, str_color = 'grey', alpha = .1)
-
-        # Determine font size, depending on the zoom factor
-        half_km_in_pixels = city.one_meter_in_pixels * 500.
-        LOG.debug('500m = %f pixels' % half_km_in_pixels)
-        if half_km_in_pixels < 10:
-            font_size  = 6
-            line_width = 1
-        elif half_km_in_pixels < 25:
-            font_size = 10
-            line_width = 1
-        elif half_km_in_pixels < 50:
-            font_size = 20
-            line_width = 2
-        elif half_km_in_pixels < 100:
-            font_size = 40
-            line_width = 3
-        elif half_km_in_pixels < 150:
-            font_size = 65
-            line_width = 4
-        elif half_km_in_pixels < 200:
-            font_size = 80
-            line_width = 5
-        elif half_km_in_pixels < 400:
-            font_size = 120
-            line_width = 6
-        else:
-            font_size = 200
-            line_width = 7
-
-        # Add the grid
-        g = self.griddesc.generate_shape_file(os.path.join(tmpdir,
-                                                           'grid.shp'), bbox)
-        city.add_shapefile(g.get_filepath(), GRID_COLOR, .6, line_width)
-
-        # Add the labels
-        for idx, label in enumerate(self.griddesc.vertical_labels):
-            x = self.griddesc.vertical_lines[idx] \
-                + self.griddesc.width_square_angle/2.
-            y = self.griddesc.horizontal_lines[0] \
-                + self.griddesc.height_square_angle*.35
-            city.add_label(x, y, label,
-                           str_color = GRID_COLOR,
-                           alpha = .9,
-                           font_size = font_size,
-                           font_family = "DejaVu Sans Bold")
-        for idx, label in enumerate(self.griddesc.horizontal_labels):
-            x = self.griddesc.vertical_lines[0] \
-                - self.griddesc.width_square_angle*.35
-            y = self.griddesc.horizontal_lines[idx] \
-                - self.griddesc.height_square_angle/2.
-            city.add_label(x, y, label,
-                           str_color = GRID_COLOR,
-                           alpha = .9,
-                           font_size = font_size,
-                           font_family = "DejaVu Sans Bold")
-
-        # Add the scale
-        T = self.griddesc.generate_scale_shape_file(os.path.join(tmpdir,
-                                                                 'scale.shp'),
-                                                    bbox.get_bottom_right()[0])
-        if T is not None:
-            s, lat, lg = T
-            city.add_shapefile(s.get_filepath(), 'black', .9, 1)
-            city.add_label(lg, lat, "500m", font_size = 16, str_color = 
'black')
-
-        # Determine parameters
-        try:
-            copyright_logo = self.parser.get('ocitysmap', 'copyright_logo')
-        except Exception:
-            copyright_logo = None
-
-        # Rendering...
-        LOG.info("Rendering generated map to %s outputs..."
-                 % ', '.join(out_formats))
-        _map = city.render_map()
-        for fmt in out_formats:
-            LOG.debug('saving %s.%s...' % (out_prefix, fmt))
-            try:
-                city.save_map("%s.%s" % (out_prefix, fmt),
-                              title,
-                              file_type = fmt,
-                              copyright_logo_png = copyright_logo)
-            except:
-                print >>sys.stderr, \
-                    "Error while rendering %s:" % (fmt)
-                traceback.print_exc()
-                # Not fatal !
-
-        return _map
diff --git a/ocitysmap/utils.py b/ocitysmap/utils.py
deleted file mode 100644
index 637e4bc..0000000
--- a/ocitysmap/utils.py
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*- coding: utf-8 -*-
-
-# ocitysmap, city map and street index generator from OpenStreetMap data
-# Copyright (C) 2009  David Decotigny
-# Copyright (C) 2009  Frédéric Lehobey
-# Copyright (C) 2009  David Mentré
-# Copyright (C) 2009  Maxime Petazzoni
-# Copyright (C) 2009  Thomas Petazzoni
-# Copyright (C) 2009  Gaël Utard
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of the
-# License, or any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU Affero General Public License for more details.
-
-# You should have received a copy of the GNU Affero General Public License
-# along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
-
-def gen_vertical_square_label(x):
-    label = ''
-    while x != -1:
-        label = chr(ord('A') + x % 26) + label
-        x /= 26
-        x -= 1
-    return label
-
-def gen_horizontal_square_label(x):
-    return str(x + 1)
-- 
1.7.4.1




reply via email to

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