El estudio del relieve mediante variables geomorfométricas, como la pendiente (slope) y la orientación del terreno (aspect), es fundamental para comprender la dinámica ambiental y las condiciones físicas que influyen en el uso del suelo, la agricultura y la gestión del territorio. En el caso del departamento del Valle del Cauca, caracterizado por una marcada heterogeneidad topográfica que abarca desde las planicies del río Cauca hasta las laderas de las cordilleras Occidental y Central, el análisis del relieve permite identificar zonas con diferentes niveles de aptitud para actividades agrícolas, conservación ambiental o desarrollo urbano.
El cálculo y visualización de estas variables se realizan a partir de un Modelo Digital de Elevación (DEM), el cual proporciona información altimétrica del terreno. A partir del DEM es posible derivar atributos como la pendiente, que representa la inclinación del terreno en grados o porcentaje, y la orientación o aspecto, que indica la dirección hacia la cual se inclina la superficie.
Estos parámetros son esenciales para múltiples disciplinas, incluyendo la agronomía, la hidrología, la planificación territorial y los estudios de riesgo ambiental, ya que influyen en la escorrentía, la exposición solar, la retención de humedad y la erosión del suelo.
En este cuaderno se presenta el procedimiento completo para el
cálculo, análisis y visualización interactiva de estas variables
geomorfométricas aplicadas al territorio del Valle del Cauca, empleando
herramientas del lenguaje R como
terra,sf,leaflet y MultiscaleDTM, las cuales
permiten reproducir un flujo de trabajo técnico, automatizado y
visualmente comprensible para la interpretación espacial del relieve
departamental.
Limpiamos la memoria.
rm(list=ls())
Cargamos las librerías:
Estas son las librerías que necesitaremos para realizar el trabajo
library(sf)
## Linking to GEOS 3.13.1, GDAL 3.11.0, PROJ 9.6.0; sf_use_s2() is TRUE
library(leaflet)
library(terra)
## terra 1.8.70
library(MultiscaleDTM)
## Warning: package 'MultiscaleDTM' was built under R version 4.5.2
library(exactextractr)
## Warning: package 'exactextractr' was built under R version 4.5.2
Las funciones de las librerías son las siguientes:
terra sirve para la lectura, el procesamiento y el análisis de datos espaciales raster.
sf trabaja con datos espaciales vectoriales.
leaflet permite la creación de mapas interactivos directamente en R o RMarkdown. MultiscaleDTM sirve para el análisis de terreno a diferentes escalas espaciales usando modelos digitales de terreno (DTM O DEM).
exactextractr sirve para extraer valores de raster como DTM, dentro de polígonos de forma muy precisa y eficiente.
MultiscaleDTM es un paquete del lenguaje R diseñado para el análisis geomorfométrico de modelos digitales del terreno (DTM o DEM, por sus siglas en inglés). Su principal función es calcular de manera eficiente y precisa diferentes atributos del relieve, tales como pendiente (slope), orientación (aspect), curvatura, rugosidad, altitud relativa, entre otros, a múltiples escalas espaciales.
El enfoque “multiescala” permite analizar cómo cambian las características del terreno cuando se usan diferentes tamaños de ventana o vecindario. Por ejemplo, una ventana pequeña (3x3 celdas) detecta variaciones locales —como microrelieves o pequeños taludes—, mientras que una ventana grande (9x9 o más) suaviza el terreno y resalta las formas generales del paisaje, como laderas o divisorias de aguas.
En términos prácticos, el paquete MultiscaleDTM combina métodos
geométricos y estadísticos para derivar variables topográficas a partir
de un raster de elevación. Una de sus funciones más empleadas,
SlpAsp(), permite calcular simultáneamente la pendiente y
la orientación del terreno en grados o radianes, a partir de un modelo
digital de elevación previamente reproyectado a coordenadas planas.
De esta manera, MultiscaleDTM se convierte en una herramienta fundamental para estudios en geografía, geomorfología, hidrología, agricultura de precisión y planificación ambiental, al facilitar el procesamiento reproducible y automatizado de información topográfica en entornos de código abierto.
Necesitamos cargar el raster con DEM de nuestro departamento realizado con anterioridad. Para ello vamos a utilizar la librería terra
list.files()
## [1] "COL_msk_alt.tif"
## [2] "cuadermopendiente_cnd.nb.html"
## [3] "Datos de elevacion del Valle del Cauca.Rmd"
## [4] "ElevacionValleDelCauca.tif"
## [5] "pendientevdc.html"
## [6] "pendientevdc.nb.html"
## [7] "pendientevdc.Rmd"
## [8] "pendientevdc_files"
## [9] "tabla.png"
## [10] "ValleDelCaucaDANE.gpkg"
(dem = terra::rast("COL_msk_alt.tif"))
## class : SpatRaster
## size : 2136, 1800, 1 (nrow, ncol, nlyr)
## resolution : 0.008333333, 0.008333333 (x, y)
## extent : -81.8, -66.8, -4.3, 13.5 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84
## source : COL_msk_alt.tif
## name : COL_msk_alt
## min value : -28
## max value : 5453
Es recomendable reducir la resolución del DEM para evitar problemas con la memoria del ordenador:
dem2 = terra::aggregate(dem,2, "mean")
## |---------|---------|---------|---------|=========================================
Leeremos nuestros municipios utilizando la librería del sf:
(munic <- sf::st_read("ValleDelCaucaDANE.gpkg"))
## Reading layer `mgn_anm_mpios' from data source
## `C:\Users\José Aguirre\Documents\GB2\DatosR\ValleDelCaucaDANE.gpkg'
## using driver `GPKG'
## Simple feature collection with 42 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -77.54977 ymin: 3.091239 xmax: -75.70724 ymax: 5.047394
## Geodetic CRS: MAGNA-SIRGAS
## Simple feature collection with 42 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: -77.54977 ymin: 3.091239 xmax: -75.70724 ymax: 5.047394
## Geodetic CRS: MAGNA-SIRGAS
## First 10 features:
## DPTO_CCDGO MPIO_CCDGO MPIO_CNMBR MPIO_CDPMP VERSION STCTNENCUE
## 1 76 001 CALI 76001 2018 749642
## 2 76 036 ANDALUCÍA 76036 2018 9439
## 3 76 041 ANSERMANUEVO 76041 2018 10533
## 4 76 054 ARGELIA 76054 2018 2900
## 5 76 111 GUADALAJARA DE BUGA 76111 2018 48459
## 6 76 113 BUGALAGRANDE 76113 2018 10610
## 7 76 122 CAICEDONIA 76122 2018 11841
## 8 76 126 CALIMA 76126 2018 11549
## 9 76 130 CANDELARIA 76130 2018 30849
## 10 76 147 CARTAGO 76147 2018 50848
## geom
## 1 MULTIPOLYGON (((-76.59175 3...
## 2 MULTIPOLYGON (((-76.22406 4...
## 3 MULTIPOLYGON (((-76.01558 4...
## 4 MULTIPOLYGON (((-76.14316 4...
## 5 MULTIPOLYGON (((-76.31608 3...
## 6 MULTIPOLYGON (((-76.15131 4...
## 7 MULTIPOLYGON (((-75.8539 4....
## 8 MULTIPOLYGON (((-76.51747 4...
## 9 MULTIPOLYGON (((-76.30455 3...
## 10 MULTIPOLYGON (((-75.94518 4...
Necesitamos que ambos conjuntos están en coordenadas geograficas que coincidan. Para esto usaremos el siguiente código:
(ValleDelCauca_crs = crs(munic))
## [1] "GEOGCRS[\"MAGNA-SIRGAS\",\n DATUM[\"Marco Geocentrico Nacional de Referencia\",\n ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"geodetic latitude (Lat)\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"geodetic longitude (Lon)\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n USAGE[\n SCOPE[\"Horizontal component of 3D system.\"],\n AREA[\"Colombia - onshore and offshore. Includes San Andres y Providencia, Malpelo Islands, Roncador Bank, Serrana Bank and Serranilla Bank.\"],\n BBOX[-4.23,-84.77,15.51,-66.87]],\n ID[\"EPSG\",4686]]"
Y lo atribuimos a nuestro “DEM”:
crs(dem2)
## [1] "GEOGCRS[\"WGS 84\",\n DATUM[\"unknown\",\n ELLIPSOID[\"WGS84\",6378137,298.257223563,\n LENGTHUNIT[\"metre\",1,\n ID[\"EPSG\",9001]]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433,\n ID[\"EPSG\",9122]]],\n CS[ellipsoidal,2],\n AXIS[\"latitude\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433,\n ID[\"EPSG\",9122]]],\n AXIS[\"longitude\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433,\n ID[\"EPSG\",9122]]]]"
Entonces tenemos que atribuir el sistema de coordenadas del Valle del Cauca a nuestro “DEM2
crs(dem2) <- ValleDelCauca_crs
Como se puede observar:
crs(dem2)
## [1] "GEOGCRS[\"MAGNA-SIRGAS\",\n DATUM[\"Marco Geocentrico Nacional de Referencia\",\n ELLIPSOID[\"GRS 1980\",6378137,298.257222101,\n LENGTHUNIT[\"metre\",1]]],\n PRIMEM[\"Greenwich\",0,\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n CS[ellipsoidal,2],\n AXIS[\"geodetic latitude (Lat)\",north,\n ORDER[1],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n AXIS[\"geodetic longitude (Lon)\",east,\n ORDER[2],\n ANGLEUNIT[\"degree\",0.0174532925199433]],\n USAGE[\n SCOPE[\"Horizontal component of 3D system.\"],\n AREA[\"Colombia - onshore and offshore. Includes San Andres y Providencia, Malpelo Islands, Roncador Bank, Serrana Bank and Serranilla Bank.\"],\n BBOX[-4.23,-84.77,15.51,-66.87]],\n ID[\"EPSG\",4686]]"
Ahora necesitamos recortar el objeto “dem2” a los limites de nuestro departamento
(dem3 = terra::crop(dem2,munic, mask=TRUE))
## class : SpatRaster
## size : 118, 111, 1 (nrow, ncol, nlyr)
## resolution : 0.01666667, 0.01666667 (x, y)
## extent : -77.55, -75.7, 3.083333, 5.05 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat MAGNA-SIRGAS (EPSG:4686)
## source(s) : memory
## name : COL_msk_alt
## min value : -1.25
## max value : 3940.00
Para el siguiente paso tenemos qur calcular los atributos del terreno. Para ello el DEM debe estar en coordenadas planas , por lo que tenemos que modificar los soguientes dos fragmentos de codigo para transformar los datos de entrada al sistema de coordenadas nacional de colombia.
Esta función reproyecta el DEM al sistema de cordenadas planas de colombia
dem_plane = project(dem3, "EPSG:9377")
También debemos asignar de manera similar para el objeto vectorial:
(munic_plane = sf::st_transform(munic, "EPSG:9377"))
## Simple feature collection with 42 features and 6 fields
## Geometry type: MULTIPOLYGON
## Dimension: XY
## Bounding box: xmin: 4494194 ymin: 1900273 xmax: 4699750 ymax: 2116536
## Projected CRS: MAGNA-SIRGAS 2018 / Origen-Nacional
## First 10 features:
## DPTO_CCDGO MPIO_CCDGO MPIO_CNMBR MPIO_CDPMP VERSION STCTNENCUE
## 1 76 001 CALI 76001 2018 749642
## 2 76 036 ANDALUCÍA 76036 2018 9439
## 3 76 041 ANSERMANUEVO 76041 2018 10533
## 4 76 054 ARGELIA 76054 2018 2900
## 5 76 111 GUADALAJARA DE BUGA 76111 2018 48459
## 6 76 113 BUGALAGRANDE 76113 2018 10610
## 7 76 122 CAICEDONIA 76122 2018 11841
## 8 76 126 CALIMA 76126 2018 11549
## 9 76 130 CANDELARIA 76130 2018 30849
## 10 76 147 CARTAGO 76147 2018 50848
## geom
## 1 MULTIPOLYGON (((4600987 195...
## 2 MULTIPOLYGON (((4642160 202...
## 3 MULTIPOLYGON (((4665634 209...
## 4 MULTIPOLYGON (((4651417 208...
## 5 MULTIPOLYGON (((4631835 199...
## 6 MULTIPOLYGON (((4650286 203...
## 7 MULTIPOLYGON (((4683364 204...
## 8 MULTIPOLYGON (((4609484 200...
## 9 MULTIPOLYGON (((4632900 194...
## 10 MULTIPOLYGON (((4673403 208...
Este paso requiere que calculemos atributos del terreno -específicamente pendiente (slope) y orientacion (aspect)- usando las funciones SLpasp del paquete MulticascaleDTM en R, con el siguiente código:
(slp_asp = MultiscaleDTM::SlpAsp(
dem_plane,
w = c(3, 3),
unit = "degrees",
method = "queen",
metrics = c("slope", "aspect"),
na.rm = TRUE,
include_scale = FALSE,
mask_aspect = TRUE
))
## class : SpatRaster
## size : 118, 112, 2 (nrow, ncol, nlyr)
## resolution : 1848.873, 1848.873 (x, y)
## extent : 4494097, 4701171, 1899617, 2117784 (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s) : memory
## names : slope, aspect
## min values : 0.007684549, 0.0725555
## max values : 20.357246604, 359.4038646
Una vez calculados los atributos del terreno, dividimos el “slp_asp” en pendiente y orientación
Capa -pendiente- 1:
(slope = subset(slp_asp, 1))
## class : SpatRaster
## size : 118, 112, 1 (nrow, ncol, nlyr)
## resolution : 1848.873, 1848.873 (x, y)
## extent : 4494097, 4701171, 1899617, 2117784 (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s) : memory
## name : slope
## min value : 0.007684549
## max value : 20.357246604
Miremos como se representa en una tabla la distribución de las pendientes:
terra::hist(slope,
main = "Pendiente Valle del Cauca",
xlab = "pendiente (en grados)")
(Explicación gráfica)
Capa 2 -orientación-:
(aspect =subset(slp_asp, 2))
## class : SpatRaster
## size : 118, 112, 1 (nrow, ncol, nlyr)
## resolution : 1848.873, 1848.873 (x, y)
## extent : 4494097, 4701171, 1899617, 2117784 (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s) : memory
## name : aspect
## min value : 0.0725555
## max value : 359.4038646
Miremos como se representa en una tabla la distribución de las pendientes:
terra::hist(aspect,
main = "Orientación Valle del Cauca",
xlab = "orientación (en grados)")
(Explicación gráfica)
Adicionalmente convertimos los grados de pendiente a porcentaje de pendiente:
(slope_perc = tan(slope*(pi/180))*100)
## class : SpatRaster
## size : 118, 112, 1 (nrow, ncol, nlyr)
## resolution : 1848.873, 1848.873 (x, y)
## extent : 4494097, 4701171, 1899617, 2117784 (xmin, xmax, ymin, ymax)
## coord. ref. : MAGNA-SIRGAS 2018 / Origen-Nacional (EPSG:9377)
## source(s) : memory
## name : slope
## min value : 0.01341207
## max value : 37.10475113
Miremos como se representa en una tabla la distribución de las pendientes:
terra::hist(slope_perc,
main = "Pendiente Valle del Cauca",
xlab = "pendiente (en porcentaje)")
Ahora tenemos que calcular el promedio de los valores de pendiente por municipio. Para ello veamos la clasificación de pendientes del IGAC para fines agronómicos:
knitr::include_graphics("tabla.png")
Explicación de tabla
m <- c(0, 3, 1,
3, 7, 2,
7, 12, 3,
12, 25, 4,
25, 50, 5,
50, 75, 6,
75, 160, 7)
m <- matrix(m, ncol=3, byrow = TRUE)
rc <- classify(slope_perc, m, right=TRUE)
Ahora vamos a computar las estadísticas zonales usando exactextractr:
(munic$mean_slope <- exactextractr::exact_extract(slope_perc, munic, 'mean'))
## | | | 0% | |== | 2% | |=== | 5% | |===== | 7% | |======= | 10% | |======== | 12% | |========== | 14% | |============ | 17% | |============= | 19% | |=============== | 21% | |================= | 24% | |================== | 26% | |==================== | 29% | |====================== | 31% | |======================= | 33% | |========================= | 36% | |=========================== | 38% | |============================ | 40% | |============================== | 43% | |================================ | 45% | |================================= | 48% | |=================================== | 50% | |===================================== | 52% | |====================================== | 55% | |======================================== | 57% | |========================================== | 60% | |=========================================== | 62% | |============================================= | 64% | |=============================================== | 67% | |================================================ | 69% | |================================================== | 71% | |==================================================== | 74% | |===================================================== | 76% | |======================================================= | 79% | |========================================================= | 81% | |========================================================== | 83% | |============================================================ | 86% | |============================================================== | 88% | |=============================================================== | 90% | |================================================================= | 93% | |=================================================================== | 95% | |==================================================================== | 98% | |======================================================================| 100%
## [1] 8.234748 2.735861 5.981479 4.842068 9.178998 3.604378 6.068478
## [8] 10.190221 0.269156 2.386823 12.163800 7.838280 8.935884 8.490119
## [15] 11.703223 12.169142 5.731778 2.972752 3.499377 6.909639 10.938899
## [22] 3.492452 9.220719 6.819207 6.108836 7.643911 7.920785 10.316816
## [29] 9.261460 2.744941 7.617874 6.259845 6.531541 7.808092 1.424047
## [36] 2.004853 6.017721 4.744247 7.055912 10.034364 9.837699 4.146656
hist(munic$mean_slope,
main = "Pendiente promedio por municipio en el Valle del Cauca",
xlab = "pendiente (en porcentaje)")
(munic$class <- exactextractr::exact_extract(rc, munic, 'mode'))
## | | | 0% | |== | 2% | |=== | 5% | |===== | 7% | |======= | 10% | |======== | 12% | |========== | 14% | |============ | 17% | |============= | 19% | |=============== | 21% | |================= | 24% | |================== | 26% | |==================== | 29% | |====================== | 31% | |======================= | 33% | |========================= | 36% | |=========================== | 38% | |============================ | 40% | |============================== | 43% | |================================ | 45% | |================================= | 48% | |=================================== | 50% | |===================================== | 52% | |====================================== | 55% | |======================================== | 57% | |========================================== | 60% | |=========================================== | 62% | |============================================= | 64% | |=============================================== | 67% | |================================================ | 69% | |================================================== | 71% | |==================================================== | 74% | |===================================================== | 76% | |======================================================= | 79% | |========================================================= | 81% | |========================================================== | 83% | |============================================================ | 86% | |============================================================== | 88% | |=============================================================== | 90% | |================================================================= | 93% | |=================================================================== | 95% | |==================================================================== | 98% | |======================================================================| 100%
## [1] 1 1 2 2 4 1 3 4 1 1 3 3 1 2 4 4 1 1 1 1 4 1 2 3 1 3 3 3 4 1 3 2 3 3 1 1 3 2
## [39] 1 3 3 1
hist(munic$class,
main = "Pendiente reclasificada del Valle del Cauca",
xlab = "Pendiente (como una categoria)")
Vamos a trasformar la pendiente a nuestras coordenadas:
(rc.geo = project(rc, "EPSG:4326"))
## class : SpatRaster
## size : 119, 112, 1 (nrow, ncol, nlyr)
## resolution : 0.01666619, 0.01666619 (x, y)
## extent : -77.56107, -75.69445, 3.077098, 5.060374 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## source(s) : memory
## name : slope
## min value : 1
## max value : 5
(slope.geo = project(slope_perc, "EPSG:4326"))
## class : SpatRaster
## size : 119, 112, 1 (nrow, ncol, nlyr)
## resolution : 0.01666619, 0.01666619 (x, y)
## extent : -77.56107, -75.69445, 3.077098, 5.060374 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## source(s) : memory
## name : slope
## min value : 0.04449286
## max value : 34.54376221
Primero necesitamos una paleta de colores para la pendiente:
palredgreen <- colorNumeric(c("darkseagreen3","yellow2", "orange", "brown2", "darkred"), values(slope.geo),
na.color = "transparent")
Ahora vamos a plotear. Ten presente tener el codigo correctamente:
leaflet(munic) %>% addTiles() %>% setView(-76.5, 3.8, 8) %>%
addPolygons(color = "gray", weight = 1.0, smoothFactor = 0.5,
opacity = 0.4, fillOpacity = 0.10,
popup = paste("Municipio: ", munic$MPIO_CNMBR, "<br>",
"Clase de Pendiente: ", munic$class, "<br>")) %>%
addRasterImage(slope.geo, colors = palredgreen, opacity = 0.8) %>%
addLegend(pal = palredgreen, values = values(slope.geo),
title = "Pendiente Valle del Cauca (%)")
## Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
## Need '+proj=longlat +datum=WGS84'
Visualizacion de pendiente
library(leaflet)
library(htmltools)
Paleta de relleno (igual que antes, si ya la tienes puedes reutilizarla)
pal_igac <- colorFactor(
palette = c("#d9f0a3","#addd8e","#78c679","#41ab5d","#238443","#006837","#004529"),
domain = munic$class
)
Contenido HTML del tooltip (bonito y claro)
labels <- sprintf("
<div class='ttcard'>
<div class='tt-title'>%s</div>
<div class='tt-row'>Pendiente promedio: <b>%.1f%%</b></div>
<div class='tt-row'>Clase IGAC: <span class='tt-pill tt-%s'>%s</span></div>
</div>",
munic$MPIO_CNMBR,
munic$mean_slope,
munic$class,
munic$class
) |> lapply(htmltools::HTML)
CSS para estilizar el tooltip (inyectado en el mapa)
tooltip_css <- htmltools::tags$style(htmltools::HTML("
.leaflet-tooltip.ttlabel {
background: #ffffff;
color: #111;
border: 1px solid #b5b5b5;
border-radius: 10px;
padding: 8px 10px;
box-shadow: 0 2px 8px rgba(0,0,0,0.25);
font-family: Arial, sans-serif;
font-size: 13px;
}
.leaflet-tooltip.ttlabel .tt-title {
font-weight: 700;
margin-bottom: 4px;
}
.leaflet-tooltip.ttlabel .tt-row {
margin: 2px 0;
}
.leaflet-tooltip.ttlabel .tt-pill {
display: inline-block;
padding: 2px 8px;
border-radius: 999px;
color: #fff;
font-weight: 600;
}
.leaflet-tooltip.ttlabel .tt-1 { background:#d9f0a3; color:#08306b; }
.leaflet-tooltip.ttlabel .tt-2 { background:#addd8e; color:#08306b; }
.leaflet-tooltip.ttlabel .tt-3 { background:#78c679; }
.leaflet-tooltip.ttlabel .tt-4 { background:#41ab5d; }
.leaflet-tooltip.ttlabel .tt-5 { background:#238443; }
.leaflet-tooltip.ttlabel .tt-6 { background:#006837; }
.leaflet-tooltip.ttlabel .tt-7 { background:#004529; }
"))
Mapa interactivo con tooltip estilizado (hover)
leaflet(munic) %>%
addProviderTiles(providers$Esri.WorldTopoMap) %>%
addControl(tooltip_css, position = "topleft") %>% # inyecta el CSS en el HTML
setView(lng = -76.5, lat = 3.8, zoom = 8) %>%
addPolygons(
fillColor = ~pal_igac(class),
color = "gray20", weight = 1, opacity = 0.6, fillOpacity = 0.85,
highlight = highlightOptions(weight = 3, color = "black", fillOpacity = 0.95, bringToFront = TRUE),
label = labels, # <- tooltip HTML bonito
labelOptions = labelOptions(
className = "ttlabel", # usa la clase CSS de arriba
direction = "auto",
sticky = TRUE, # el tooltip sigue al puntero
textsize = "13px",
opacity = 1
)
) %>%
addLegend(
pal = pal_igac,
values = munic$class,
title = "Clase de Pendiente IGAC",
opacity = 1
)
## Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
## Need '+proj=longlat +datum=WGS84'
Asegúrate de tener la capa aspect reproyectada a coordenadas geográficas
(aspect.geo <- project(aspect, "EPSG:4326"))
## class : SpatRaster
## size : 119, 112, 1 (nrow, ncol, nlyr)
## resolution : 0.01666619, 0.01666619 (x, y)
## extent : -77.56107, -75.69445, 3.077098, 5.060374 (xmin, xmax, ymin, ymax)
## coord. ref. : lon/lat WGS 84 (EPSG:4326)
## source(s) : memory
## name : aspect
## min value : 9.335389
## max value : 355.747528
Creamos una paleta circular de colores para mostrar direcciones (0–360°)
pal_aspect <- colorNumeric(
palette = c("blue", "cyan", "green", "yellow", "orange", "red", "purple", "blue"),
domain = values(aspect.geo),
na.color = "transparent"
)
Mapa interactivo del aspecto del terreno
leaflet() %>%
addProviderTiles(providers$CartoDB.Positron) %>%
setView(lng = -76.5, lat = 3.8, zoom = 8) %>%
addRasterImage(aspect.geo, colors = pal_aspect, opacity = 0.8) %>%
addPolygons(
data = munic,
color = "black", weight = 1,
opacity = 0.7, fillOpacity = 0,
popup = paste0("<b>Municipio:</b> ", munic$MPIO_CNMBR)
) %>%
addLegend(
pal = pal_aspect,
values = values(aspect.geo),
title = "Orientación (grados)",
opacity = 1
)
## Warning: sf layer has inconsistent datum (+proj=longlat +ellps=GRS80 +towgs84=0,0,0,0,0,0,0 +no_defs).
## Need '+proj=longlat +datum=WGS84'
original notebook, showing the creation of an elevation raster: Lizarazo, I., 2025. Elevation data processing and analysis in R. Available at https://rpubs.com/ials2un/otro_dem
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26100)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=Spanish_Colombia.utf8 LC_CTYPE=Spanish_Colombia.utf8
## [3] LC_MONETARY=Spanish_Colombia.utf8 LC_NUMERIC=C
## [5] LC_TIME=Spanish_Colombia.utf8
##
## time zone: America/Bogota
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] htmltools_0.5.8.1 exactextractr_0.10.0 MultiscaleDTM_1.0
## [4] terra_1.8-70 leaflet_2.2.3 sf_1.0-21
##
## loaded via a namespace (and not attached):
## [1] sass_0.4.10 generics_0.1.4 class_7.3-23
## [4] KernSmooth_2.23-26 lattice_0.22-7 digest_0.6.37
## [7] magrittr_2.0.4 rgl_1.3.24 RColorBrewer_1.1-3
## [10] evaluate_1.0.5 grid_4.5.1 fastmap_1.2.0
## [13] jsonlite_2.0.0 e1071_1.7-16 DBI_1.2.3
## [16] promises_1.5.0 scales_1.4.0 crosstalk_1.2.2
## [19] codetools_0.2-20 jquerylib_0.1.4 cli_3.6.5
## [22] shiny_1.11.1 rlang_1.1.6 units_1.0-0
## [25] base64enc_0.1-3 cachem_1.1.0 yaml_2.3.10
## [28] otel_0.2.0 tools_4.5.1 raster_3.6-32
## [31] dplyr_1.1.4 httpuv_1.6.16 png_0.1-8
## [34] vctrs_0.6.5 R6_2.6.1 mime_0.13
## [37] proxy_0.4-27 lifecycle_1.0.4 classInt_0.4-11
## [40] leaflet.providers_2.0.0 htmlwidgets_1.6.4 pkgconfig_2.0.3
## [43] bslib_0.9.0 pillar_1.11.1 later_1.4.4
## [46] glue_1.8.0 Rcpp_1.1.0 xfun_0.53
## [49] tibble_3.3.0 tidyselect_1.2.1 rstudioapi_0.17.1
## [52] knitr_1.50 farver_2.1.2 xtable_1.8-4
## [55] rmarkdown_2.30 compiler_4.5.1 sp_2.2-0
post scriptum: In case the error persists, that those easy answers are often hard to find. done by: +BVVR+