lunes, 1 de diciembre de 2025

Perspectiva aérea desde mapa de elevaciones con C++

En 'Perspectiva aérea desde mapa de elevaciones con R' se explicaba el concepto de perspectiva aérea y se proponía un algoritmo, mucho más bonito e interesante que eficiente, para calcular de forma quasi vectorizada en R imágenes en perspectiva aérea a partir de un mapa de elevaciones.

Pero los tiempos avanzan, y en la era de los LLM's podemos reformular el código por fuerza bruta en R, es decir usando bucles sin contemplaciones, y pedirle a ChatGPT que lo traduzca a C++ embebido para acelerarlo. Traducir código se le da excepcionalmente bien a ChatGPT, y ejecutar bucles rápido es la especialidad de C++, así que solo pueden formar un equipo ganador.

Vamos a calcular algunos ejemplos de la geografía española, partiendo de datos de elevación con resolución de 2m del Centro Nacional de Información Geográfica del Ministerio de Transportes.

Un bucle lee secuencialmente las filas del DEM de arriba abajo, acumulando sobre una imagen final los perfiles o siluetas de cada fila individual del DEM y asignándoles un nivel de gris creciente. La oclusión de atrás hacia adelante entre las superposiciones acumuladas implementa implícitamente la eliminación de superficies ocultas. El resultado es la perspectiva aérea isométrica de un observador situado en la parte inferior del DEM:



Procesamos en Photoshop la perspectiva aérea para dejarla más interesante (hacer clic para ver en resolución original):



En el segundo ejemplo calculamos la perspectiva aérea de la zona pirenaica en la que se encuentra enclavado su pico más alto, el Aneto (hacer clic para ver en alta resolución):



Y sin salirnos de la región hacemos lo propio con el Parque Nacional de Ordesa y Monte Perdido (hacer clic para ver en alta resolución):



Terminamos con el perfil montañoso, esta vez más suave y alargado, que hay en Gerona entre Torroella de Montgrí y las islas Medas, pasando por Estartit. Con las islas he hecho un poco de trampa rotándolas en el DEM para que no se solapen entre ellas, cosa que ocurre cuando se observan desde sur (hacer clic para ver en alta resolución):


~~~

La mejora en velocidad de la versión compilada en C++ es de dos órdenes de magnitud, pasando de más de 2min a menos de 2s de tiempo de ejecución sobre el raster del Aneto, un DEM de gran tamaño (6.500x7.500 píxeles o 49Mpx). Tiempos de 3 ejecuciones de cada rutina (s):


~~~

En videojuegos de los 80 se generaba sensación de profundidad cuando el personaje se movía horizontalmente con la técnica parallax scrolling, consistente en desplazar los elementos de la pantalla a distintas velocidades horizontales: más rápido los del primer plano y más lentamente los más lejanos.

Se emulaba así la sensación que percibimos cuando viajamos en coche o en tren y miramos el paisaje por una ventana lateral: las cosas cercanas al vehículo pasan muy rápido mientras la montaña que queda lejos lo hace más lentamente, y la luna o el sol directamente nos "persiguen" ya que no se mueven en absoluto.

Tomando la perspectiva aérea de Ordesa y Monte Perdido he probado a aplicar este trampantojo. Funciona fantásticamente al principio, y con mucha suavidad ya que estamos usando tantos planos como resolución tiene el DEM (en concreto 4.650 filas con desplazamiento independiente). Una vez se empieza a perder la correspondencia real entre los relieves cercanos y los lejanos se estropea un poco la cosa al generarse montañas ficticias alargadas bastante anodinas (hacer clic para ver el vídeo):



Los frames se han generado en R compilando en C++ el cálculo del mapa de elevación parcial desplazado para cada frame y su correspondiente conversión a perspectiva aérea. En total se alcanza un ritmo de unos 4fps, es decir unos 6s de cálculo para cada segundo de animación.

~~

Repositorio con el código R: GitHub.

No hay comentarios:

Publicar un comentario

Por claridad del blog, por favor trata de utilizar una sintaxis lo más correcta posible y no abusar del uso de emoticonos, mayúsculas y similares.