Plugin QGIS para la gestión de obstáculos

Automatización del mantenimiento de la base de datos, cálculo de vulneraciones y generación de reseñas
Logo del Plugin QGIS

Para el desarrollo del complemento se han utilizado las siguientes herramientas y tecnologías de código abierto:

  • GitHub. Plataforma de alojamiento de código fuente que permite mantener proyectos de software de código abierto, colaborar entre diferentes equipos e integrar el control de versiones con Git.
  • Visual Studio Code. Editor de código multiplataforma que admite diferentes lenguajes de programación y se integra con Git para el control de cambios.
  • Plugin Builder 3. Herramienta de creación de plugins para QGIS que genera la estructura básica de carpetas y archivos de código necesarios.
  • Plugin Reloader. Complemento de QGIS que permite recargar automáticamente los plugins cuando se realizan cambios en el código, sin necesidad de reiniciar QGIS.
  • Python 3. Lenguaje de programación de alto nivel, ampliamente utilizado en el desarrollo de plugins y de fácil integración con QGIS a través de librerías específicas.
  • Librerías:
    • PyQGIS. Conjunto de clases que permiten ejecutar código Python en QGIS, proporcionando acceso a la API de QGIS para interactuar con capas vectoriales y ráster, proyectos, layouts, etc.
    • psycopg2. Librería de Python que proporciona una interfaz para conectarse y trabajar con bases de datos PostgreSQL, permitiendo ejecutar consultas SQL y gestionar transacciones.
    • pandas. Utilizada para manipular tablas de datos y construir hojas en formato Excel a partir de consultas a la base de datos.
    • simplekml. Utilizada para generar de forma simplificada archivos KML o KMZ con puntos y atributos, listos para visores como Google Earth.
    • PyQt. Proporciona una plataforma para el desarrollo de interfaces gráficas de usuario (GUI) mediante los widgets de Qt.
  • Qt Designer. Herramienta de diseño de interfaces gráficas que permite crear la disposición de ventanas y diálogos (widgets, botones, etiquetas de texto, etc.) de forma visual.
Imagen de la herramientas utilizadas

Creación de la estructura de carpetas del plugin

La estructura inicial del complemento se generó con el plugin oficial Plugin Builder 3 de QGIS, que automatiza la creación del esqueleto de un nuevo plugin. Mediante este complemento se definieron los datos básicos del proyecto (nombre del plugin, nombre de la clase principal, autor, versión, descripción y versión mínima de QGIS).

A partir de esta información, Plugin Builder 3 creó automáticamente una carpeta del plugin en el directorio de extensiones de QGIS, con la siguiente estructura básica:

  • Archivos de arranque del plugin: __init__.py, metadata.txt y el fichero principal de lógica (<nombre_plugin>.py).
  • Módulo con la clase de interfaz: por ejemplo, <nombre_plugin>_dialog.py.
  • Fichero de diseño de la interfaz en formato Qt Designer (.ui), ubicado en la subcarpeta forms/.
  • Recursos gráficos (icono del plugin, imágenes) definidos en un archivo resources.qrc y almacenados en una carpeta de imágenes.
  • Carpeta i18n/ preparada para futuras traducciones.

Creación de la interfaz del plugin

El diseño de la interfaz del plugin se ha desarrollado íntegramente a través de Qt Designer. Con el objetivo de facilitar al usuario una forma gráficamente cómoda de usar el plugin, se ha establecido una distribución por fases, agrupando en una misma ventana las distintas operaciones del flujo de trabajo (selección de aeropuerto, gestión de obstáculos, visitas, cálculos, exportaciones, etc.).

Lógica principal del plugin

En el archivo <nombre_plugin>_dialog.py es donde tiene lugar el trabajo principal del plugin. Está programado en lenguaje Python y utiliza las librerías mencionadas para ejecutar las diferentes tareas.

Cada fase del plugin se implementa mediante distintos métodos o funciones (def), que a su vez se relacionan con los widgets de la interfaz (botones, cuadros de selección, etc.). A continuación, se detalla la estructura del plugin dividida por fases, donde cada fase corresponde a una tarea específica del flujo de trabajo:

  • Selección y/o creación de una base de datos para un nuevo aeropuerto.
  • Fase 1. Carga y edición de la base de datos de obstáculos de un aeropuerto.
  • Fase 2. Creación y gestión de una tabla de visitas o mediciones de campo.
  • Fase 3. Análisis para calcular las vulneraciones frente a las SLO y obtención de referencias catastrales.
  • Fase 4. Generación de reseñas en formato PDF de cada uno de los obstáculos.
  • Fase 5. Exportación de la información de cada obstáculo a un fichero KMZ.
  • Fase 6. Exportación de las tablas de la base de datos a un archivo Excel en formato .xlsx.
  • Fase 7. Exportación del contenido de las tablas en formato GeoJSON para su uso en el visor de mapas web.
Interfaz principal del plugin de QGIS

Selección / creación de BBDD

La interfaz incorpora dos widgets: uno para seleccionar el aeropuerto sobre el que trabajar y otro para crear un nuevo aeropuerto en la base de datos PostgreSQL.

En primer lugar, el desplegable de selección lista automáticamente los aeropuertos disponibles detectados en el esquema public, extrayendo el código del aeropuerto a partir de las tablas que comienzan por bbdd_. Al confirmar la selección, el plugin establece ese aeropuerto como contexto activo y lo usa como criterio por defecto en el resto de las operaciones. Las tablas asociadas (bbdd_<código>, visitas_<código>, vuln_cast_<código>) pueden existir previamente (creadas en pgAdmin) o haberse generado desde el propio plugin en las fases posteriores.

Por otro lado, el botón de creación abre un diálogo donde se introduce el código del aeropuerto. El sistema crea la tabla bbdd_<código> aplicando ese prefijo. En el mismo diálogo se indica el huso UTM correspondiente, con el que se fija el SRID de las tablas. Tras la creación, el nuevo aeropuerto queda disponible en el QComboBox para su selección.

Para establecer la conexión plugin–BBDD PostgreSQL, se guardan los parámetros de conexión en un diccionario self.db_params y, a través de la librería psycopg2, se establece la conexión:

conn = psycopg2.connect(
    host=self.db_params["host"],
    port=self.db_params["port"],
    dbname=self.db_params["dbname"],
    user=self.db_params["user"],
    password=self.db_params["password"]
)

Mediante esta conexión se realiza una consulta SQL para listar las tablas existentes en la BBDD y mostrar únicamente las que siguen el patrón bbdd_. En caso de crear una nueva tabla, la conexión ejecuta la sentencia SQL CREATE TABLE bbdd_<código> (...).

Ventana de creación de tablas

Cargar y editar una BBDD (Fase 1)

En esta parte, el plugin se conecta a la BBDD PostgreSQL/PostGIS mediante los parámetros de conexión guardados en la fase anterior y construye con PyQGIS una capa PostGIS a partir de la tabla bbdd_<código> seleccionada. Esta capa se añade al proyecto de QGIS como QgsVectorLayer y se abre su tabla de atributos directamente en modo edición (startEditing()). El usuario trabaja sobre la tabla de atributos convencional de QGIS, editando los obstáculos directamente en la base de datos.

Imagen fase 1 class=

Actualizar la tabla de visitas (Fase 2)

En esta fase, el plugin se conecta de nuevo a la BBDD PostgreSQL/PostGIS con los parámetros de conexión definidos y genera, mediante PyQGIS, la tabla visitas_<código> a partir de los obstáculos en estado En seguimiento de bbdd_<código>. A continuación, construye una capa PostGIS desde esa tabla, la añade al proyecto de QGIS como QgsVectorLayer y abre su tabla de atributos directamente en modo edición (startEditing()). El usuario introduce en esa tabla las mediciones de campo y observaciones de cada visita utilizando la tabla de atributos convencional de QGIS.

Imagen de la tabla de visitas

Cálculo de vulneraciones y referencia catastral (Fase 3)

El plugin se conecta de nuevo a la BBDD PostgreSQL/PostGIS con los parámetros de conexión definidos y genera una tabla de resultados de vulneraciones. Para cada obstáculo, toma sus coordenadas planas (X, Y) y su altura y, mediante PyQGIS, muestrea el valor de cada ráster de superficie limitadora en ese punto. La vulneración se calcula como la diferencia entre la altura del obstáculo y la cota de la superficie (altura_obstáculo – altura_superficie): si el resultado es positivo se considera que vulnera la superficie y se almacena el valor, y si es cero o negativo se interpreta como “sin vulneración”.

De forma adicional, el plugin realiza una intersección espacial punto–en–polígono (similar a la herramienta “Unir atributos por localización” de QGIS) con la cartografía catastral para cada obstáculo y guarda la referencia catastral del polígono que lo contiene en la misma tabla de resultados.

Imagen de la tabla de vulneraciones

Generación de reseñas (Fase 4)

En esta fase se parte de una plantilla de diseño de impresión en QGIS (layout) previamente configurada con atlas, donde ya se ha definido la composición de la reseña: ortofoto centrada en el obstáculo, zona para fotografías de campo y bloque de datos relevantes (identificador, coordenadas, alturas, vulneración, etc.).

El plugin se conecta a la BBDD PostgreSQL/PostGIS, toma la capa de visitas como capa de cobertura del atlas y, mediante PyQGIS, recupera el layout, activa el atlas y, tras seleccionar la ortofoto y la carpeta de salida, itera por cada registro para exportar automáticamente una reseña en PDF con QgsLayoutExporter, generando un fichero por elemento con un nombre estructurado. Finalmente, actualiza la tabla de visitas en la base de datos marcando qué elementos disponen de reseña y guardando la ruta del PDF, de modo que esta información pueda reutilizarse después en el geoportal para la descarga directa de las reseñas.

Plantilla de la reseña de obstáculo

Generación de KMZ (Fase 5)

El plugin se conecta de nuevo a la BBDD PostgreSQL/PostGIS, extrae los obstáculos con sus coordenadas y atributos y genera un fichero KMZ listo para abrir en visores como Google Earth. Para ello utiliza la librería simplekml y reutiliza la lógica del complemento KMZTOOLS, organizando los elementos en carpetas según su tipo o estado (por ejemplo, finalizados, condicionados, en seguimiento, vulneran SLO), asignando estilos e iconos diferenciados y construyendo descripciones con la información más relevante de cada obstáculo. De este modo se obtiene una visualización 3D complementaria al trabajo en QGIS y al geoportal web.

Generación de tablas Excel (Fase 6)

El plugin se conecta a la BBDD PostgreSQL/PostGIS y extrae, mediante consultas SQL, las tablas principales del sistema (obstáculos, visitas y resultados de vulneraciones). Estas consultas se cargan en estructuras de datos con la librería pandas y, a continuación, se agrupan en un único libro de trabajo de Excel utilizando la clase ExcelWriter de la propia librería. El resultado es un fichero Excel estructurado y listo para revisión, explotación adicional o generación de informes, sin necesidad de exportaciones manuales desde QGIS ni copias y pegados desde distintas fuentes.

Exportación para el geoportal (Fase 7)

En esta fase, el plugin se conecta a la BBDD PostgreSQL/PostGIS y extrae, mediante consultas SQL y PyQGIS, las capas necesarias para la visualización web (obstáculos finalizados, condicionados, en seguimiento, vulneraciones y superficies asociadas). A partir de estos datos genera ficheros GeoJSON organizados por aeropuerto y tipo de información, listos para ser consumidos por el visor Leaflet. Además, crea un fichero de configuración en JavaScript que incluye el listado de aeropuertos y las rutas a cada GeoJSON, de manera que el geoportal pueda cargar dinámicamente las capas sin pasos manuales intermedios.