Thumbnails con Mapnik y OpenStreetMap

¿Alguna vez te has visto en la tesitura de conocer el estado en OpenStreetMap de una determinada provincia, municipio, comunidad autónoma, región etc. en una fecha concreta? Pues bien, en este artículo intentaremos afrontar esta cuestión desde una perspectiva más pedagógica que profesional

Objetivo:
Crear thumbnails (imágenes reducidas) de cada provincia que serán generadas cada semana para ver la evolución histórica de las aportaciones de usuarios a OpenStreetMap. Cada imagen tendrá como nombre la fecha de su creación, y se almacenarán cada una en su carpeta de provincia correspondiente. Estas imágenes serán visibles en un servicio web para su consulta pública.

Fases:

Para llevar a cabo este objetivo precisamos de:

  1. Actualizar cada semana la base de datos con el último “planet osm”
  2. Generar las imágenes de cada provincia (mediante un script en Python)
  3. Colocarlas en el lugar adecuado de nuestro servidor web
  4. Programar la tarea para que se ejecute de forma automática cada semana, sin intervención del usuario.

Figura: Ejemplo del renderizado de una imagen de la provincia de Alicante

Tile de Alicante

Tile de Alicante el 3 de noviembre de 2009

Descripción:
A lo largo de este pequeño artículo mostraremos las posibilidades conjuntas de OSM, PostGIS y Mapnik para que, con muy pocas líneas de código, seamos capaces de generar un repositorio de imágenes de cada provincia (en nuestro caso, aunque se puede adaptar a comunidades autónomas, municipios, etc.) que serán generadas por un script en python programado para ejecutarse una vez a la semana. Dicho script utilizará los módulos de Mapnik para generar imágenes a partir de un mapfile, y PsycoPg para llamar a sentencias SQL de PostgreSQL.

Punto de partida:
Tenemos instalado un servidor con las siguientes aplicaciones instaladas y configuradas:

  • Python
  • PostgreSQL y PostGIS
  • Mapnik y utilidad Mapnik de OSM
  • Una tabla de PostGIS con las provincias
  • Un servidor web para mostrar los resultados

Actualizar la base de datos de OSM cada semana

Para realizar esta fase necesitamos un script que automatice todas las funciones:

  • Borrar la bbdd existente
  • Descarga del planet
  • Creación de la bbdd con PostGIS
  • Carga de datos con osm2pgsql

Script Bash para recargar la base de datos de OSM

#!/bin/sh
echo "Borrando spain.osm.bz2"
rm spain.osm.bz2
echo "Descargando fichero osm de Spain desde Cloudmade.com"
wget http://downloads.cloudmade.com/europe/spain/spain.osm.bz2
echo "Descomprimiendo"
bzip2 -d spain.osm.bz2
echo "Borrando bbdd osm"
dropdb -h localhost -U postgres osm
echo "Creando bbdd osm"
createdb -U postgres -E UTF8 osm
echo "Instalar lenguaje pl/pgsql y Postgis en bbdd osm"
createlang -U postgres plpgsql osm
psql -U postgres -f /usr/share/pgsql/contrib/postgis.sql osm
psql -U postgres -f /usr/share/pgsql/contrib/spatial_ref_sys.sql osm
echo "Añadir datos d espain.osm a la bbdd osm"
echo "Tiempo aproximado: 11 minutos"
/home/<user>/compilar/osm2pgsql/osm2pgsql --slim -H localhost -U postgres -d osm ./spain.osm
echo "fin"
exit 0

Programar tarea con CRONTAB
Como ya sabes, los “crones” son tareas (deaemon) que se programan para ejecutarse en el momento (tiempo) que decidamos. Sí deseas más información aquí tienes un buen enlace: http://dns.bdat.net/documentos/cron/x50.html

Generar el árbol de directorios.
Creamos un script bash para generar las carpetas de cada provincia. Vamos a utilizar el código de cada provincia por cuestión de comodidad

#!/bin/bash
# Crear directorios para provincias.

for provincias in 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
do
  echo $provincias
  mkdir -p $provincias
done

exit 0

Este sencillo script, que seguro podrás mejorar, debemos de ejecutarlo en el directorio de nuestro website donde se alojarán el servicio para ver la evolución de OSM

Generar imágenes de OSM por provincia
Este script en Python hace uso de los módulos de Mapnik para generar la imagen, y de Psycopg para ejecutar sentencias SQL. Fíjate que la clave consiste en calcular por cada provincia las columnas con los valores de la extensión (xmin, ymin, xmax, ymax). Opcionalmente puedes añadirle una tolerancia para que el límite no se circunscriba a la caja de la provincia, sino que sea como una especie de buffer.
En nuestro caso, la tabla “provincias” está en la proyección UTM-ED50 del uso 30 (epsg: 23030), por lo que para utilizarlo con los datos de OSM necesitamos proyectar los valores de la extensión a Mercator (EPSG: 900913)

NOTA: Si no tienes instalago psycopg (o psycopg2 según la distro) lo puedes instalar con

yum install python-psycopg2.x86_64

Script de Python

#!/usr/bin/env python
## DNS de la bbdd que contiene las provincias
DSN = 'host=localhost user=postgres dbname=demos'

import sys, psycopg, mapnik
## Nota: Si obtienes algun error aqui, cambia psycopg por psycopg2
from datetime import date

## mapnik
mapfile = 'osm.xml'
## tamaño de la imagen
m = mapnik.Map(400, 400)

if len(sys.argv) > 1:
    DSN = sys.argv[1]

print 'Abrir conexion usando dns', DSN
conn = psycopg.connect(DSN)
## Nota: Si obtienes algun error aqui, cambia psycopg por psycopg2
curs = conn.cursor()

curs.execute('select codigo, st_xmin(st_extent(st_transform(geometria,900913))) as xmin, st_ymin(st_extent(st_transform(geometria,900913))) as ymin, st_xmax(st_extent(st_transform(geometria,900913))) as xmax, st_ymax(st_extent(st_transform(geometria,900913))) as ymax from ine.provincias group by codigo')

row = curs.fetchone()

rows = curs.fetchall()
print 'Creando imagenes...';
for row in rows:
    now = date.today()
    ## A cada imagen le asignamos como nombre la fecha de creación de la imagen
    map_output = 'miniaturas/'+row[0]+'/'+now.strftime("%Y-%m-%d&")+'.png'
    mapnik.load_map(m, mapfile)
    bbox = mapnik.Envelope(mapnik.Coord(row[1],row[2]), mapnik.Coord(row[3],row[4]))
    m.zoom_to_box(bbox)
    mapnik.render_to_file(m, map_output)

conn.commit()

Ejecutamos el script

python miniatura_provincias.py

Por último sólo nos queda hacer visible a nuestro servidor web las tiles. Para ello tenemos dos opciones:

a) Copiamos el directorio miniaturas a nuestra carpeta de publicación web

cp /home/mapnik/miniaturas /var/www/<tu_ruta>/

b) Crear un enlace rígido en nuestra web que apunte al directorio “miniaturas”

ln -d /home/mapnik/miniaturas /var/www/&lt;tu_ruta&gt;/miniaturas

Este segundo método es más recomendable, puesto que nos permite aislar la lógica de nuestra aplicación del servicio web.

Test
Probamos el ejemplo
http://www.gisandchips.org/demos/j3m/miniaturas/

Automatización:

Sí queremos automatizar estas tareas, de forma que cada semana obtengamos una nueva imagen, cuyo nombre de imagen es la fecha en que se lanza el cron, debemos de lanzar un script que, como root, realice estos pasos. A modo de ejemplo, este sería el Bash:

#!/bin/sh
cd <ruta_directorio_volcado_bbdd_osm>
python ./<fichero python para generar miniaturas>
cp /home/mapnik/miniaturas /var/www/<tu_ruta>

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

VN:F [1.7.7_1013]
Rating: 9.6/10 (5 votes cast)
Thumbnails con Mapnik y OpenStreetMap9.6105
  • Share/Bookmark
  1. No comments yet.

  1. November 4th, 2009
  2. November 4th, 2009