Lissajous#

Lissajous-curve geometry.

Standard 2-D form: x(t) = A_x · sin(a · t + δ), y(t) = A_y · sin(b · t).

For coprime integer frequency ratios (a, b) and arbitrary phase δ, the curve closes after t [0, 2π]. A pairwise-coprime triple (a, b, c) applied to the three Cartesian axes yields a Lissajous knot.

References

lissajous_2d(ratio: Fraction | int | float | Tuple[int, int], phase: float = 1.5707963267948966, amps: Tuple[float, float] = (1.0, 1.0), n_points: int = 1000, n_periods: int = 1) GeometryData[source]#

A single 2-D Lissajous curve.

Samples x(t) = A_x · sin(a · t + phase) and y(t) = A_y · sin(b · t) over t [0, · n_periods], where (a, b) is a coprime representation of ratio.

Parameters:
  • ratio (Fraction, int, float, or (int, int)) – Frequency ratio a / b of the x-component to the y-component.

  • phase (float, default=π/2) – Phase shift δ in radians applied to the x-component.

  • amps (tuple of float, default=(1.0, 1.0)) – Amplitudes (A_x, A_y).

  • n_points (int, default=1000) – Number of samples along the curve.

  • n_periods (int, default=1) – Number of fundamental periods to sample. For coprime (a, b) the curve closes after one period.

Returns:

GeometryDatageom_type='curve_2d' with shape (n_points, 2). Metadata includes the coprime (a, b) pair, closure flag, and phase.

lissajous_3d(ratios: Sequence[Fraction | int | float | Tuple[int, int]], phases: Sequence[float] = (0.0, 0.0, 0.0), amps: Sequence[float] = (1.0, 1.0, 1.0), n_points: int = 2000) GeometryData[source]#

A 3-D Lissajous curve.

Samples x_i(t) = A_i · sin(f_i · t + φ_i) for i {0, 1, 2}, where f_i is a coprime integer derived from ratios[i].

When all three f_i are pairwise coprime the resulting curve is a Lissajous knot; this is flagged in metadata['knot'].

Parameters:
  • ratios (sequence of length 3) – Frequencies for x, y, z.

  • phases (sequence of length 3, default=(0, 0, 0)) – Phase per axis in radians.

  • amps (sequence of length 3, default=(1, 1, 1)) – Amplitude per axis.

  • n_points (int, default=2000)

Returns:

GeometryDatageom_type='curve_3d' with shape (n_points, 3).

lissajous_pairwise_grid(input: HarmonicInput, n_points: int = 500, phase: float = 1.5707963267948966) List[List[GeometryData]][source]#

Build a 2-D grid of pairwise Lissajous curves from a HarmonicInput.

For an input with N components, returns an N×N nested list where entry [i][j] is the 2-D Lissajous of component i (x-axis) against component j (y-axis). The diagonal contains 1:1 unison curves.

Parameters:
  • input (HarmonicInput)

  • n_points (int, default=500)

  • phase (float, default=π/2)

Returns:

list of list of GeometryDataN × N matrix of curve_2d geometries.

lissajous_compound(input: HarmonicInput, n_points: int = 2000, n_periods: int = 1) GeometryData[source]#

Sum-of-sinusoids Lissajous from a HarmonicInput.

Treats the input components as a chord. The x-coordinate is the sum of all components phase-shifted by π/2; the y-coordinate is the sum without the phase shift. This collapses an N-component HarmonicInput into a single 2-D Lissajous-like curve.

Parameters:
  • input (HarmonicInput)

  • n_points (int, default=2000)

  • n_periods (int, default=1)

Returns:

GeometryDatageom_type='curve_2d'.

lissajous_phase_drift(ratio: Fraction | int | float | Tuple[int, int], drift_rate: float, duration: float, sr: int = 1000, amps: Tuple[float, float] = (1.0, 1.0)) GeometryData[source]#

Lissajous with a linearly-drifting phase.

The phase δ(t) = drift_rate · t evolves linearly with time, producing the classic “spinning” Lissajous animation when rendered.

Parameters:
  • ratio (Fraction, int, float, or (int, int))

  • drift_rate (float) – Phase drift in radians per second.

  • duration (float) – Total duration in seconds.

  • sr (int, default=1000) – Sample rate (samples per second).

  • amps (tuple of float, default=(1.0, 1.0))

Returns:

GeometryDatageom_type='curve_2d' with shape (int(sr * duration), 2).

lissajous_topology(geom: GeometryData) dict[source]#

Inspect a Lissajous-style curve_2d and return topological summary.

Parameters:

geom (GeometryData) – Must have geom_type='curve_2d'.

Returns:

dict – Keys:

  • 'lobes_x', 'lobes_y' — integer lobe counts (read from metadata when available; otherwise estimated by counting zero crossings on each axis).

  • 'closed' — whether the first and last points coincide within a small tolerance.

  • 'self_intersections' — count of polyline self-intersections (brute-force, O(N²)).

  • 'period_ratio'Fraction representing the a / b ratio when known, else None.