Proyecto: Inventario de árboles urbanos
Marco Hernandez
Un inventario de árboles urbanos es, en esencia, un sistema de información geográfica especializado: cada árbol es una entidad con ubicación, atributos biológicos, estado de salud e historial de intervenciones. Pero para que sea realmente útil —tanto para el municipio que planifica podas y detecta riesgos, como para el vecino que quiere saber qué especie tiene enfrente de su casa— el diseño no puede quedarse en “un punto en un mapa con un nombre”. Necesita un modelo de datos que soporte series temporales de inspecciones, una capa de permisos que distinga usuarios institucionales de contribuciones ciudadanas, y un flujo de moderación que permita crecer con datos abiertos sin perder calidad.
En este artículo recorremos la arquitectura completa: el modelo de entidades, las relaciones entre tablas, el stack técnico recomendado y las funcionalidades que separan un inventario útil de una simple capa de puntos en un mapa.
Modelo de entidades
El núcleo del sistema gira alrededor de seis grupos de entidades: el árbol individual, su especie, su ubicación administrativa, su historial de inspecciones, las intervenciones de mantenimiento y los usuarios/instituciones que interactúan con él.
1. species (catálogo de especies)
No conviene guardar el nombre de la especie como texto libre en cada árbol: se repite miles de veces, genera inconsistencias (“Jacaranda” vs “jacaranda mimosifolia”) y no permite enriquecer datos comunes a toda la especie.
| Columna | Tipo | Descripción |
|---|---|---|
| id | bigint PK | Identificador |
| scientific_name | varchar | Nombre científico |
| common_name | varchar | Nombre común local |
| family | varchar | Familia botánica |
| origin | enum | Nativa / introducida / invasora |
| avg_height_m | numeric | Altura promedio adulta |
| avg_canopy_m | numeric | Diámetro de copa promedio |
| growth_rate | enum | Lento / medio / rápido |
| description | text | Notas ecológicas |
2. trees (el árbol individual)
Es la tabla central. Cada fila es un árbol real, geolocalizado con PostGIS.
| Columna | Tipo | Descripción |
|---|---|---|
| id | bigint PK | Identificador |
| species_id | FK → species | Especie asignada |
| geom | geometry(Point, 4326) | Ubicación exacta (PostGIS) |
| neighborhood_id | FK → neighborhoods | Barrio / comuna |
| address_reference | varchar | Dirección aproximada legible |
| planting_date | date, nullable | Fecha de plantación si se conoce |
| dbh_cm | numeric | Diámetro a la altura del pecho |
| height_m | numeric | Altura estimada actual |
| status | enum | Vivo / muerto / talado / reemplazado |
| ownership | enum | Público / privado con vereda pública |
| source | enum | Institucional / ciudadano / importación masiva |
| created_by | FK → users | Quién lo cargó |
| verified | boolean | Si pasó moderación |
| created_at / updated_at | timestamp | Auditoría |
El campo geom como tipo geométrico nativo (y no dos columnas lat/lng) es lo que permite hacer consultas espaciales reales: “árboles a menos de 200 m de esta escuela”, “árboles dentro de este polígono de barrio”, o generar mapas de calor de cobertura arbórea directamente en SQL con ST_DWithin, ST_Within y funciones similares de PostGIS.
3. inspections (historial de estado)
Un árbol no es estático: se enferma, crece, pierde ramas. Cada visita técnica genera un registro, nunca se sobrescribe el estado anterior.
| Columna | Tipo | Descripción |
|---|---|---|
| id | bigint PK | Identificador |
| tree_id | FK → trees | Árbol inspeccionado |
| inspector_id | FK → users | Técnico responsable |
| inspection_date | date | Fecha |
| health_status | enum | Óptimo / regular / deficiente / crítico |
| risk_level | enum | Bajo / medio / alto (riesgo de caída) |
| findings | text | Observaciones (plagas, hongos, daño estructural) |
| photos | relación a media |
Evidencia fotográfica |
Este historial es lo que convierte al sistema en una herramienta de gestión de riesgo real: permite ver la evolución de un árbol en el tiempo y priorizar intervenciones antes de que ocurra una caída.
4. interventions (mantenimiento)
Registra qué se hizo, no solo qué se observó.
| Columna | Tipo | Descripción |
|---|---|---|
| id | bigint PK | Identificador |
| tree_id | FK → trees | Árbol intervenido |
| type | enum | Poda / fumigación / apuntalamiento / tala / plantación / reemplazo |
| performed_by | FK → users/institutions | Cuadrilla o contratista |
| performed_at | date | Fecha de ejecución |
| cost | numeric, nullable | Costo (solo visible a nivel institucional) |
| notes | text | Detalle de la intervención |
5. neighborhoods (unidad administrativa)
Una tabla poligonal (geometry(Polygon, 4326)) con los límites de barrios, comunas o cualquier división administrativa relevante, que permite agregaciones estadísticas por zona (“cobertura arbórea por barrio”, “densidad de árboles por habitante”).
6. users / roles
| Rol | Puede |
|---|---|
| Ciudadano anónimo | Ver el mapa público, consultar fichas de árboles |
| Ciudadano registrado | Reportar árboles nuevos, reportar incidencias, comentar |
| Moderador comunitario | Validar reportes ciudadanos, resolver conflictos de datos |
| Técnico institucional | Cargar inspecciones e intervenciones oficiales |
| Administrador municipal | Gestionar usuarios, exportar reportes, definir políticas |
Relaciones entre tablas
El diagrama relacional queda, en términos generales, así:
species (1) ───< (N) trees
neighborhoods (1) ───< (N) trees
trees (1) ───< (N) inspections
trees (1) ───< (N) interventions
trees (1) ───< (N) media
users (1) ───< (N) trees (created_by)
users (1) ───< (N) inspections (inspector_id)
users (1) ───< (N) interventions (performed_by)
Todo se conecta a través del árbol (trees) como entidad central, y este a su vez pertenece a una especie y a una unidad administrativa. El patrón es deliberadamente similar al de un sistema de tickets: el árbol es el “caso” y las inspecciones/intervenciones son sus “eventos” en el tiempo, lo cual facilita construir líneas de tiempo y reportes de auditoría con consultas SQL relativamente simples.
Stack técnico recomendado
Para un proyecto de este tipo, una combinación probada es:
- Backend: Laravel + PHP, con Eloquent y el paquete
laravel-postgis(o consultas raw conDB::selectpara las operaciones espaciales más complejas) sobre PostgreSQL + PostGIS como base de datos. PostGIS no es opcional aquí: es lo que habilita los índices espaciales (GIST) que hacen viable renderizar miles de árboles en un mapa sin degradar el rendimiento. - API: un conjunto de endpoints REST (o GraphQL si se prefiere) que expongan los árboles como GeoJSON, formato que consumen de forma nativa la mayoría de las librerías de mapas.
- Frontend público y de carga: Vue.js con Leaflet (o MapLibre GL si se necesita renderizado vectorial más pesado) para el visor de mapa, y un formulario simple de carga con geolocalización del dispositivo para las contribuciones ciudadanas.
- Almacenamiento de imágenes: un disco S3-compatible para las fotos de inspecciones y reportes, referenciado desde una tabla
mediapolimórfica.
Funcionalidades para usuarios institucionales
Un municipio no usa el inventario para “mirar árboles”; lo usa para tomar decisiones y justificar presupuesto. Las funcionalidades clave incluyen:
- Panel de riesgo: listado priorizado de árboles con
risk_level = alto, para programar podas o apuntalamientos antes de la temporada de vientos o lluvias fuertes. - Planificación de intervenciones: calendario de podas/fumigaciones por cuadrilla y por zona, generado a partir de las inspecciones pendientes.
- Reportes agregados: cobertura arbórea por barrio, especies dominantes, edad promedio del arbolado, servicios ecosistémicos estimados (captura de CO₂, sombra generada, reducción de temperatura), calculados con fórmulas alométricas simples a partir del DAP (diámetro a la altura del pecho) y la especie.
- Exportación de datos: shapefile, GeoJSON o CSV para cruzar con otros sistemas municipales (catastro, obras públicas, permisos de construcción).
- Trazabilidad legal: historial completo de intervenciones por árbol, útil ante reclamos vecinales o auditorías.
Funcionalidades para habitantes de la ciudad
Del lado ciudadano, el valor está en la cercanía y la utilidad cotidiana:
- Mapa público interactivo: cualquiera puede buscar “¿qué árbol es ese?” tocando el punto en el mapa y viendo especie, edad estimada y una foto.
- Reporte de incidencias: “esta rama está por caer”, “este árbol parece enfermo”, con foto y geolocalización automática desde el celular, que entra como un reporte pendiente de verificación.
- Solicitud de plantación: un vecino puede pedir que se plante un árbol en una vereda específica, lo que alimenta la planificación institucional de nuevas plantaciones.
- “Adoptar un árbol”: asignar informalmente el cuidado de riego de un árbol cercano a un vecino interesado, con recordatorios simples.
- Ficha educativa por especie: información sobre beneficios, cuidados y curiosidades, aprovechando la tabla
speciesya cargada.
Features para que la comunidad contribuya y lo mantenga
Esta es, muchas veces, la parte que decide si el proyecto sigue vivo después del entusiasmo inicial. Algunas piezas de arquitectura que lo facilitan:
- Flujo de moderación con estado
verified: todo árbol o reporte cargado por un ciudadano entra comoverified = falsey queda visible en una cola de moderación. Un moderador comunitario (no necesariamente un empleado municipal) puede aprobar, corregir o rechazar, con un motivo registrado. - Historial de cambios (versionado): cada edición a un árbol se guarda en una tabla
tree_revisionscon el valor anterior, quién lo cambió y cuándo, al estilo wiki. Esto da confianza para abrir la edición a la comunidad sin miedo a perder datos. - Gamificación ligera: contador de árboles reportados y verificados por usuario, insignias simples (“100 árboles mapeados”), y un ranking opcional por barrio para incentivar la cobertura de zonas menos mapeadas.
- API pública y datos abiertos: exponer el inventario (sin datos sensibles como costos de intervención) bajo una licencia abierta y un endpoint documentado, para que universidades, ONGs o desarrolladores externos puedan construir sobre el proyecto.
- Reglas de conflicto claras: si dos personas reportan datos distintos sobre el mismo árbol (por ejemplo, especie diferente), el sistema debe mostrar ambas versiones al moderador en lugar de que una sobrescriba silenciosamente a la otra.
- Documentación y guías de contribución: una guía corta de “cómo identificar la especie”, “cómo tomar una buena foto para el reporte”, y un canal de comunicación (foro, grupo, issues en un repositorio) para que la comunidad técnica pueda proponer mejoras al propio software, si el proyecto se libera como código abierto.
Conclusión
Un inventario de árboles urbanos bien diseñado no es solo una capa más en un SIG municipal: es una pieza de infraestructura cívica que conecta la gestión técnica del arbolado con la participación ciudadana cotidiana. La clave arquitectónica está en separar claramente el árbol (dato estable), su historial de inspecciones e intervenciones (datos temporales) y la capa de contribución/moderación (datos de confianza variable), de modo que instituciones y habitantes puedan alimentar el mismo sistema sin pisarse los datos entre sí. Con PostgreSQL y PostGIS como base espacial, Laravel como capa de negocio y Vue.js como interfaz, es perfectamente viable construir este tipo de plataforma con un equipo pequeño y hacerla crecer de forma sostenida gracias a la comunidad que la usa y la cuida.