Skip to contents

Constructs a central line of spots near the segment defined by endpoints `A` and `B`, then builds additional parallel lines on the left, right, or both sides by translating the segment along its left unit normal. After each line is built, its spots are removed from the remaining pool to avoid reuse.

Usage

build_similar_trajectories(
  df,
  A,
  B,
  top_n = 19,
  n_extra = 2,
  side = c("left", "right", "both"),
  lane_width_factor = 1.15,
  max_dist = NULL
)

Arguments

df

A data frame of candidate spots containing at least columns `x` and `y`. Additional columns are preserved.

A

A data frame with columns `x` and `y` defining endpoint A of the central segment. If it contains multiple rows, only the first row is used.

B

A data frame with columns `x` and `y` defining endpoint B of the central segment. If it contains multiple rows, only the first row is used.

top_n

Integer; number of closest spots to keep per line (default `19`). If `NULL`, no top-N truncation is applied in the underlying selection.

n_extra

Integer; number of additional lines to build on each requested side (default `2`). For example, `n_extra = 2` with `side = "both"` yields 1 center line + 2 left + 2 right.

side

Character; which side(s) to build relative to the vector \(A \rightarrow B\). One of `"left"`, `"right"`, or `"both"`.

lane_width_factor

Numeric scalar; multiplier applied to the estimated spot spacing to obtain the inter-line offset (default `1.15`).

max_dist

Numeric; if not `NULL`, only spots with distance to each (translated) segment `<= max_dist` are considered when building each line.

Value

A data frame containing all selected spots from all lines, stacked together, with additional columns `trajectory_id` (e.g., `"main"`, `"left_1"`, `"right_1"`) and `offset` (signed offset used for that line).

Details

The inter-line distance is computed as: $$w = lane\_width\_factor \cdot spacing$$ where `spacing` is the median nearest-neighbor distance estimated from `df`.

Lines are generated by shifting both endpoints `A` and `B` by `offset * n`, where `n` is the left unit normal of \(A \rightarrow B\). Positive offsets correspond to the left side; negative offsets correspond to the right side.

This function relies on helpers such as `estimate_spot_spacing()`, `unit_normal_left()`, `shift_point()`, `build_one_line()`, and `remove_used_points()`.

The implementation uses the base R pipe `|>` and `dplyr::mutate()` / `dplyr::bind_rows()`. Ensure `dplyr` is installed.

Examples

df <- data.frame(
  x = rep(1:10, each = 3),
  y = rep(1:3, times = 10),
  id = seq_len(30)
)
A <- data.frame(x = 1, y = 2)
B <- data.frame(x = 10, y = 2)

out <- build_similar_trajectories(df, A, B, top_n = 5, n_extra = 1, side =
"both")
head(out)
#>   x y id dist_to_seg pos_on_seg trajectory_id offset
#> 1 1 2  2        0.00  0.0000000          main   0.00
#> 2 2 2  5        0.00  0.1111111          main   0.00
#> 3 3 2  8        0.00  0.2222222          main   0.00
#> 4 4 2 11        0.00  0.3333333          main   0.00
#> 5 5 2 14        0.00  0.4444444          main   0.00
#> 6 1 3  3        0.15  0.0000000        left_1   1.15
unique(out$trajectory_id)
#> [1] "main"    "left_1"  "right_1"