Published: 2024-11-10
El desarrollo de muchas aplicaciones involucra ubicar cosas en un mapa. Hoy en dia, pareciera que la única forma de hacerlo es con Google Maps, pero utilizarlo en una aplicación mediana a grande tiene un coste inmenso.
Pensando en eso, y queriendo hacer un mapa con todas las rutas de combi de Arequipa, pense que en vez de pagarle a Google podría utilizar recursos gratis. Y así es como me adentré en el mundo de mapas online.
Este blog contiene imágenes y datos de © OpenStreenMap y sus colaboradores.
Esto es todo lo que utilizo para crear los mapas. En particular Linux. Puede que esta guia funcione en Windows, puede que no.
Existen varias formas de mostrar mapas, pero la más común es utilizando algo llamado “tiles”. Un tile es una imagen de una sección del mapa.
Por ejemplo, a continuación muestro una imagen de un mapa, y despues la misma imagen donde se muestra la división de los tiles.
Cada “cuadrado” es un tile. También existen formas de cómo codificar estos tiles, pero generalmente son imágenes png o jpg.
Si abres la consola de una página con mapas, vas a pestaña Red y mueves el mapa, verás que se hacen peticiones para obtener estos tiles.
Así que se podría decir que un mapa es una cuadrícula de imágenes.
Como dato adicional, cada tile es una imagen png por lo general, y un mapa tiene miles de millones de tiles. Cada imagen png pesa alrededor de 100KiB, así que almacenar todas esas imágenes y servirlas tiene un costo. Costo de almacenamiento y costo de ancho de banda.
También, los mapas tienen varios niveles de zoom:
Estos niveles van del 0 al 22. El nivel 0 es un único tile que muestra todo el planeta:
El nivel 1 duplica sus dimensiones, así que consta de 4 tiles:
Y así sucesivamente, hasta el nivel 22. En teoría se puede renderizar muchos más niveles (23, 24, etc), pero más adelante verás por qué no se hace (spoiler: es costoso).
Cada tile se identifica por 3 números: su nivel (Z), su posición horizontal (Y) y su posición vertical (X). Esto resulta en: Z/Y/X.
Por ejemplo, en zoom 0 el único tile que existe es:
En zoom 1 hay 4 tiles:
Y así sucesivamente. Un último ejemplo: el centro de Arequipa en nivel 15 tiene estos tiles:
Estos tiles se sirven desde un servidor web.
Se sirven con una url: <dominio.com>/<otros>/X/Y/Z.png
.
Por ejemplo, la imágen del centro (15/9871/17896
)
en mi servidor se sirve desde la url: https://combi.araozu.dev/tiles/15/9871/17896.jpg
.
Hasta aquí la teoría sobre los tiles e imágenes.
Los tiles que te mostré son el producto final. Estos tiles se generan
a partir de datos almacenados en archivos .xml
. Estos datos contienen
información acerca de las calles, pistas, parques, distritos, etc etc etc.
Toda la información que se ve en las imágenes está almacenada como texto.
Puedes ir a OpenStreetMap, ver a alguna parte del mundo e inspeccionar cualquier cosa:
Eventualmente encontrarás el código xml de lo que inspecciones. Algo como esto:
<?xml version="1.0" encoding="UTF-8"?>
<osm version="0.6" generator="openstreetmap-cgimap 2.0.1 (2051417 spike-08.openstreetmap.org)" copyright="OpenStreetMap and contributors" attribution="http://www.openstreetmap.org/copyright" license="http://opendatacommons.org/licenses/odbl/1-0/">
<way id="328012181" visible="true" version="3" changeset="119318346" timestamp="2022-04-04T21:06:47Z" user="TuAmigoElEditor" uid="13950332">
<nd ref="3348297717"/>
<nd ref="3348297711"/>
<nd ref="3348297710"/>
<nd ref="3348297707"/>
<nd ref="3348297706"/>
<tag k="landuse" v="cemetery"/>
<tag k="name" v="Cementerio Parque de la Esperanza"/>
<tag k="religion" v="christian"/>
</way>
</osm>
Toda la información del mapa de todo el mundo se almacena de forma similar. Para generar un mapa primero hay que descargar estos archivos xml. Este proceso lo explico más adelante.
El renderizador toma los archivos .xml
y los convierte en imágenes .png
.
Este renderizador es quien define los colores, trazos, fuentes, tamaños
de letra, etc. Se encarga de transformar los datos en algo visual.
Hay formas de personalizar los renderizadores, y se detalla mas adelante.
Una vez renderizados los tiles se sirven mediante un servidor web. Esto puede ser un CDN, un VPS, un servicio de nube, etc.
El proceso de renderizado se puede hacer on-demand: Cada vez que llega una petición de un tile el servidor renderiza en ese momento el tile, y lo devuelve. Como imaginarás, este proceso es costoso.
Si no se necesita generar tiles con la información más reciente, se pueden renderizar todos los tiles de antemano, y servirlos como archivos estáticos.
Finalmente, los clientes son librerías que consumen los tiles que un servidor provee, y se encargan de organizarlos, mostrarlos, permitir arrastrar el mapa, hacer zoom, etc.
El cliente más famoso para la web es Leaflet. Le entregas la URL donde estan los tiles, y se encarga del resto.
OpenStreetMap técnicamente tiene un servidor de tiles que puedes utilizar. Sin embargo, su uso con librerías de terceros como Leaflet no esta permitido. Solo OSM puede usar sus tiles.
Ahora viene lo divertido:
Primero necesitamos saber qué área del planeta tierra necesitamos en nuestro mapa. Técnicamente puedes generar tiles para todo el planeta, pero eso te tardaría muchísimo tiempo y recursos.
En Planet OSM se encuentra un indice de los datos de todo el planeta. Descargar todos los datos del planeta tierra pesa 144GiB.
En Geofabrik.de puedes descargar todo un continente y paises. Por ejemplo, todo sudamerica pesa 3.4GiB, y todo Argentina pesa 352MiB.
En BBBike puedes descargar ciertas áreas o ciudades importantes.
Para descargar un área en específico ve a Protomaps y selecciona el área que quieres descargar. Yo descargaré Arica, Chile para el tutorial.
Otra herramienta útil para obtener un área en coordenadas es Tile Calculator.
Tras presionar “Create Extract” se empezará a procesar la solicitud:
Una vez termine, descarga el mapa con el boton “Download .OSM.PBF”:
Dependiendo del área que descargaste este archivo pesará entre 1-10 MiB.
Ahora tienes un archivo .osm.pbf
. Este archivo contiene toda la información de (en mi caso) Arica:
calles, edificios, museos, parques, mercados, etc etc etc. Cambiale de nombre a uno fácil de usar.
Yo llamaré a mi mapa arica.osm.pbf
.
El siguiente paso es generar tiles con este archivo pbf.
Basado en la guía de https://switch2osm.org/serving-tiles/using-a-docker-container/.
En un terminal en linux:
.osm.pbf
allí.docker volume create osm-data
.osm.pbf
con este comando. Reemplaza
donde sea necesario:docker run -v /ruta/absoluta/al/archivo/arica.osm.pbf:/data/region.osm.pbf -v osm-data:/data/database/ overv/openstreetmap-tile-server import
Esto demorará varios minutos, dependiendo de tu velocidad de internet. Al final de este comando debes tener un mensaje como:
INFO:root: Import complete
+ sudo -u renderer touch /data/database/planet-import-complete
+ service postgresql stop
* Stopping PostgreSQL 15 database server
...done.
+ exit 0
Una vez termine el comando anterior ejecuta:
docker run -p 8080:80 -v osm-data:/data/database -d overv/openstreetmap-tile-server run
Esto creará un contenedor de docker con el servidor de tiles on-demand. Ahora entra en tu navegador a http://localhost:8080/.
Verás un mapa:
Aquí ve al lugar que importaste y asegurate de que se renderiza. Verás que los lugares fuera del área que definiste están en blanco. Esto es normal.
Con esto ya tienes un servidor on-demand. Puedes configurar tu sistema para que sea accesible desde el exterior, levantarlo en un vps, etc etc.
O también puedes obtener todos los tiles, almacenarlos y servirlos estáticamente. Eso se ve en el siguiente paso.
Continuara…
Habrás visto que los tiles vienen con un estilo por defecto:
Tal vez no te gustan los colores, tal vez no necesitas tantos íconos de negocios, tal vez quieres cambiar el tamaño o fuente de las letras. Todo esto se puede personalizar, lo que será tema de un próximo post.