Soy nuevo en el fascinante mundo SIG, y he estado investigando todo el tema durante los últimos días. Mi objetivo es servir mapas de todo el planeta con datos OSM en mis propios servidores.
Mi pila es:
- Postgres + Postgis : para almacenar, transformar y procesar datos SIG.
- Mapnik - Biblioteca para renderizar mosaicos
- Tilestache - Servir y almacenar caché
- Nginx : proxy inverso a Tilestache
- Folleto ( cliente de mapa Slippy )
Para importar y diseñar datos OSM, estoy usando
- Archivo PBF (Extracto / Planeta)
- osm2pgsql
- CartoCSS
- openstreetmap-carto
- Kosmtik - Mapa GUI para desarrollo / depuración
Como el archivo del planeta completo es enorme, actualmente estoy usando un extracto de Sao Paulo , que es lo suficientemente bueno / pequeño para realizar pruebas.
Antes de llegar al problema que tengo, lo guiaré a través de los pasos que tomé hasta ahora:
Lo que funcionó
PostgreSQL y PostGIS están instalados correctamente. Estoy usando 9.6 para el primero, 2.3 para el segundo. También he agregado las extensiones postgis_topology
y hstore
, que se usarán más adelante.
Tengo instalado osm2pgsql 0.92.0. Para importar el extracto de Sao Paulo, utilizo
osm2pgsql -G U <user> -d <db> -C 1000 -W --hstore --style openstreetmap-carto.style --tag-transform-script openstreetmap-carto.lua <pbf>
Los hstore
, style
y tag-transform-script
se necesitan argumentos para la utilización adecuada del estilo de la OSM, tal como se describe aquí .
Como se describe en la instalación de openstreetmap-carto, también agregué índices personalizados y descargué los shapefiles y fuentes necesarios (excepto los emoji).
Verifiqué que los datos de extracción están cargados correctamente en la base de datos usando QGIS. Pude ver y consultar todos los puntos, polígonos, líneas y carreteras. Todo esta ahí.
Problemas
El siguiente paso es renderizar los mosaicos, y ahí es donde tengo problemas. Tengo mapnik y python-mapnik 3.x, así como carto 0.18.2.
Desde project.mml de OSM , he generado mi propio project.xml usando carto
. He realizado los siguientes cambios en el resultado:
- Agregue el nombre de usuario de Postgres (parámetro
user
en el XML de Mapnik ). La información de conexión restante se toma de ~ / .pgpass . - Reemplazar directorio relativo
data/<shape>.shp
a/full/path/data/<shape>.shp
- Reemplazar directorio relativo
symbols/<symbol>.svg
a/full/path/symbols/<symbol>.svg
Realicé una prueba unitaria de estos cambios: los directorios incorrectos para archivos de forma y símbolos generarán un error cuando Mapnik intente cargar el estilo. Lo mismo se aplica para la información incorrecta de la base de datos.
Y aquí está el problema: cada mosaico representado por Mapnik está "en blanco" (fondo azul-ish, que es el fondo definido para OSM). Esto es lo que he tratado de solucionar este problema:
Cosas que he probado
Tal vez el estilo generado no sea válido de alguna manera. Tal vez algún polígono / forma (¿el océano?) Está cubriendo otro.
He instalado Kosmtik, ¡y funcionó bien! Pude navegar a través del extracto, inspeccionar datos, acercar y alejar en todos los niveles.
Tal vez estoy generando mosaicos en la ubicación incorrecta
He configurado TileStache con Mapnik como proveedor. Luego, configuré reglas de redireccionamiento http://[abc].tile.openstreetmap.org
para http://myserver/<layer>
usar Switcheroo, como se describe aquí . Esto significa que el acceso openstreetmaps.org
tendría todos los mosaicos representados en mi servidor.
Curiosamente, el zoom 1 funciona (el que tiene 4 mosaicos). Supongo que solo usa el archivo de forma planeta / mundo, que se descargó con el estilo. Todo lo demás, independientemente del zoom o la ubicación, se muestra en "blanco". Entonces, incluso cuando navega en la ubicación del extracto, no se representará correctamente.
Tenga en cuenta que, al usar Kosmtik, pude ver el nombre del extracto desde el zoom 4.
Tal vez estoy generando mosaicos en la ubicación incorrecta
Las proyecciones son difíciles. Tal vez hay algo "mal traducido" en alguna parte.
Así que he analizado las solicitudes Kosmtik estaba haciendo (ya que éstas estaban trabajando). Utiliza la biblioteca Modestmaps, que se traduce al formato Slippy ( <zoom>/<x>/<y>
), el mismo formato utilizado por Leaflet, TileStache y openstreetmap.org
.
Por ejemplo, solicitar 17/48561/74357.png
en Kosmtik funciona, pero el mismo mosaico regresa como "en blanco" en TileStache. Mi teoría era que de alguna manera TileStache lo estaba traduciendo a otra coordenada, fuera del área de extracción. (A pesar de que TileStache estaba usando "mercator esférico" como la proyección).
Así que he decidido usar los enlaces de Python de Mapnik directamente. Hasta ahora he manejado tres tipos diferentes de proyecciones, esto es lo que sé sobre ellas. Por favor corrígeme si estoy equivocado:
- EPSG4326 / WGS84: proyección habitual de longitud / longitud, igual que la utilizada en el GPS. La unidad es grados.
- EPSG3857 / {Web, Google, Pseudo} mercator / 900913: se utiliza en la mayoría de los mapas web en mosaico. La unidad está en metros (no metros "reales", ya que se distorsiona fuertemente cerca de los polos).
- "Formato resbaladizo": no es una proyección, pero sí otro formato para traducir.
Entonces, el Slippy 17/48561/74357
estaría cerca -46.632(lon), -23.531(lat)
en EPSG4326, y cerca -5191050.49, -2696361.67
en EPSG3875 / Google mercator.
Usando python, he generado los mosaicos de estas coordenadas directamente en Mapnik. El resultado fue siempre mosaicos en blanco. Yo creo que estoy usando las proyecciones correctas (más sobre esto más adelante).
Primero, una cosa a tener en cuenta. Está claro que el problema no está en Mapnik, ni en el estilo. Por un lado, Kosmtik usa Mapnik como backend, y funciona bien. En segundo lugar, si a propósito genero un mosaico fuera del área de extracción en Kostmik, obtengo un mosaico en blanco, como se esperaba.
Esto me lleva a creer que estoy usando la proyección incorrecta en el script de Python de Mapnik y TileStache. Antes de mostrar el código, un comentario sobre OSM (de nuevo, corrígeme si me equivoco):
- Los datos "nativos" de OSM se almacenan en EPSG4326
- osm2pgsql importa datos OSM como EPSG3857, y esa es la proyección en Postgis.
- El estilo de Mapnik (XML) tiene dos proyecciones, entrada y salida, explicadas aquí :
- La proyección de entrada se define en el objeto Mapa y es el "sistema de coordenadas en el que se representa el mapa"
- La proyección de salida se define en el objeto Layer y debe ser igual a mis datos.
El XML resultante de Mapnik tiene:
<Map srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over" background-color="#b5d0d0">
#snip#
<Layer name="world" #snip# srs="+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0.0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs +over">
Entonces, tal como lo veo, las proyecciones de entrada y salida están en "merc" (3857), ¡y eso es correcto! Mis datos se almacenan con 3857, y se espera que el mapa resultante esté en 3857.
Finalmente, aquí están las diferentes llamadas de Mapnik que he probado:
Box2d con 3857 coordenadas:
map = mapnik.Map(800, 800)
bbox = Box2d(-5191050.49, -2696361.67, -5191059.49, -2696370.70)
mapnik.load_map(map, '/path/to/style.xml')
map.zoom_to_box(bbox)
mapnik.render_to_file(map, 'output.png') # Blank
Box2d con 4326 coordenadas transformadas a 3857
merc = mapnik.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 +nadgrids=@null +no_defs +over')
longlat = mapnik.Projection('+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
bbox = mapnik.Box2d(-23.53, -46.63, -24.03, -47.03)
transform = mapnik.ProjTransform(longlat, merc)
merc_bbox = transform.forward(bbox)
# load, zoom, render -> Blank
También lo he intentado con diferentes estilos. El resultado siempre está en blanco, pero eso es inesperado porque creo que estas coordenadas estarían dentro de mi extracto. Al intentar representar coordenadas fuera del extracto, se representa correctamente en blanco.
De todos modos, estoy perdido y me preguntaba si alguien podría arrojar algo de luz, debo estar perdiendo algo. Pero hasta ahora, he estado luchando con este problema durante más de 24 horas y no tengo idea de qué podría estar mal.