Bath_0tif<-'https://github.com/MiriamLL/data_supporting_webpage/raw/refs/heads/main/Blog/2025/Bathymetry/gebco_2024_n60.0_s50.0_w1.0_e9.0.tif'Contour lines
In this blog post, we’ll explore how to plot contour lines from a raster using bathymetry data as an example.
Intro
This months blog post is about how to create contour lines from a raster file, and how to add labels using the package shadowtext.
A contour line (also isoline, isopleth, isoquant or isarithm) of a function of two variables is a curve along which the function has a constant value, so that the curve joins points of equal value (Wikipedia).
In cartography, a contour line (often just called a “contour”) joins points of equal elevation (height) above a given level, such as mean sea level. A contour map is a map illustrated with contour lines, for example a topographic map, which thus shows valleys and hills, and the steepness or gentleness of slopes. The contour interval of a contour map is the difference in elevation between successive contour lines (Wikipedia).
Read
For the example, we will be using Bathymetry data. Bathymetry gives us information on the water depth around an area.
The data comes from: GEBCO: General Bathymetry Chart of the Oceans provides information from bathymetry in the ocean.
To download visit webpage. For more details and instructions on how to load bathymatry data in R go to my bathymetry post
Load the terra package for reading raster data.
library(terra)The function rast helps to read raster data, replacing package raster.
Bath_1raster<-rast(Bath_0tif)Crop
Keep a reduced area for making the calculations faster.
ext(Bath_1raster)
crop_extent <- ext(3, 9, 53, 56)
Bath_2cropped <- crop(Bath_1raster, crop_extent)
plot(Bath_2cropped)Contour lines.
Calculate contour lines. Since we are working with bathymetric data, and contour lines are often labeled with the prefix “iso-” based on the type of variable they represent, the lines derived from bathymetric data can specifically be referred to as isobaths.
Depth_range <- global(Bath_2cropped, fun = "range", na.rm = TRUE)
Depth_rangeContour_levels <- seq(0, -80, by = -5)Bath_3contours <- as.contour(Bath_2cropped, levels = Contour_levels)The resulting object class is “SpatVector”.
class(Bath_3contours)Check by plotting the data.
plot(Bath_2cropped, col = terrain.colors(100), main = "Bathymetry 5m Contours")
lines(Bath_3contours, col = "blue")Export the shapefile using the function writeVector.
writeVector(Bath_3contours, "Bathymetry_10m_contours.shp", overwrite = TRUE)The contour lines are also available to download here.
Plot
Load the package sf to transform from SpatVector to sf.
library(sf)From SpatVector to sf.
Bath_4lines <- st_as_sf(Bath_3contours)Load ggplot2 to use geom_sf.
library(ggplot2)Lines
Bath_5df <- as.data.frame(Bath_1raster, xy = TRUE)library(tidyverse)Bath_6sub <- Bath_5df %>%
filter(x > 2 & x < 10)%>%
filter(y > 52 & y < 57)%>%
rename(Bathymetry=3) %>%
filter(Bathymetry < 10)Bath_7centroids <- Bath_4lines %>%
group_by(level) %>%
summarise(geometry = st_centroid(st_union(geometry)))Bath_8plot<-ggplot() +
geom_raster(data = Bath_6sub , aes(x = x, y = y, fill = Bathymetry)) +
scale_fill_viridis_c(option = "mako")+
geom_sf(data = Bath_4lines, color = "grey", size = 0.3) +
geom_sf(data = GermanNorthSea::German_land , color='#ffffbe', fill='#ffffbe')+
geom_sf_text(data = Bath_7centroids, aes(label = -level),
inherit.aes = FALSE, size = 4, color = "white") +
theme_void() +
coord_sf(xlim = c(3.3,8.8),
ylim = c(53.2,55.8),
label_axes = list(left = "N", bottom = 'E'))+
theme(legend.position = 'none')
Bath_8plotShadows
To be able to better see the text use the package shadowtext.
library(shadowtext)Bath_7centroids_df <- cbind(Bath_7centroids, st_coordinates(Bath_7centroids))Bath_9plot<-Bath_8plot+geom_shadowtext(
data = Bath_7centroids_df,
aes(x = X, y = Y, label = -level), # label is -level to not show negative values
size = 4,
color = "black",
bg.color = "white", # white shadow
bg.r = 0.15, # radius of the shadow
inherit.aes = FALSE
)
Bath_9plot
Other options
library(scico)ggplot() +
geom_sf(data = Bath_4lines, aes(color = level), size = 0.3) +
scale_color_scico(palette = "imola", direction = 1) +
geom_sf(data = GermanNorthSea::German_land, color = 'grey', fill = 'grey') +
theme_bw() +
coord_sf(
xlim = c(3.3, 8.8),
ylim = c(53.2, 55.8),
label_axes = list(left = "N", bottom = 'E')) +
theme(legend.position = 'right') +
labs(color = "Depth (m)")