Como todo buen chaval en sus 20, me gusta vivir la vida y tener mis caprichines: conseguir un buen curro, independizarme, ahorrar para mi jubilación y comprar una vivienda. Afortunadamente, la mayoría de estos objetivos van bien encaminados pero lo de comprar la vivienda se me resiste. A veces me frustro con ello porque creo no hacer lo suficiente para lograrlo pero después veo los tipos de interés y se me pasa.
En todas mis venturas y desventuras en la búsqueda de un inmueble que me pueda permitir hay una constante: el mar de lágrimas que supone buscar información catastral. Una tarde de búsqueda de inmuebles suele ser así:
- Hacer doomscrolling a través de una miríada de anuncios que no se adecuan a mis necesidades
(a.k.a tendría que vender mi alma al diablo) - Encontrar un inmueble que podría valerme
- Revisar la información contra el catastro, especialmente para los terrenos
(Sí, valoro la autopromoción. ¿Que estoy loco? Lo sé) . Normalmente no hay referencia catastral y hay quesufrirutilizar el mapa de la web - Volver al punto 1
Pero Juan, ¿Por qué buscas todo esto en el catastro si normalmente en el anuncio te suele venir detallado? Una vez reporté un anuncio por listar un
terreno como urbano cuando en la información catastral del terreno(proporcionada en el anuncio) se listaba como rústico.
Procedieron a quitar la información catastral del anuncio en vez de listarla correctamente. Uno no se puede fiar de nadie hoy en día,
y menos con algo que te puede hipotecar
Experiencia de usuario
Os presento el mapa del catastro. A primera vista, puede parecer que el mapa es responsive. Invito al lector a hacer zoom hasta que se empiece a ver la información catastral:

A poco que se mueva el mapa se puede ver un símbolo de carga. Este se repite si se quiere cambiar la vista lo cuál, sinceramente, resulta bastante molesto. Si lo comparamos con la experiencia de usuario de Google Maps deja bastante que desear 😢:
¿Cómo funciona el catastro?
Por defecto profesional, ver que un sistema informático no funciona debidamente me llama la atención y, si lo tengo que usar frecuentemente, necesito intentar
arreglarlo
Peticiones HTTP
Como backender, mi primer instinto es ir a lo que conozco, las peticiones a una API:
Como se puede observar, se utilizan varias peticiones para renderizar el mapa:
- Las imágenes tomadas de tms-ign-base.idee.es que son bastante eficientes 👍
- Las imágenes tomadas de sedecatastro.gob.es que no lo son 👎
El hecho que una imagen del mapa tenga una latencia de casi 1 segundo no es un buen augurio. Echemosle un vistazo a varios de los parametros de la request:
SERVICE=WMSWIDTH=1920HEIGHT=425BBOX=-434969.6867710633,5381250.394276095,-425797.2433768422,5383280.75283992Hay varias cosas a destacar en estos parámetros:
- Los parámetros WIDTH y HEIGHT muestran claramente una petición de una imagen del tamaño del navegador. Esto se contrasta con la manera de hacer queries de Google Maps o tms-ign-base.idee.es ya que estos reciben varias imágenes por renderizado.
- BBOX al ser un rango continuo en vez de discreto, apunta a que el servidor realiza el renderizado a la hora de hacer la petición. La manera en la que se hace el resto de peticiones, al ser discretas y seguir una estructura de directorios, apunta a un servidor de contenido que simplemente sirve los archivos almacenados.
- El parámetro SERVICE apunta a una especificación de protocolo o de servidor de backend. Volveremos a ello más tarde.
La principal conclusión que se podría sacar de este análisis es que la interfaz de la request no es muy cache friendly. Cada vez que se mueve la visión del mapa es necesario rerenderizar la imagen entera. Además, no se puede prerenderizar imagenes fuera del viewport como en los mapas basados en tiling. Estos factores hacen la experiencia de usuario muy ortopédica.
¿Podemos arreglarlo del lado del cliente?
La hipótesis del apartado anterior apunta a que las peticiones no están muy optimizadas. Podría parecer a primera vista que no podemos hacer nada al respecto pero… ¡resulta que sí!.
Os presento Leaflet.js, una librería para integrar mapas interactivos usando diferentes servidores. Mientras leía la documentación de la librería para integrar la vista de idee.es, descubrí que había algo que se llamaba TileLayer.WMS ¿Os suena de algo? Exacto. Es el parámetro SERVICE de la request. Esto apunta a qué el backend usa un estándar definido y probablemente algún software open-source para servir la información.
Intentemos crear un pequeño componente JS para renderizar la información del catastro:
var map = L.map('map').setView([43.454, -3.823], 18);var IGN = L.tileLayer('https://tms-ign-base.idee.es/1.0.0/IGNBaseTodo/{z}/{x}/{-y}.jpeg', {maxZoom: 17});IGN.addTo(map);var ortofoto = L.tileLayer('https://tms-pnoa-ma.idee.es/1.0.0/pnoa-ma/{z}/{x}/{-y}.jpeg');ortofoto.addTo(map);var catastro = L.tileLayer.wms("https://www1.sedecatastro.gob.es/cartografia/GeneraMapa.aspx", { layers: 'CATASTRO', format: 'image/png', transparent: true});var baseMaps = { "IGN": IGN, "Ortofoto": ortofoto};var overlayMaps = { "Catastro": catastro}var layerControl = L.control.layers(baseMaps, overlayMaps).addTo(map);Aquí os presento el prototipo de mapa que permite renderizar tanto el mapa satelital como la información catastral. Arriba a la derecha se pueden desactivar/activar las diferentes capas. Si se prueba a hacer zoom y se activa la capa del catastro, se puede ver una gran mejora en el rendimiento.
⚠️ El servidor del catastro tiene rate limits al número de peticiones. Como el cliente usa un proceso de tiling, hace muchas más requests que de costumbre y puede saltar el rate limit. No recomiendo usar esta solución durante mucho tiempo(está aquí con fines ilustrativos) y para nada lo digo por experiencia propia 😇
La raíz del problema
Bingo. Así que se puede crear un cliente muy sencillo que funcione fluido con el backend. Entonces… ¿Cómo es que la experiencia de la web es tan nefasta?.
El código JavaScript del renderizado del mapa del catastro se puede acceder a través de este enlace. Una de las cosas importantes a las que hace referencia es a una librería llamada OpenLayers. Esta librería es, en esencia, una alternativa a LeafLet para visualizar mapas.
Veamos como hace uso de esta librería:
771 var vectorLayer = new ol.layer.Vector({ title: 'Posicionar', source: vectorSource });
777 var map = new ol.Map({778 interactions: interaccionesxDefecto,779 controls: ([pantallaCompleta, rotor, EscalaLineal, PosicionRatonGPS]),780 target: 'map',782 layers: [vectorLayer],783 moveTolerance: 5,784 view: vistaMapa785 });Como se puede ver, actualmente el catastro hace un uso ineficiente de la librería al usar una layer de vectorizado. Como habíamos visto antes, solicita la información catastral con una única solicitud de todo lo que se necesita renderizar en ese momento.
Si sustituimos la definición del mapa por:
779 var map = new ol.Map({780 interactions: interaccionesxDefecto,781 controls: ([pantallaCompleta, rotor, EscalaLineal, PosicionRatonGPS]),782 target: 'map',783 layers: [layerIGNT, layerTeseladaTamanio, layerTeselada],784 moveTolerance: 5,785 view: vistaMapa786 });y se activa la capa en el loop del programa:
if (ponerCAT && ponerCATEscala) { map.addLayer(layer1Imagen); map.addLayer(layerTeselada);}if (ponerGeoServerWMSR) { map.addLayer(layerGeoserverWMSR);};if (ponerGeoServerWMTSR) { map.addLayer(layerGeoserverWMTSR);};if (soloTematicos) { if (ponerTematicos) { map.removeLayer(layer1Imagen); map.removeLayer(layerTeselada); map.addLayer(layer1Tematicos); };}Conseguimos que el cliente obtenga el mapa de manera teselada 🎉🎉🎉
¿Pero con teselación no bombardearíamos a peticiones el servidor?
Si y no. Efectivamente, con la infraestructura actual del servidor al necesitar renderizar cada imagen que devuelve la teselación
podría provocar una denegación de servicios
sequenceDiagram
Participant WMS
Participant Frontend
Actor Usuario
Usuario ->> Frontend: Mueve la vista
Frontend ->> WMS: HTTP GET PNG
WMS -->> WMS: Renderizando vista(1 seg delay)....
WMS -->> Frontend: Respuesta HTTP PNG
Frontend ->> Usuario: El usuario ve la actualización del mapa
Sin embargo, si la teselación usara un protocolo XYZ como hace Google o IDEE, sería facilmente convertible en un problema de content delivery, lo cuál es inherentemente menos costoso:
sequenceDiagram
Participant WMS
participant Cache
participant API
Participant Frontend
Actor Usuario
Usuario ->> Frontend: Mueve la vista
Frontend ->> API: HTTP GET XYZ PNG
API ->> Cache: HTTP GET XYZ PNG
Cache -->> API: Respuesta HTTP PNG
alt Si la casilla no está presente
API ->> WMS: HTTP GET PNG
WMS -->> WMS: Renderizando vista(1 seg delay)....
WMS -->> API: Respuesta HTTP PNG
API ->> Cache: Guardar la imagen en la cache
end
API -->> Frontend: Respuesta HTTP PNG
Frontend ->> Usuario: El usuario ve la actualización del mapa
Con esta solución, la web del catastro podría tener la fluidez que hemos conseguido en el ejemplo de Javascript sin incurrir en un sobrecoste computacional al lanzar varias renderizaciones simultáneas. Además, no sería necesario un cambio en el backend ni de la infraestructura con la que se suben actualizan los datos.
De hecho, con simplemente invalidar la cache cuando se produzca una actualización de los datos de esa región sería suficiente para tener los datos actualizados.
Próximos pasos
Tras este análisis y sin involucrar al catastro, se podría intentar montar un servidor de visualización optimizado con los datos abiertos del catastro. Sin embargo, el volcado masivo de los datos del catastro se actualiza 2 veces al año y, sin obtener actualizaciones en tiempo real, el mapa quedaría desactualizado rápidamente.
Otra opción sería montar la cache encima de la API pública del servidor WMS. Sería la opción más viable ya que permitiría obtener actualizaciones en tiempo real simplemente
invalidando la caché. Sin embargo, la API pública del catastro tiene rate_limits
Así que, de momento, este mini proyecto se va al cajón de proyectos en pausa a la espera de que algún alma caritativa use este post para arreglar la UX de la web.