# RoadLine

> Talos 0.6 · Since 0.6

A road's centre line, from `ctx.world.road(id)`.

Read-only. Positions are in the road entity's own frame (add the entity's transform for the world's). The engine builds it once per road, so calling `ctx.world.road(id)` again is cheap and returns the same object; keeping it from `init` is still fine. @example const road = ctx.world.road("circuit")! const here = road.closest(ctx.entity.position, ctx.state.s) // lap progress, off-road distance const ahead = road.at(here.s + 20) // a point to steer toward if (Math.abs(here.offset) > ahead.halfWidth) ctx.hud.prompt("road.off")

## Signature

```ts
export interface RoadLine {
  /** Metres once around a closed road, end to end on an open one. */
  readonly length: number
  /** True for a loop (a lap circuit), false for an open road; `at` wraps on a closed road and clamps on an open one. */
  readonly closed: boolean
  /** Width of the kerb strip outside each edge, metres; 0 for a road with no `kerb`. `halfWidth` does not include it. */
  readonly kerbWidth: number
  /** Height of the kerb strip, metres; 0 with no `kerb`. */
  readonly kerbHeight: number
  /** The wall the file asked for, or null for a road with no `barrier`. */
  readonly barrier: RoadBarrier | null
  /** The road's trigger gates, in order along it: the child entity's scene id (`ctx.world.find(id)`) and its distance along the road. Gate 0 is the start line. */
  readonly gates: readonly { readonly id: string; readonly s: number }[]
  /** The centre line at distance `s`. */
  at(s: number): RoadSample
  /**
   * The nearest point on the centre line to `pos`. With `hintS` only samples within `windowM` (default
   * 40 m) of it are searched, so a car asking every tick cannot jump to a crossing section of road.
   */
  closest(pos: Vec3, hintS?: number, windowM?: number): RoadClosest
  /**
   * Where the kerb and the wall stand at distance `s`, as lateral distances from the centre line. The wall
   * is `halfWidth + kerbWidth + offsetM` out: keep a car's centre inside `barrier.inner` minus its radius
   * and it stays on the road side of it.
   */
  edge(s: number): RoadEdge
  /** The centre line as points `stepM` apart (default the road's sample step): a minimap polyline. */
  polyline(stepM?: number): Vec3[]
}
```

Import: `import type { RoadLine } from "@argus/api"`

## Members

| Member | Signature | Description |
|---|---|---|
| `length` | `readonly length: number` | Metres once around a closed road, end to end on an open one. |
| `closed` | `readonly closed: boolean` | True for a loop (a lap circuit), false for an open road; `at` wraps on a closed road and clamps on an open one. |
| `kerbWidth` | `readonly kerbWidth: number` | Width of the kerb strip outside each edge, metres; 0 for a road with no `kerb`. `halfWidth` does not include it. |
| `kerbHeight` | `readonly kerbHeight: number` | Height of the kerb strip, metres; 0 with no `kerb`. |
| `barrier` | `readonly barrier: RoadBarrier \| null` | The wall the file asked for, or null for a road with no `barrier`. |
| `gates` | `readonly gates: readonly { readonly id: string; readonly s: number }[]` | The road's trigger gates, in order along it: the child entity's scene id (`ctx.world.find(id)`) and its distance along the road. Gate 0 is the start line. |
| `at` | `at(s: number): RoadSample` | The centre line at distance `s`. |
| `closest` | `closest(pos: Vec3, hintS?: number, windowM?: number): RoadClosest` | The nearest point on the centre line to `pos`. With `hintS` only samples within `windowM` (default 40 m) of it are searched, so a car asking every tick cannot jump to a crossing section of road. |
| `edge` | `edge(s: number): RoadEdge` | Where the kerb and the wall stand at distance `s`, as lateral distances from the centre line. The wall is `halfWidth + kerbWidth + offsetM` out: keep a car's centre inside `barrier.inner` minus its radius and it stays on the road side of it. |
| `polyline` | `polyline(stepM?: number): Vec3[]` | The centre line as points `stepM` apart (default the road's sample step): a minimap polyline. |

## Example

The tested fixture `fixtures/app/agent.ts`.

```ts
import type { Behavior } from "@argus/api"

// Sends a nav agent to `props.target` once, then reports arrival through ctx.state so the
// test can read it without polling the crowd directly.
export default {
  init(ctx) {
    ctx.state.arrived = false
    ctx.nav?.goTo(ctx.props.target as [number, number, number])
  },
  update(ctx) {
    if (ctx.nav?.arrived) ctx.state.arrived = true
  },
} satisfies Behavior
```
