TerraLink in R: Quickstart

Overview

TerraLink helps you build habitat corridors between patches, using either raster or vector inputs.

Raster inputs are polygonized and analyzed through the vector corridor pipeline, matching the current QGIS plugin workflow.

The package is designed for scenario-based corridor planning:

  1. load habitat data
  2. choose the optimization mode that matches the ecological outcome you want
  3. set approximate planning constraints such as budget, corridor width, and search distance
  4. run several plausible scenarios
  5. compare the PRE/POST outputs and keep the scenario that best fits the planning goal

This is usually more useful than searching for a single “perfect” run, because different TerraLink modes reward different connectivity improvements.

The canonical TerraLink strategies are:

Choosing a strategy

The three canonical strategies are not just aliases:

As a rule of thumb:

You can list packaged example scripts with:

terralink_examples()

You can also locate packaged sample data with:

terralink_sample_data()

Built-in sample data

This package includes tiny sample files in inst/extdata so examples run immediately.

library(terralink)

paths <- terralink_sample_data()
paths
# paths["raster"]   -> habitat.tif
# paths["vector"]   -> patches.gpkg
# paths["obstacle"] -> impassable.gpkg

Raster workflow

library(terralink)

raster_result <- terralink_raster(
  raster = terralink_sample_data("raster"),
  patch_values = 1,
  obstacle_values = 2,
  budget = 220,
  min_patch_size = 10,
  min_corridor_width = 3,
  max_search_distance = 30,
  corridor_cell_assignment = "sum_total_network_area",
  units = "pixels"
)

raster_result$summary

Raster mode is useful for habitat grids and land-cover rasters. It can also use impassable values or ranges directly from the raster, which makes it a good fit for scenario testing with categorical land-cover maps.

In the current R package, raster inputs are funneled through the vector engine after raster-to-polygon conversion rather than using a separate raster-only backend.

Vector workflow

library(terralink)

vector_result <- terralink_vector(
  patches = terralink_sample_data("vector"),
  budget = 2.5,
  min_patch_size = 0.1,
  min_corridor_width = 20,
  max_search_distance = 500,
  units = "metric"
)

vector_result$summary

Vector mode is useful when habitat patches are already represented as polygons. It often gives cleaner patch-level geometry and is usually the better choice when your planning inputs are already polygon features rather than classified rasters.

Raster and vector runs can point in the same general direction without being numerically identical. The two pipelines use different spatial representations and corridor construction steps, so the safest interpretation is always scenario-vs-scenario within a single pipeline.

Barbados-style examples

These scripts use the raster/vector settings used during parity checks:

source(system.file("scripts", "example_raster_barbados.R", package = "terralink"))
source(system.file("scripts", "example_vector_barbados.R", package = "terralink"))

Obstacle-aware routing (optional)

For shortest-path corridors around impassable features, install:

install.packages(c("gdistance", "raster", "sp"))

Then use:

result <- terralink_vector(
  patches = terralink_sample_data("vector"),
  budget = 2.5,
  min_patch_size = 0.1,
  min_corridor_width = 20,
  max_search_distance = 500,
  units = "metric",
  obstacle_layers = terralink_sample_data("obstacle")
)

Understanding the result object

Every call to terralink_raster() or terralink_vector() returns a terralink_result object. Here is what is inside and how to access it:

result <- terralink_vector(
  patches = terralink_sample_data("vector"),
  budget = 2.5,
  min_patch_size = 0.1,
  min_corridor_width = 20,
  max_search_distance = 500,
  units = "metric"
)

# Quick overview (uses the print method)
result

# Selected corridors as an sf object
result$corridors

# Patches used in the analysis
result$patches

# Connected networks (one polygon per component)
result$networks

# Run summary: budget used, corridors selected, patches, strategy
result$summary

# PRE/POST connectivity metrics (named list)
result$metrics

# Human-readable metrics report
cat(result$metrics_report, sep = "\n")

# Strategy-specific optimization stats
result$strategy_stats

# Warnings and diagnostics
result$warnings
result$diagnostics

For raster mode, the result also contains:

Interpreting metrics

TerraLink computes PRE/POST metrics so you can measure the improvement that corridors provide. The key insight is: compare the change (POST minus PRE) across scenarios, not the absolute values.

Metric reference

Metric What it measures Higher is better? When to focus on it
Total Connected Habitat Area Habitat area in multi-patch networks Yes General structural connectivity
Largest Network Area Area of the biggest connected component Yes Consolidation into one backbone
Habitat Availability Dispersal-weighted reachable habitat Yes Species-specific accessibility
Mean Effective Resistance Average movement difficulty across the patch graph No (lower = better) Movement quality
Habitat-Normalized Mesh Effective mesh size / total habitat area Yes Fragmentation reduction
Largest Connected Component Proportion (LCC) Share of habitat in the largest network Yes Dominance of one network
Probability of Connectivity (PC) Area-weighted dispersal probability Yes Functional landscape connectivity
Flow Redundancy (IME or FRI) How many alternative routes exist Yes Route redundancy / resilience
Strategic Mobility Inverse detour ratio Yes Directness of travel
Landscape Fluidity Inverse mean path resistance Yes Overall ease of movement
Composite Connectivity Score Weighted blend of mesh, LCC, PC, flow Yes Single summary index

Which metrics match which strategy?

All strategies produce all metrics, so you can always see the trade-offs.

Practical interpretation rules

  1. Compare within the same pipeline (raster-to-raster or vector-to-vector). Cross-pipeline comparisons are valid directionally but not numerically exact.
  2. Compare PRE vs POST to quantify the marginal value of corridors.
  3. Compare scenarios (different strategies, budgets, or corridor widths) side by side.
  4. Look at diminishing returns: if doubling the budget barely moves the metrics, you have likely reached saturation.
  5. Avoid over-interpreting one run in isolation. Absolute metric values depend on landscape configuration, CRS, and parameter choices.

Comparing scenarios

The most effective way to use TerraLink is to run several scenarios and compare:

library(terralink)

patches_path <- terralink_sample_data("vector")

# Run three strategies with the same budget
strategies <- c("most_connected_networks", "largest_single_network", "landscape_fluidity")

results <- lapply(strategies, function(s) {
  terralink_vector(
    patches = patches_path,
    budget = 2.5,
    min_patch_size = 0.1,
    min_corridor_width = 20,
    max_search_distance = 500,
    strategy = s,
    units = "metric"
  )
})
names(results) <- strategies

# Build a comparison table
comparison <- data.frame(
  strategy = strategies,
  corridors = sapply(results, function(r) r$summary$corridors_used),
  budget_used = sapply(results, function(r) r$summary$budget_used),
  connected_area_post = sapply(results, function(r)
    r$metrics$total_connected_habitat_area_post),
  largest_network_post = sapply(results, function(r)
    r$metrics$largest_network_area_post),
  fluidity_post = sapply(results, function(r)
    r$metrics$landscape_fluidity_post),
  habitat_avail_post = sapply(results, function(r)
    r$metrics$habitat_availability_post)
)
print(comparison)

This table makes it easier to see which strategy aligns with which objective. In many landscapes, most_connected_networks tends to favor total connected area, largest_single_network tends to favor the dominant component, and landscape_fluidity tends to favor fluidity and mobility scores, but the actual ranking depends on landscape structure and parameter choices.

You can also compare budgets:

budgets <- c(1.0, 2.5, 5.0, 10.0)

budget_results <- lapply(budgets, function(b) {
  terralink_vector(
    patches = patches_path,
    budget = b,
    min_patch_size = 0.1,
    min_corridor_width = 20,
    max_search_distance = 500,
    units = "metric"
  )
})

budget_comparison <- data.frame(
  budget = budgets,
  corridors = sapply(budget_results, function(r) r$summary$corridors_used),
  connected_area = sapply(budget_results, function(r)
    r$metrics$total_connected_habitat_area_post),
  composite_score = sapply(budget_results, function(r)
    r$metrics$composite_connectivity_post)
)
print(budget_comparison)

Parameter selection guide

Budget

The budget is the total area available for corridor construction (hectares for metric, acres for imperial, pixels for raster pixel mode).

Minimum corridor width

Controls how wide each corridor is buffered.

Maximum search distance

The maximum gap between patch edges that TerraLink will try to bridge.

Minimum patch size

Drops patches smaller than this threshold before analysis.

Species dispersal distance

Used by habitat-availability metrics. Set this to the focal species’ typical natal dispersal or daily movement range.

Troubleshooting

No corridors generated

If result$summary$corridors_used is 0:

  1. Increase max_search_distance – patches may be farther apart than the current limit.
  2. Lower min_patch_size – small patches are being filtered out, leaving too few to connect.
  3. Increase budget – the cheapest available corridor may exceed the current budget.
  4. Check your data – make sure patch_values match actual raster cell values, or that the sf object has valid polygon geometry.

Check result$diagnostics for a message explaining why no corridors were selected.

Only one patch found

TerraLink needs at least two patches to build corridors. If your raster or vector input resolves to a single patch:

gdistance / obstacle errors

Obstacle-aware routing requires the gdistance, raster, and sp packages. If these are not installed and you pass obstacle_values or obstacle_layers, the behavior depends on obstacle_strategy:

Install the optional dependencies with:

install.packages(c("gdistance", "raster", "sp"))

Very large rasters

For rasters with more than 10 million cells, set allow_large = TRUE. You may also want to reduce max_pair_checks or max_candidates to keep memory usage manageable.

Unexpected metric values

Glossary

Term Definition
Corridor A strip of habitat connecting two patches, allowing species movement between them.
Patch A contiguous area of habitat. In raster mode, a group of connected habitat cells; in vector mode, a polygon feature.
Network / Component A group of patches linked by corridors into a single connected unit.
Budget The total area available for new corridor construction (hectares, acres, or pixels).
Effective resistance A measure of how difficult it is to move between two patches through the corridor network, based on circuit theory. Lower values mean easier movement.
Habitat availability The amount of habitat reachable from a given patch, weighted by the probability of dispersal (which decays with distance).
Dispersal kernel A function describing how the probability of an organism reaching a destination decreases with distance. TerraLink uses an exponential kernel.
Landscape fluidity The inverse of mean path resistance across the patch graph. Higher fluidity means the landscape is easier to traverse overall.
Flow redundancy A measure of how many alternative routes exist between patches. Higher redundancy means the network is more resilient to local disruptions.
Probability of connectivity (PC) An index combining patch area and inter-patch dispersal probability into a single measure of landscape connectivity.
Effective mesh size A fragmentation metric: the probability that two randomly chosen points in the habitat fall within the same connected component. Normalized by total habitat area in TerraLink.
LCC (Largest Connected Component) The proportion of total habitat area captured by the single largest network.
Strategic mobility The inverse of the mean detour ratio across the patch graph. Higher values mean more direct travel routes.
Composite connectivity score A user-configurable weighted blend of mesh, LCC, PC, and flow redundancy into a single index.
PRE / POST PRE = metric value with patches only (no corridors). POST = metric value after adding the selected corridors. The difference measures the improvement from corridors.
IME Inverse Mean Effective-resistance. A flow redundancy method based on circuit theory.
FRI Flow Redundancy Index. An alternative flow redundancy calculation.