blog(es): post on osm tiles
@ -11,10 +11,10 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@astrojs/check": "^0.9.4",
|
"@astrojs/check": "^0.9.4",
|
||||||
"@astrojs/mdx": "^3.1.7",
|
"@astrojs/mdx": "^3.1.9",
|
||||||
"@astrojs/tailwind": "^5.1.1",
|
"@astrojs/tailwind": "^5.1.2",
|
||||||
"@types/node": "^22.3.0",
|
"@types/node": "^22.3.0",
|
||||||
"astro": "^4.15.11",
|
"astro": "^4.16.10",
|
||||||
"tailwindcss": "^3.4.5",
|
"tailwindcss": "^3.4.5",
|
||||||
"typescript": "^5.5.3"
|
"typescript": "^5.5.3"
|
||||||
},
|
},
|
||||||
|
745
pnpm-lock.yaml
@ -74,6 +74,10 @@ pre.astro-code>code .line::before {
|
|||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#blog ul {
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@media (prefers-color-scheme: dark) {
|
@media (prefers-color-scheme: dark) {
|
||||||
.astro-code {
|
.astro-code {
|
||||||
|
BIN
public/img/blog/es/osm/01.jpg
Normal file
After Width: | Height: | Size: 122 KiB |
BIN
public/img/blog/es/osm/02.jpg
Normal file
After Width: | Height: | Size: 141 KiB |
BIN
public/img/blog/es/osm/03.jpg
Normal file
After Width: | Height: | Size: 163 KiB |
BIN
public/img/blog/es/osm/04.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
public/img/blog/es/osm/05.jpg
Normal file
After Width: | Height: | Size: 57 KiB |
BIN
public/img/blog/es/osm/06.jpg
Normal file
After Width: | Height: | Size: 71 KiB |
BIN
public/img/blog/es/osm/07.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
public/img/blog/es/osm/08.jpg
Normal file
After Width: | Height: | Size: 97 KiB |
BIN
public/img/blog/es/osm/09.jpg
Normal file
After Width: | Height: | Size: 33 KiB |
BIN
public/img/blog/es/osm/10.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
public/img/blog/es/osm/11.jpg
Normal file
After Width: | Height: | Size: 104 KiB |
BIN
public/img/blog/es/osm/11.jpg~
Normal file
After Width: | Height: | Size: 96 KiB |
BIN
public/img/blog/es/osm/12.jpg
Normal file
After Width: | Height: | Size: 675 KiB |
BIN
public/img/blog/es/osm/13.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
public/img/blog/es/osm/14.jpg
Normal file
After Width: | Height: | Size: 62 KiB |
BIN
public/img/blog/es/osm/15.jpg
Normal file
After Width: | Height: | Size: 106 KiB |
BIN
public/img/blog/es/osm/16.jpg
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
public/img/blog/es/osm/17.jpg
Normal file
After Width: | Height: | Size: 23 KiB |
BIN
public/img/blog/es/osm/18.jpg
Normal file
After Width: | Height: | Size: 18 KiB |
BIN
public/img/blog/es/osm/19.jpg
Normal file
After Width: | Height: | Size: 78 KiB |
BIN
public/img/blog/es/osm/20.jpg
Normal file
After Width: | Height: | Size: 82 KiB |
345
src/pages/blog/es/osm-maps.md
Normal file
@ -0,0 +1,345 @@
|
|||||||
|
---
|
||||||
|
layout: ../../../layouts/BlogLayoutEs.astro
|
||||||
|
title: Como crear/utilizar mapas online sin pagar a Google
|
||||||
|
description: |
|
||||||
|
Esta guia detalla todo el proceso para crear tu propio
|
||||||
|
Google maps, sin pagar 1 centavo.
|
||||||
|
pubDate: "2024-11-10"
|
||||||
|
tags: ["mapas", "maps", "google maps", "openstreetmaps", "osm", "docker", "go"]
|
||||||
|
image:
|
||||||
|
url: "/img/blog/es/osm/01.jpg"
|
||||||
|
alt: "Mapa del centro de Arequipa-Perú"
|
||||||
|
caption: "Ejemplo de un mapa de Arequipa, generado por mi"
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
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](https://combi.araozu.dev/), 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.](https://www.openstreetmap.org/copyright)
|
||||||
|
|
||||||
|
|
||||||
|
## Requisitos
|
||||||
|
|
||||||
|
Esto es todo lo que utilizo para crear los mapas. En particular
|
||||||
|
Linux. Puede que esta guia funcione en Windows, puede que no.
|
||||||
|
|
||||||
|
- Cualquier linux reciente. Yo utilizo arch (btw).
|
||||||
|
- Docker y docker compose
|
||||||
|
- El [lenguaje de programación Go](https://go.dev) instalado.
|
||||||
|
- Conocimiento básico de la terminal
|
||||||
|
- Conocimiento básico de Docker
|
||||||
|
- (opcional) conocimientos de un editor de texto para terminal: nano/vi/vim
|
||||||
|
- (opcional) conocimiento de servidores como apache/nginx
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Tiles
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
![Mapa del centro de Arequipa](/img/blog/es/osm/02.jpg)
|
||||||
|
|
||||||
|
![Mapa del centro de Arequipa con divisiones para los tiles](/img/blog/es/osm/03.jpg)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
![Petición de tiles en combi.araozu.dev](/img/blog/es/osm/04.jpg)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
[Tiles en Wikipedia inglés.](https://en.wikipedia.org/wiki/Tiled_web_map)
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Niveles (layers)
|
||||||
|
|
||||||
|
También, los mapas tienen varios niveles de zoom:
|
||||||
|
|
||||||
|
![Arequipa, nivel 1](/img/blog/es/osm/05.jpg)
|
||||||
|
|
||||||
|
![Arequipa, nivel 2](/img/blog/es/osm/06.jpg)
|
||||||
|
|
||||||
|
Estos niveles van del 0 al 22. El nivel 0 es un único tile que muestra
|
||||||
|
todo el planeta:
|
||||||
|
|
||||||
|
![Tile nivel 0](/img/blog/es/osm/07.jpg)
|
||||||
|
|
||||||
|
El nivel 1 duplica sus dimensiones, así que consta de 4 tiles:
|
||||||
|
|
||||||
|
![Tile nivel 1](/img/blog/es/osm/08.jpg)
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Posicionamiento de los tiles
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
![Axis del mapa](/img/blog/es/osm/09.jpg)
|
||||||
|
|
||||||
|
Por ejemplo, en zoom 0 el único tile que existe es:
|
||||||
|
|
||||||
|
![Tile 0/0/0](/img/blog/es/osm/10.jpg)
|
||||||
|
|
||||||
|
En zoom 1 hay 4 tiles:
|
||||||
|
|
||||||
|
![Tiles de zoom 1](/img/blog/es/osm/11.jpg)
|
||||||
|
|
||||||
|
Y así sucesivamente. Un último ejemplo: el centro de Arequipa
|
||||||
|
en nivel 15 tiene estos tiles:
|
||||||
|
|
||||||
|
<div class="text-center"><img src="/img/blog/es/osm/12.jpg" style="display: inline-block;max-height: 800px;" /></div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Mapas como datos
|
||||||
|
|
||||||
|
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](https://openstreetmap.org/), ver a alguna
|
||||||
|
parte del mundo e inspeccionar cualquier cosa:
|
||||||
|
|
||||||
|
![OSM inspector](/img/blog/es/osm/13.jpg)
|
||||||
|
|
||||||
|
Eventualmente encontrarás el código xml de lo que inspecciones. Algo
|
||||||
|
como esto:
|
||||||
|
|
||||||
|
```xml
|
||||||
|
<?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.
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Renderizadores
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
## Teoría: Servidores de mapas
|
||||||
|
|
||||||
|
Una vez renderizados los tiles se sirven mediante un servidor web.
|
||||||
|
Esto puede ser un CDN, un VPS, un servicio de nube, etc.
|
||||||
|
|
||||||
|
### Servidores on-demand
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
### Servidores estáticos
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
## Teoría: Clientes
|
||||||
|
|
||||||
|
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](https://leafletjs.com/).
|
||||||
|
Le entregas la URL donde estan los tiles, y se encarga del resto.
|
||||||
|
|
||||||
|
![Leaflet](/img/blog/es/osm/14.jpg)
|
||||||
|
|
||||||
|
|
||||||
|
[OpenStreetMap](https://openstreetmap.org) 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.
|
||||||
|
|
||||||
|
|
||||||
|
## La práctica: Crear y servir nuestros propios tiles estáticos
|
||||||
|
|
||||||
|
Ahora viene lo divertido:
|
||||||
|
|
||||||
|
## Descargar datos del mapa que queremos
|
||||||
|
|
||||||
|
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](https://planet.openstreetmap.org/) se encuentra
|
||||||
|
un indice de los datos de todo el planeta. Descargar todos los
|
||||||
|
datos del planeta tierra pesa **144GiB**.
|
||||||
|
|
||||||
|
En [Geofabrik.de](https://download.geofabrik.de/) puedes
|
||||||
|
descargar todo un continente y paises. Por ejemplo, todo sudamerica
|
||||||
|
pesa **3.4GiB**, y todo Argentina pesa **352MiB**.
|
||||||
|
|
||||||
|
En [BBBike](https://download.bbbike.org/osm/bbbike) puedes descargar
|
||||||
|
ciertas áreas o ciudades importantes.
|
||||||
|
|
||||||
|
Para descargar un área en específico ve a
|
||||||
|
[Protomaps](https://app.protomaps.com/)
|
||||||
|
y selecciona el área que quieres descargar.
|
||||||
|
Yo descargaré Arica, Chile para el tutorial.
|
||||||
|
|
||||||
|
<div class="text-center"><img src="/img/blog/es/osm/15.jpg" style="display: inline-block;max-height: 800px;" /></div>
|
||||||
|
|
||||||
|
Otra herramienta útil para obtener un área en coordenadas es
|
||||||
|
[Tile Calculator](https://tools.geofabrik.de/calc/).
|
||||||
|
|
||||||
|
Tras presionar "Create Extract" se empezará a procesar la solicitud:
|
||||||
|
|
||||||
|
<div class="text-center"><img src="/img/blog/es/osm/16.jpg" style="display: inline-block;max-height: 800px;" /></div>
|
||||||
|
|
||||||
|
Una vez termine, descarga el mapa con el boton "Download .OSM.PBF":
|
||||||
|
|
||||||
|
<div class="text-center"><img src="/img/blog/es/osm/17.jpg" style="display: inline-block;max-height: 800px;" /></div>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
## Crear un renderizador on-demand
|
||||||
|
|
||||||
|
Basado en la guía de
|
||||||
|
[https://switch2osm.org/serving-tiles/using-a-docker-container/](https://switch2osm.org/serving-tiles/using-a-docker-container/).
|
||||||
|
|
||||||
|
En un terminal en linux:
|
||||||
|
|
||||||
|
- Crea una carpeta y mueve tu archivo `.osm.pbf` allí.
|
||||||
|
- Crea un volumen de docker con:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
docker volume create osm-data
|
||||||
|
```
|
||||||
|
|
||||||
|
- Importa tu archivo `.osm.pbf` con este comando. Reemplaza
|
||||||
|
donde sea necesario:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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:
|
||||||
|
|
||||||
|
```plain
|
||||||
|
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:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
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/](http://localhost:8080).
|
||||||
|
|
||||||
|
Verás un mapa:
|
||||||
|
|
||||||
|
![Leaflet](/img/blog/es/osm/18.jpg)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
![Leaflet](/img/blog/es/osm/19.jpg)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
## Scrapear nuestro renderizador
|
||||||
|
|
||||||
|
Continuara...
|
||||||
|
|
||||||
|
|
||||||
|
## Compilar nuestros tiles
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Personalizar nuestros tiles
|
||||||
|
|
||||||
|
Habrás visto que los tiles vienen con un estilo por defecto:
|
||||||
|
|
||||||
|
![Leaflet](/img/blog/es/osm/20.jpg)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|