OpenStreetMap y Mapnik

Objetivo:
Siguiendo con la serie de artículos sobre OSM vamos a introducirnos en las posibilidades que nos ofrece Mapnik para renderizar datos de OSM contenidos en una geodatabase que hemos creado con “osm2pgsql” (ver artículo previo).
El objetivo final es crear un fichero de mapa (mapfile) en XML para utilizarlo con Python y los bindings de Mapnik. Una vez realizado este proceso podremos generar tanto imágenes como conjuntos de teselas (tiles)

Descarga de utilidades OSM para Mapnik
En el repositorio subversion de OSM tenemos todo lo necesario para montar nuestro propio motor de renderizado de imágenes y conjuntos de tiles.
Para descargar estas utilidades nos situamos en la raíz de nuestro “home” y procedemos a la descarga:

svn co http://svn.openstreetmap.org/applications/rendering/mapnik/ mapnik
cd mapnik

Este es el contenido de la carpeta “mapnik”:

  • symbols: carpeta con los iconos utilizados “oficialmente” en el “slippy map” de www.openstreetmap.org
  • osm_template.xml:  plantilla por defecto para generar un mapfile de OSM
  • set_mapnik.env:  script de configuración de directorios, datasources, etc.
  • generate_image.py:  script para generar una imagen
  • generate_tiles.py:  script para generar tiles
  • otros archivos

Descarga de shapefiles:

OSM necesita una serie de shapefiles para poder renderizar aspectos como la costa, paises, masas de agua, etc.
Lo ideal es que dentro del directorio “mapnik” creemos una carpeta donde almacenarlos

mkdir world_boundaries

Ahora descargamos los shapefiles y los descomprimimos

echo "Tamaño 50 Mb"
wget http://tile.openstreetmap.org/world_boundaries-spherical.tgz
echo "processed_p: Tamaño 227 Mb"
wget http://tile.openstreetmap.org/processed_p.tar.bz2
echo "shoreline_300: Tamaño 46 Mb"
$ wget http://tile.openstreetmap.org/shoreline_300.tar.bz2
cd world_boundaries
echo "Descomprimir"
tar -xvzf world_boundaries-spherical.tgz
tar jxvf processed_p.tar.bz2
tar jxvf shoreline_300.tar.bz2

De todas las shapes de estos archivos nos interesan fundamentalmente tres:

  • shoreline_300 : polígonos con los contienentes y en cuadrículas, utilizado para el renderizado de la costa. El detalle es muy tosco, por lo que se utiliza para escalas superiores a 1/600.000
  • processed_p:  polígonos con los contienentes y en cuadrículas, utilizado para el renderizado de la costa. Tienen gran detalle, por lo que se utiliza para escalas inferiores a 1/600.000
  • builtup_area:  polígonos con masas de agua continentales (lagos)

Configuración de Mapnik para OSM

El siguiente paso es configurar el fichero “set_mapnik.env” donde especificaremos las rutas a las carpetas de símbolos, shapefiles y conexiones a PostGIS.
Este fichero será utilizado por la plantilla de OSM (“osm_template.xml”) para sustituir las variables contenidas entre “%”, como por ejemplo “%HOST%”, por nuestros valores personalizados.

Contenido del fichero “set_mapnik.env”

#!/bin/sh
# Nombre del mapfile
export MAPNIK_MAP_FILE=/home/<usuario>/mapnik/osm.xml

# carpeta de símbolos
export MAPNIK_SYMBOLS_DIR=/home/<usuario>/mapnik/symbols

# carpeta de shapefiles
export MAPNIK_WORLD_BOUNDARIES_DIR=/home/<usuario>/mapnik/world_boundaries

# Carpeta donde se generarán las tiles
export MAPNIK_TILE_DIR=/home/<usuario>/mapnik/tiles/

# Host de PostgreSQL
export MAPNIK_DBHOST='localhost';

# Puerto de PostgreSQL
export MAPNIK_DBPORT=''

# Nombre de la base de datos del planet OSM
export MAPNIK_DBNAME='osm'

# Nombre del usuario de Postgres con derechos sobre la base de datos OSM
export MAPNIK_DBUSER='postgres'

# Password del usuario de PostgreSQL
export MAPNIK_DBPASS='';

# Prefijo utilizado en las tablas. Este prefijo es generado si se utiliza
# el parámetro "-p <nombre>" en la utilidad "osm2pgsql". Si no lo utilizamos
# se entiende que será "planet_";
export MAPNIK_PREFIX=''
$*
#-----------------------------------------------------------------------------

NOTA: En el script sustituye “” por tu nombre de usuario.

Configuración de la plantilla de OSM

Como ya hemos indicado, entre los ficheros proporcionados en la carpeta “mapnik”, tenemos uno muy especial, “osm_template.xml”. Como habeis deducido se trata de la plantilla que utiliza Mapnik para generar el mapfile (“osm.xml”). Sí no tocamos nada de este archivo obtendremos un renderizado de imágenes o tiles igual que el utilizado por el “slippy map” de www.openstreetmap.org. Es aquí, por tanto, donde debemos de agudizar nuestro ingenio para establecer una simbología acorde con nuestros intereses: cambiar colores, retocar las SQL de las layers, añadir o cambiar iconos, etc.

En lo referente a este artículo, sólo vamos a realizar pequeños cambios.

1. Vamos a resaltar las paradas del tranvía para que aparezca el logotipo “oficial” por el que se conoce en Alicante a este medio de transporte (TRAM)

En el documento cambiamos este texto:

     <Rule>
      <MaxScaleDenominator>100000</MaxScaleDenominator>
      <MinScaleDenominator>25000</MinScaleDenominator>
      <Filter>[railway]='station' and not [disused]='yes'</Filter>
      <PointSymbolizer file =  "%SYMBOLS_DIR%/station_small.png" type="png" width="6" height="6" />
    </Rule>

Por este otro

    <Rule>
      <MaxScaleDenominator>100000</MaxScaleDenominator>
      <MinScaleDenominator>25000</MinScaleDenominator>
      <Filter>[railway]='station' and not [disused]='yes'</Filter>
      <PointSymbolizer file =  "%SYMBOLS_DIR%/tram2.png" type="png" width="20" height="20" />
    </Rule>

2. Por otra parte vamos a cambiar el color de fondo para las áreas residenciales
Color: ♦♦♦♦♦

    <Rule>
      <MaxScaleDenominator>1000000</MaxScaleDenominator>
      <MinScaleDenominator>1000</MinScaleDenominator>
      <Filter>[landuse] = 'residential'</Filter>
      <PolygonSymbolizer>
        <CssParameter name="fill">#F6CEE3</CssParameter>
      </PolygonSymbolizer>
    </Rule>

Crear imágenes

Una vez configurado nuestro mapfile (“osm.xml”) pasamos a generar imágenes utilizando el script “generate_image.py”. Te recomendamos que hagas una copia de ese archivo para no trabajar con el original. Con un editor de textos tienes que modificar los siguientes parámetros:

#!/bin/sh
# ... resto de código
    mapfile = "osm.xml"
    map_uri = "image.png"

    #---------------------------------------------------
    #  Change this to the bounding box you want
    #
    # Área metropolitana de Alicante
    ll = (-0.5534, 38.3245, -0.4267, 38.4071)
    #---------------------------------------------------
    z = 18
    imgx = 50 * z
    imgy = 50 * z
# ... resto de código

Cómo ves sólo es necesario modificar tres aspectos:

  1. Extensión de la imagen en grados decimales: xmin,ymin,xmax,ymax
  2. Nivel de zoom: del 1 (mundo) al 18 (máximo de detalle)
  3. Dimensiones de la imagen en píxeles

NOTA:

Para evitar resultados desagradables intenta ajustar el BBOX y las dimensiones de la imagen.

Por último debemos de realizar los siguientes pasos para generar la imagen

1. Leer las variables que hemos definido en “set_mapnik.env”

source set-mapnik-env

2.  Utilizar la plantilla “osm-template.xml” para generar el fichero “oxm.xml”

./customize-mapnik-map >$MAPNIK_MAP_FILE

3. Lanzar el script:

python mi_genera_imagen.py

Este es el resultado:

Zoom 14

Zoom 18 (fíjate en el renderizado de las estaciones del TRAM)

Crear las tiles

Esta es la parte de Mapnik que tiene más interés para nosotros, puesto que nos permitirá generar nuestro propio TMS para ser utilizado con independencia del “Slippy map” de OpenStreetMap.

1. Creamos el directorio donde se guardarán las tiles creadas:

mkdir -p $MAPNIK_TILE_DIR

2. Editamos el fichero “generate_tiles.py” para definir las zonas a renderizar

#!/usr/bin/python
# resto de código
# directorio donde se almacenan las imágenes
        tile_dir = home + "/osm/tiles/"

    #-------------------------------------------------------------------------
    #
    # Change the following for different bounding boxes and zoom levels
    #
    # Start with an overview
    # World
    bbox = (-180.0,-90.0, 180.0,90.0)

    render_tiles(bbox, mapfile, tile_dir, 0, 5, "World")

    # Europa
    minZoom = 6
    maxZoom = 8
    bbox = (1.0,10.0, 20.6,50.0)
    render_tiles(bbox, mapfile, tile_dir, minZoom, maxZoom)

    # Provincia de Alicante
    bbox = (-1.498,37.622,0.529,38.946)
    render_tiles(bbox, mapfile, tile_dir, 9, 11 , "Europe+")

    # Área metropolitana de la ciudad de Alicante
    bbox = (-0.6171,38.295,-0.3637,38.4602)
    render_tiles(bbox, mapfile, tile_dir, 12, 18 , "Alicante")

Cómo habrás podido deducir vamos a generar tiles en cuatro intervalos de escala:

  • Escalas pequeñas: Zoom del 1 al 5
  • Escalas medias: 6 al 8
  • Escalas grandes (más detalles): 9 al 11
  • Escalas de máximo detalle): 12 al 18

3. Ejecutamos el script

python ./mi_genera_tiles.py

4. Comprobación:
Fíjate que en la carpeta “tiles” tendremos una carpeta por cada nivel de zoom. En los niveles superiores es donde habrán más imágenes (las de mayor detalle)

ls tiles

Por fin, ya hemos creado nuestro directorio de tiles listo para ser utilizado por OpenLayers como un TMS.

Esto es todo. Espero que os haya gustado. Comentarios y críticas serán bien recibidas

Este artículo es el segundo de una serie formada por:

  • Renderizado con Mapnik
  • Mapnik y OpenStreetMap (este post)
  • Thumbnails con Mapnik y OpenStreetMap
  • Uso de TMS de OpenStreetMap con OpenLayers
  • TMS de OpenStreetMap con Mod_tile
  1. Aun no hay comentarios.

  1. 4 noviembre 2009
  2. 26 junio 2010