Pattern

Pattern is the reusable container that sits between the flight-pattern generators and campaign/planning workflows.

  • Pattern generators such as racetrack() and spiral() return Pattern instances.

  • Line-based patterns store ordered FlightLine objects.

  • Waypoint-based patterns store ordered Waypoint objects.

  • compute_flight_plan() accepts Pattern objects directly and expands them into their underlying elements.

  • Campaign assigns stable pattern_id and line_id values when a pattern is added to a campaign.

Pattern class

class Pattern[source]

Bases: object

A named, parameterized pattern within a campaign.

Variables:
  • pattern_id – Stable identifier assigned by the owning Campaign. Empty string for patterns not yet added to a campaign.

  • kind – Generator kind (“rosette”, “racetrack”, “polygon”, “sawtooth”, “spiral”).

  • name – Human-readable name.

  • params – Generator parameters as a plain-JSON-compatible dict (lengths/altitudes in meters). Sufficient to regenerate.

  • lines – Ordered mapping of line_id -> FlightLine for line-based patterns. Empty for waypoint-based patterns.

  • waypoints – Ordered list of Waypoints for continuous patterns. Empty for line-based patterns.

kind: str
name: str
params: dict[str, Any]
pattern_id: str = ''
lines: dict[str, FlightLine]
waypoints: list[Waypoint]
property is_line_based: bool
property is_waypoint_based: bool
property line_ids: list[str]
elements()[source]

Return the ordered flight lines or waypoints for this pattern.

Return type:

list[FlightLine] | list[Waypoint]

property entry_waypoint: Waypoint

Waypoint where this pattern’s traversal begins.

For line-based patterns, this is the start of the first leg (self.lines[first_line_id].waypoint1). For waypoint-based patterns, this is the first element of self.waypoints.

Used by the flight-line optimizer to compute transit-in cost when scheduling this pattern in a sortie.

Raises:

HyPlanValueError – If the pattern has no elements (empty lines and empty waypoints).

property exit_waypoint: Waypoint

Waypoint where this pattern’s traversal ends.

For line-based patterns, this is the end of the last leg (self.lines[last_line_id].waypoint2). For waypoint-based patterns, this is the last element of self.waypoints.

Used by the flight-line optimizer to compute transit-out cost when scheduling this pattern in a sortie.

Raises:

HyPlanValueError – If the pattern has no elements (empty lines and empty waypoints).

replace_line(line_id, line)[source]

Replace a line in place, preserving its ID and pattern membership.

Return type:

None

Parameters:
to_dict()[source]

Serialize the pattern to a plain JSON-compatible dict.

Return type:

dict[str, Any]

classmethod from_dict(data)[source]

Reconstruct a Pattern from a dict produced by to_dict().

Return type:

Pattern

Parameters:

data (dict[str, Any])

to_geojson()[source]

Return a GeoJSON FeatureCollection of this pattern’s elements.

Line-based patterns yield one LineString feature per leg (with line_id and pattern_id in properties). Waypoint-based patterns yield one Point feature per waypoint plus one LineString for the connecting track.

Return type:

dict[str, Any]

regenerate(**overrides)[source]

Return a new Pattern by re-invoking the generator with params.

Keyword overrides are merged into params for the regeneration call. Overrides may use either the stored params spelling (radius_m=50_000) or the generator-style name with pint-aware units (radius=50 * ureg.km); unknown keys raise HyPlanValueError. The returned Pattern is not yet added to a campaign; use Campaign.replace_pattern() to swap it in.

Return type:

Pattern

Parameters:

overrides (Any)

translate(offset_north, offset_east)[source]

Return a new Pattern shifted by the given N/E offsets.

Every contained FlightLine and Waypoint is moved by the same geodetic N/E offset (delegating to each element’s existing offset_north_east method). The pattern’s stored center_lat / center_lon params are updated to match so a subsequent regenerate() produces the same geometry.

Parameters:
  • offset_north (Quantity | float) – Northward distance (negative for south). float is interpreted as metres; pass a pint Quantity for other units.

  • offset_east (Quantity | float) – Eastward distance (negative for west); same conventions as offset_north.

Return type:

Pattern

Returns:

A new Pattern at the translated position. The original is unchanged.

move_to(latitude, longitude)[source]

Return a new Pattern re-anchored at the given centre.

For built-in generator patterns (those whose params carry center_lat / center_lon), the new pattern is produced by regenerate() at the new centre — exact, regardless of displacement size. For ad-hoc patterns, computes the geodetic N/E delta from the pattern centroid to (latitude, longitude) and delegates to translate().

Parameters:
  • latitude (float) – New centre latitude in decimal degrees.

  • longitude (float) – New centre longitude in decimal degrees.

Return type:

Pattern

Returns:

A new Pattern centred on (latitude, longitude).

rotate(angle_deg, around=None)[source]

Return a new Pattern rotated by angle_deg (compass CW).

Each element is rotated about around (the pattern’s centre by default). Headings on every contained Waypoint and FlightLine are shifted by the same angle. params["heading"] is also shifted if present, so a subsequent regenerate() produces matching geometry.

Parameters:
  • angle_deg (float) – Clockwise rotation in degrees. rotate(360) is the identity; rotate(-90) rotates 90° CCW.

  • around (tuple[float, float] | None) – (latitude, longitude) pivot. None (default) rotates about the pattern’s current centre.

Return type:

Pattern

Returns:

A new rotated Pattern.

classmethod from_relative(anchor, *, bearing, distance, generator, **generator_kwargs)[source]

Build a pattern centred at a geodesic offset from an anchor.

Combines Waypoint.relative_to() with a pattern generator: computes the offset point from anchor along bearing for distance, then calls generator with that point as the center keyword. All other kwargs are forwarded to the generator unchanged.

Parameters:
  • anchor (Waypoint | tuple[float, float]) – A Waypoint or (latitude, longitude) tuple.

  • bearing (float) – Initial true bearing from anchor (compass deg).

  • distance (Quantity) – Geodesic distance as a pint Quantity with length units (matches Waypoint.relative_to(), which rejects bare numbers).

  • generator (Callable[..., Pattern]) – A pattern generator from hyplan.flight_patterns (e.g. racetrack, rosette, polygon, sawtooth, spiral).

  • **generator_kwargs (Any) – Forwarded to generator (e.g. heading, altitude, leg_length, n_legs).

Return type:

Pattern

Returns:

The Pattern produced by generator(center=offset, ...).

Example

>>> from hyplan.units import ureg
>>> from hyplan.flight_patterns import racetrack
>>> from hyplan.waypoint import Waypoint
>>> from hyplan.pattern import Pattern
>>> edw = Waypoint(34.92, -117.87, heading=0, name="EDW")
>>> pattern = Pattern.from_relative(
...     edw,
...     bearing=90,
...     distance=200 * ureg.nautical_mile,  # 200 nmi east
...     generator=racetrack,
...     heading=0,
...     altitude=35_000 * ureg.foot,
...     leg_length=10 * ureg.nautical_mile,
...     n_legs=5,
... )
__init__(kind, name, params, pattern_id='', lines=<factory>, waypoints=<factory>)
Parameters:
Return type:

None