---
title: "Route"
description: "Waypoint-based waveguide route."
canonical_url: "https://www.rosette.dev/docs/api-reference/Route"
markdown_url: "https://www.rosette.dev/docs/api-reference/Route.md"
source_url: "https://github.com/PreFab-Photonics/rosette/blob/f086d7670645fd36c05362d696d442a2b2e74850/www/content/docs/api-reference/Route.mdx"
docs_channel: "main"
docs_revision: "f086d7670645fd36c05362d696d442a2b2e74850"
---

# Route

Waypoint-based waveguide route.

Import with `from rosette.routing import BendInfo, Route`.

Route connects an ordered sequence of waypoints with straight segments,
inserting bends at corners and interpolating width across each segment.
The corner shape is controlled by the `bend_profile` parameter: `"circular"`
(default) uses a constant-radius arc fillet, while `"euler"` uses a
clothoid (Cornu-spiral) fillet whose curvature varies linearly with arc
length. Lower-loss on high-index-contrast platforms, at the cost of a
longer fillet (roughly 2x the arc length of a circular bend with the
same peak curvature).

Route is **not** an auto-router. You must supply intermediate waypoints
to create the path shape you want.



> **Note: Waypoints create the shape**
>
> When connecting two ports, always add intermediate `(x, y)` waypoints
> so the route departs and arrives along each port's axis. Two ports alone
> produce a straight diagonal line between them, ignoring port directions.



```python
# Connecting two ports with an S-bend:
route = Route(Layer(1, 0), width=0.5, bend_radius=5.0)
route.start_at_port(port_a)                    # departs along port_a's axis
route.to(mid_x, port_a.position.y)             # horizontal segment out
route.to(mid_x, port_b.position.y)             # vertical transition
route.end_at_port(port_b)                      # arrives along port_b's axis
cell = route.to_cell("my_route")

# Manual waypoints:
route = Route(Layer(1, 0), width=0.5, bend_radius=5.0)
route.start_at(0, 0, angle=0)
route.to(50, 0)
route.to(50, 30)
route.end_at(100, 30, angle=0)
cell = route.to_cell("my_route")  # Returns Cell with .at()
```

## Attributes



### `path_length`

```python
path_length: float
```

Total optical path length.





### `warnings`

```python
warnings: list[str]
```

Warnings from route generation (e.g., auto-reduced bend radii).





### `bends`

```python
bends: list[BendInfo]
```

Typed diagnostics for bends generated by the route, including effective
radii, corner positions, and any automatic radius reductions. See
[`BendInfo`](/docs/api-reference/BendInfo).



## Methods



### `__init__`

```python
__init__(layer, width=0.5, bend_radius=5.0, bend_profile='circular') -> None
```

Create a new Route.



- **`layer`** (`Layer | int | tuple[int, int]`)

  The layer for the route geometry.





- **`width`** (`float`, default `0.5`)

  Default waveguide width.





- **`bend_radius`** (`float`, default `5.0`)

  Default bend radius. With `bend_profile="circular"` this is the constant
  arc radius of each corner. With `bend_profile="euler"` this is the
  *minimum* radius of curvature, reached at the midpoint of each corner.





- **`bend_profile`** (`Literal['circular', 'euler']`, default `'circular'`)

  Corner bend shape. `"circular"` (default) inserts a constant-radius arc
  fillet. `"euler"` inserts a clothoid (Cornu-spiral) fillet whose
  curvature varies linearly with arc length. Lower-loss on
  high-index-contrast platforms at the cost of a longer fillet.





**Returns:** `None`





### `start_at`

```python
start_at(x, y, angle=0.0) -> None
```

Start the route at a specific position and angle (degrees).



- **`x`** (`float`)

  X coordinate.





- **`y`** (`float`)

  Y coordinate.





- **`angle`** (`float`, default `0.0`)

  Departure angle in degrees (0 = +X direction).





**Returns:** `None`





### `start_at_port`

```python
start_at_port(port) -> None
```

Start the route at a port's position, heading into the port.

The port's outward-facing direction is flipped 180 degrees so the
route departs in the correct direction (away from the component).
The port's width is used as the starting width.

The first waypoint after this should continue along the port's axis
(e.g., same y for a horizontal port) before turning.



- **`port`** (`Port`)

  The port to start at.





**Returns:** `None`





### `to`

```python
to(x, y, width=None, bend_radius=None) -> None
```

Add a waypoint to the route.

The route draws a straight segment from the previous waypoint to
`(x, y)`, inserting a circular bend at the corner if the direction
changes. Provide intermediate waypoints to create L-bends and
S-bends. The router does not infer turns on its own.



- **`x`** (`float`)

  X coordinate of the waypoint.





- **`y`** (`float`)

  Y coordinate of the waypoint.





- **`width`** (`float | None`, default `None`)

  Override width at this waypoint. The width is interpolated across the
  full segment ending at this waypoint. Add a preceding waypoint to set
  where the transition starts.





- **`bend_radius`** (`float | None`, default `None`)

  Override bend radius at this corner.





**Returns:** `None`





### `end_at`

```python
end_at(x, y, angle=0.0) -> None
```

End the route at a specific position and angle (degrees).



- **`x`** (`float`)

  X coordinate.





- **`y`** (`float`)

  Y coordinate.





- **`angle`** (`float`, default `0.0`)

  Arrival angle in degrees.





**Returns:** `None`





### `end_at_port`

```python
end_at_port(port) -> None
```

End the route arriving into a port.

The port's outward-facing direction is flipped 180 degrees so the
route arrives heading into the component. The port's width is used
as the ending width.

The last waypoint before this should approach along the port's axis
(e.g., same y for a horizontal port) to ensure a flush connection.



- **`port`** (`Port`)

  The port to end at.





**Returns:** `None`





### `to_cell`

```python
to_cell(name) -> Cell
```

Convert the route to a geometry-only Cell.

Warnings are printed to stderr if the route had to auto-reduce bend radii
or encountered other issues. This provides immediate feedback to both
users and AI agents about potential design problems.

Path length, warnings, and bend diagnostics remain available on this `Route`.
Rosette also retains them privately alongside the generated cell for design
checks and `rosette-layout` JSON; they are not exposed as Cell metadata.



- **`name`** (`str`)

  Name for the generated cell.





**Returns:** `Cell`

A Cell containing the route geometry.





### `through`

```python
through(*waypoints, layer, width=0.5, bend_radius=5.0, bend_profile='circular') -> Route
```

Create a route through a series of waypoints (static method).

A convenience method that creates a Route, adds all waypoints, and
returns the result. You **must** include intermediate waypoints to
create turns. Two ports alone produce a straight diagonal line
regardless of port directions.

Port directions are used only for the first and last waypoint
(to set departure/arrival angle). Intermediate ports are treated
as plain `(x, y)` positions; their direction is ignored.



> **Example**
>
> ```python
> # S-bend between two component ports:
> route = Route.through(
>     port_a,                        # start at port_a, depart along its axis
>     (25, port_a.position.y),       # extend horizontally
>     (25, port_b.position.y),       # shift vertically
>     port_b,                        # arrive at port_b along its axis
>     layer=Layer(1, 0),
>     bend_radius=10.0,
> )
> cell = route.to_cell("my_route")
> ```





- **`*waypoints`** (`Port | Point | tuple[float, float] | tuple[float, float, float]`)

  Sequence of waypoints. Each can be a Port (position + width; direction
  used only if first/last), a Point (position only), an `(x, y)` tuple,
  or an `(x, y, angle)` tuple (for first/last waypoint).





- **`layer`** (`Layer | int | tuple[int, int]`)

  The layer for the route.





- **`width`** (`float`, default `0.5`)

  Default waveguide width.





- **`bend_radius`** (`float`, default `5.0`)

  Default bend radius.





- **`bend_profile`** (`Literal['circular', 'euler']`, default `'circular'`)

  Corner bend shape: `"circular"` (default) or `"euler"` (clothoid corner
  with linearly-varying curvature).





**Returns:** `Route`

A Route that can be converted to a Cell with `to_cell()`.