Polygon & Circular#
Polygon and circular geometric structures.
Phase 2 implements the basic ratio-driven shapes. Phase 4 adds the
biotuner-metric-driven variants: interval_vector_diagram,
polygon_chord_pattern, and consonance_polygon.
- star_polygon(n: int, k: int, radius: float = 1.0) GeometryData[source]#
Schläfli star polygon
{n/k}.Vertices are placed on a circle of given
radius. Edges connect vertexito vertex(i + k) mod n. Whengcd(n, k) > 1the figure decomposes intogcd(n, k)disjoint compound polygons; the return type is thenpolygon_set.- Parameters:
n (int) – Number of vertices on the circle,
n >= 3.k (int) – Step size,
1 <= k < n.radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='polygon'whengcd(n, k) == 1geom_type='polygon_set'whengcd(n, k) > 1
- times_table_circle(n_points: int, multiplier: float, radius: float = 1.0) GeometryData[source]#
Modular-multiplication “times-table” pattern on a circle.
n_pointspoints are placed evenly on a circle of givenradius. For eachi ∈ [0, n_points), an edge is drawn fromitoint(round(i * multiplier)) mod n_points. Self-loops (the i==j case) are dropped.- Parameters:
n_points (int, must be >= 2)
multiplier (float) – Modular multiplier. Integer multipliers produce the classic Mardi-Gras patterns; non-integer values produce richer textures.
radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='graph'.
- times_table_from_input(input: HarmonicInput, n_points: int = 360, mode: str = 'ratio', radius: float = 1.0) GeometryData[source]#
Chord-driven times-table: one edge family per harmonic ratio.
Each component of
inputcontributes its own multiplier; all edge families share the samen_points-vertex circle and are returned in a singleGeometryDataso they can be drawn as overlaid colour layers.- Parameters:
input (HarmonicInput)
n_points (int, default=360) – Number of points on the circle. 360 is a convenient default because most rational chord ratios give clean modular periods.
mode ({‘ratio’, ‘pitch_class’, ‘integer’}, default=’ratio’) – How each ratio is converted into a multiplier:
'ratio'— multiplier =ratio(float).i → int(round(i * ratio)) mod n_points.'pitch_class'— multiplier =round(n_points * log2(ratio)). One “octave” wraps the circle once.'integer'— multiplier =Fraction(ratio).limit_denominator(32).numerator.
radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='graph'.edgescarries every edge across all ratio families;metadata['ratio_index']is an int array aligned withedgesmapping each edge to the originating ratio index (so a renderer can colour each family separately).metadata['multipliers']lists the resolved multiplier per ratio.
- tuning_circle(input: HarmonicInput, radius: float = 1.0) GeometryData[source]#
Place input components on a circle by their log-equave pitch class.
For each ratio
r, the angle is2π · log_equave(r), wrapped into[0, 2π). Amplitudes are exposed as per-point weights.- Parameters:
input (HarmonicInput)
radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='point_cloud_2d'with shape(n_components, 2)andweightsof lengthn_components.
- rose_curve(ratio: Fraction | int | float | Tuple[int, int], n_points: int = 2000, n_periods: int | None = None, radius: float = 1.0) GeometryData[source]#
Polar rose:
r(θ) = radius · cos((p/q) · θ).For coprime
(p, q), the curve closes after: -θ ∈ [0, q · π]ifp + qis even, -θ ∈ [0, 2 · q · π]ifp + qis odd.If
n_periodsis given, the curve is sampled over[0, n_periods · π]explicitly; otherwise the closure-aware default above is used.- Parameters:
ratio (Fraction, int, float, or (int, int))
n_points (int, default=2000)
n_periods (int, optional) – Override the auto-computed sampling range (in units of π).
radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='curve_2d'.
- epicycloid(ratio: Fraction | int | float | Tuple[int, int], R: float = 1.0, n_points: int = 2000) GeometryData[source]#
Epicycloid traced by a point on a small circle rolling outside a large one.
With
ratio = R / r = p / q(coprime), the curve haspcusps and closes after the small circle completesqrevolutions.- Parameters:
ratio (Fraction, int, float, or (int, int)) – Ratio of fixed circle radius to rolling circle radius,
R / r.R (float, default=1.0) – Radius of the fixed (large) circle.
n_points (int, default=2000)
- Returns:
GeometryData –
geom_type='curve_2d'.
- hypocycloid(ratio: Fraction | int | float | Tuple[int, int], R: float = 1.0, n_points: int = 2000) GeometryData[source]#
Hypocycloid traced by a point on a small circle rolling inside a large one.
With
ratio = R / r = p / q(coprime,p > q), the curve hasp - qcusps. Forp = qthe trace is a degenerate point.- Parameters:
ratio (Fraction, int, float, or (int, int)) –
R / r. Must satisfyR > r > 0for a non-degenerate curve; i.e., the coprime form must havep > q.R (float, default=1.0)
n_points (int, default=2000)
- Returns:
GeometryData –
geom_type='curve_2d'.
- interval_vector_diagram(input: HarmonicInput, radius: float = 1.0, bin_cents: float = 50.0) GeometryData[source]#
Graph of pairwise intervals binned into cents-classes.
Nodes are placed on the tuning circle. For each pair
(i, j), the interval in cents is computed (modulo equave). Intervals are bucketed inbin_cents-wide classes; an edge’s weight is the interval-class count — how many other pairs share that bucket. Edges thus highlight the chord’s interval-vector multiplicities.- Parameters:
input (HarmonicInput)
radius (float, default=1.0)
bin_cents (float, default=50.0) – Bucket width for grouping intervals into classes.
- Returns:
GeometryData –
geom_type='graph'withedgesof shape(E, 2)and per-edgeweights.
- polygon_chord_pattern(input: HarmonicInput, metric: str | Callable[[float], float] = 'dyad_similarity', threshold: float | None = None, radius: float = 1.0) GeometryData[source]#
Chord-pattern graph weighted by a biotuner harmonicity metric.
Nodes are placed on the tuning circle. Every pair of distinct components has an edge weighted by
metric(ratio_j / ratio_i)(after rebounding the quotient into[1, ∞)). Optionally threshold to keep only the strongest pairs — yields the polygonal “chord skeleton” of the most consonant relationships.- Parameters:
input (HarmonicInput)
metric (str or callable, default=’dyad_similarity’) – Either a single-ratio biotuner metric name (one of
'dyad_similarity','compute_consonance','tenneyHeight','log_distance') or a callableratio -> score.tenneyHeightis sign-flipped so higher always means “more consonant” downstream.threshold (float, optional) – Drop edges with weight below
threshold.Nonekeeps all.radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='graph'.
- consonance_polygon(input: HarmonicInput, metric: str | Callable[[float], float] = 'dyad_similarity', radius: float = 1.0) GeometryData[source]#
Convex polygon whose vertex angles encode each ratio’s consonance share.
Each component’s “consonance share” is the sum of pairwise
metricscores against all other components. Vertices are then placed at cumulative-angle positions: the polygon’s angular density spikes around the most-connected ratios and thins around outliers.- Parameters:
input (HarmonicInput)
metric (str or callable, default=’dyad_similarity’)
radius (float, default=1.0)
- Returns:
GeometryData –
geom_type='polygon'withweightscarrying the per-vertex consonance share. The first vertex is placed at angle 0.