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:
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:
most_connected_networkslargest_single_networklandscape_fluidityThe three canonical strategies are not just aliases:
largest_single_network: favors one dominant connected
backbonemost_connected_networks: favors broad structural
connected area across the landscapelandscape_fluidity: favors easier movement, route
shortening, and reduced bottlenecksAs a rule of thumb:
most_connected_networks for structural
integrationlargest_single_network for consolidationlandscape_fluidity for movement quality and
redundancyYou can list packaged example scripts with:
You can also locate packaged sample data with:
This package includes tiny sample files in inst/extdata
so examples run immediately.
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$summaryRaster 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.
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$summaryVector 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.
These scripts use the raster/vector settings used during parity checks:
For shortest-path corridors around impassable features, install:
Then use:
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$diagnosticsFor raster mode, the result also contains:
result$corridor_raster – SpatRaster where corridor
cells carry values according to
corridor_cell_assignmentresult$contiguous_raster – SpatRaster labeling each
contiguous patch-corridor networkresult$patch_table – data frame of patch attributes
(id, area, centroid)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 | 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 |
most_connected_networks aims to
improve Total Connected Habitat Area and Meshlargest_single_network aims to improve
Largest Network Area and LCClandscape_fluidity aims to improve
Landscape Fluidity, Strategic Mobility, and Flow RedundancyAll strategies produce all metrics, so you can always see the trade-offs.
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)The budget is the total area available for corridor construction (hectares for metric, acres for imperial, pixels for raster pixel mode).
Controls how wide each corridor is buffered.
The maximum gap between patch edges that TerraLink will try to bridge.
Drops patches smaller than this threshold before analysis.
Used by habitat-availability metrics. Set this to the focal species’ typical natal dispersal or daily movement range.
max_search_distance is used as a rough
proxy.If result$summary$corridors_used is 0:
max_search_distance – patches
may be farther apart than the current limit.min_patch_size – small patches
are being filtered out, leaving too few to connect.budget – the cheapest
available corridor may exceed the current budget.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.
TerraLink needs at least two patches to build corridors. If your raster or vector input resolves to a single patch:
min_patch_size so that smaller fragments are
retained.patch_connectivity (raster mode): switching from
8 to 4 may split one large patch into separate pieces.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:
"error" (default): stops with a clear error telling you
to install the packages."straight_line": falls back to straight-line corridors
(obstacles are ignored)."disable_obstacles": silently drops obstacle data.Install the optional dependencies with:
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.
| 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. |