--- title: "Transects and cross-sections" output: rmarkdown::html_vignette vignette: > %\VignetteIndexEntry{Transects and cross-sections} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r, include = FALSE} knitr::opts_chunk$set(collapse = TRUE, comment = "#>", fig.width = 7, fig.height = 4) ``` ```{r setup, message = FALSE} library(blueterra) library(terra) ``` Transects turn a bathymetric raster into cross-sectional profiles. They are useful for showing terraces, escarpments, slope breaks, and cross-shelf gradients that are not always obvious from cell-by-cell terrain metrics. ## Data and Surface Orientation ```{r data} bathy <- read_bathy(blueterra_example("hitw")) rectangles <- terra::vect(blueterra_example("sampling_rectangles")) hitw_rect <- rectangles[rectangles$site_id == "hitw", ] prepared <- prepare_bathy( bathy, depth_range = c(-220, -25), smooth = TRUE ) estimate_surface_orientation(prepared, hitw_rect) ``` `estimate_surface_orientation()` converts local aspect into a representative bearing and a transect angle. Slope weighting emphasizes cells where orientation is better defined. Its `orientation_resultant_length` records aspect-vector concentration: values near one indicate a stable common direction, whereas values near zero indicate cancelling aspects and an unstable mean angle. ## Automatic Transect Orientation ```{r automatic} transects <- make_transects( hitw_rect, spacing = 75, bathy = prepared ) transects[, c( "transect_id", "angle_deg", "angle_source", "mean_aspect_deg", "orientation_resultant_length" )] ``` ```{r automatic-map, eval=requireNamespace("ggplot2", quietly = TRUE), fig.alt="Automatically oriented transects over hillshaded bathymetry."} plot_transects( prepared, transects, color_by = "transect_id", show_legend = FALSE, contour_interval = 25, title = "Terrain-Oriented Transects", subtitle = "Line angle estimated from local surface aspect" ) ``` Inspect the resultant length before treating an automatic angle as a useful surface-derived direction. A weak value calls for a manual angle or the bounding-box orientation rather than a precise interpretation of the estimated mean aspect. ## Manual Angle Override Manual angles remain useful when transects need to match survey design, a predefined grid, or a known field orientation. ```{r manual} manual_transects <- make_transects( hitw_rect, spacing = 75, angle = 45 ) manual_transects[, c("transect_id", "angle_deg", "angle_source")] ``` ## Sampling Cross-Sections `sample_transects()` extracts raster values at regular positions along each line. `extract_cross_sections()` is an alias for the same operation when the output is being used as a profile table. ```{r sample} samples <- sample_transects(transects, prepared, n = 12) sections <- extract_cross_sections(transects, prepared, n = 12) head(samples[, c("transect_id", "distance", "x", "y", "bathy_m")]) summarize_cross_sections(samples, value_col = "bathy_m") identical(names(samples), names(sections)) ``` ```{r cross-section-plot, eval=requireNamespace("ggplot2", quietly = TRUE), fig.alt="Bathymetric cross-sections with bathy_m on the y-axis."} plot_cross_sections( samples, value_col = "bathy_m", show_legend = TRUE, mean_profile = TRUE, mean_profile_na_rm = TRUE, normalize_distance = FALSE, profile_direction = "top_to_bottom", title = "Bathymetric Cross-Sections", subtitle = "Profiles read from shallow to deep terrain" ) ``` The value column is explicit. This matters because transect tables include numeric metadata such as `width_m`, `height_m`, `angle_deg`, and `offset`. The default profile direction places the top or shallow endpoint on the left and the bottom or deeper endpoint on the right. For negative-elevation bathymetry, that means profiles read from higher numeric values toward lower numeric values. Empty profile ends are trimmed and distance is reset to zero before plotting. The mean profile uses `mean_profile_na_rm = TRUE` by default, so it continues across the full available distance range instead of stopping where the shortest transect ends. ## Single-Transect Profile ```{r profile, eval=requireNamespace("ggplot2", quietly = TRUE), fig.alt="Bathymetric profile along a single transect."} one <- samples[samples$transect_id == samples$transect_id[1], ] plot_depth_profile( one, value_col = "bathy_m", profile_direction = "top_to_bottom", title = "Bathymetry Along One Transect" ) ``` ## Metric Profiles The same plotting functions work with derived metrics. When both bathymetry and a metric are sampled together, `plot_depth_profile()` can draw the metric value against bathymetric elevation, with depth or elevation on the y-axis. ```{r slope-profile, eval=requireNamespace("ggplot2", quietly = TRUE), fig.alt="Slope profile along one transect."} metrics <- derive_terrain(prepared, metrics = c("slope", "tri", "bpi")) metric_samples <- sample_transects( transects, c(prepared, metrics[["slope_deg"]]), n = 25 ) metric_one <- metric_samples[metric_samples$transect_id == metric_samples$transect_id[1], ] plot_depth_profile( metric_one, depth_col = "bathy_m", value_col = "slope_deg", profile_direction = "top_to_bottom", title = "Slope Along Depth" ) ``` In this layout, the x-axis is the terrain metric and the y-axis is the bathymetric or elevation coordinate. If only one value column is supplied, `plot_depth_profile()` falls back to the distance-profile layout.