Creating Symmetry
Fourier
DigitalArt.Fourier — Module
FourierFourier constructions for symmetry patterns, following Farris Chapter 4.
General curve function μg
The general parameterised curve is a finite Fourier sum:
μg(t; cs, fs) = Σᵢ cs[i] · exp(im · fs[i] · t)where cs are complex coefficients and fs are integer frequencies. This is the core building block for all curve construction in the project.
Selective Fourier sums fkm
fkm(t, k, m) sums only those terms where the frequency index n satisfies n ≡ k (mod m). This selects a specific residue class of Fourier modes and is the mechanism Farris uses to enforce wallpaper symmetry groups.
fkm(t, k, m; M, as) = Σ_{n=−M}^{M, n%m==k} as[n+M+1] · exp(im · n · t)DigitalArt.Fourier.fkm — Method
fkm(t, k, m; M=5, as=ones(2M+1)) -> ComplexF64Selective Fourier sum retaining only frequencies n where n % m == k.
This construction is central to Farris' approach to wallpaper symmetry groups: by restricting which Fourier modes participate, specific rotational and reflective symmetries are enforced.
fkm(t, k, m) = Σ_{n=−M}^{M} as[n+M+1] · exp(im·n·t) [where n % m == k]Arguments:
t: real parameterk: residue class (integer)m: modulus (positive integer)M: half-bandwidth; frequencies range over−M:M(default 5)as: coefficient vector of length2M+1(default all ones)
Example — 5-fold symmetry, residue class 3:
M = 37
t = range(0, 2π, 1000)
vals = fkm.(t, 3, 5; M=M, as=ones(2M+1))DigitalArt.Fourier.μg — Method
μg(t; cs, fs) -> ComplexF64General Fourier curve: sum of rotating complex exponentials.
μg(t) = Σᵢ cs[i] · exp(im · fs[i] · t)Arguments:
t: real parameter (typically in[0, 2π])cs: vector of complex coefficientsfs: vector of integer frequencies (same length ascs)
Example:
t = range(0, 2π, 1000)
vals = μg.(t, cs=[1.0, 0.5, im/3], fs=[1, 6, -14])Symmetry
DigitalArt.Symmetry — Module
SymmetryRendering functions for rotational symmetry artwork.
Provides drawfunc for basic curve plotting and drawZθfunc4b for the core symmetry construction: drawing n rotated copies of a curve with a probabilistic color sequence.
The symmetry construction
Given a complex-valued curve func(t) and n evenly spaced rotation angles θ ∈ [0, 2π), each rotated copy is exp(im·θ) · func(t). Colors evolve via the mycolor state machine (see SymmetryColors).
The history array returned by drawZθfunc4b records (θ, color, cont) for each rotation, enabling replay or animation.
DigitalArt.Symmetry.drawZθfunc4b — Method
drawZθfunc4b(func, t, ic, cf, cfs; n=8) -> (Figure, history)Draw n rotationally symmetric copies of a complex-valued curve with evolving colors.
Arguments:
func: complex-valued function of a real parametertt: parameter range (e.g.range(0, 2π, 1000))ic: initial HSLA colorcf: color selector function (e.g.mycolorfromSymmetryColors)cfs: color configuration array passed tocfn: number of rotations (default 8)
The figure has a black background. Each rotation θ = 2πk/n produces a curve exp(im·θ) · func.(t) drawn in the current color. Color is updated each step via cf(cfs; pc=current_color, cont=cont_flag).
Returns:
Figure: the completed Makie figurehistory: vector of[θ, color, cont]for each rotation step
DigitalArt.Symmetry.drawfunc — Method
drawfunc(func, t; color=nothing) -> FigurePlot the complex-valued curve func evaluated at parameter values t.
The real and imaginary parts of func.(t) are used as x and y coordinates. If color is nothing, a random RGBA color is chosen.
Returns a Makie Figure.
SymmetryColors
DigitalArt.SymmetryColors — Module
SymmetryColorsColor generation and color state machine for symmetry artwork.
Provides randomised HSLA color generators for common color families, a perturbation function for smooth color variation, and a probabilistic state machine (mycolor) that drives the color evolution across rotational traces.
Color configuration arrays (cfs)
A cfs array is a Vector of (threshold, color_fn) pairs where thresholds are cumulative probabilities summing to 1. The first entry drives the "stay near current color" behaviour; subsequent entries are discrete jumps to new color families. Example:
cfs3 = [(0.80, rred), (0.82, ablack), (0.87, rgreen), (0.95, rblue), (1.0, awhite)]Preset named colors
chinese_red = HSLA(11, 0.70, 0.39, 1.0)
cadmium_orange = HSLA(28, 0.84, 0.55, 1.0)
naples = HSLA(48, 0.94, 0.67, 1.0)DigitalArt.SymmetryColors.ablack — Method
ablack() -> HSLASolid black.
DigitalArt.SymmetryColors.awhite — Method
awhite() -> HSLASolid white.
DigitalArt.SymmetryColors.color_from_color — Method
color_from_color(c; Δ=[0.1, 0.1, 0.1, 0.1]) -> HSLAReturn a new HSLA color near c by adding uniform random perturbations in [-Δ/2, Δ/2] to each of hue (H), saturation (S), lightness (L), and alpha (A). S, L, and A are clamped to [0, 1].
DigitalArt.SymmetryColors.mycolor — Method
mycolor(cfs; pc=nothing, cont=false) -> (HSLA, Bool)Probabilistic color selector with continuity tracking.
The state machine has two modes:
- Continuous (
cont=true): with probabilitycfs[1][1], slightly vary the previous colorpcviacolor_from_color. Returns(new_color, true). - Jump (
cont=falseor random draw exceeds first threshold): select a new color family from the remaining entries incfs. Returns(new_color, false).
Arguments:
cfs: vector of(threshold, color_fn)pairs; thresholds are cumulative probabilities in(0, 1]summing to 1.0. The first entry drives continuation.pc: previous color (used bycolor_from_colorwhen continuing).cont: whether we are currently in a continuous color run.
Returns a tuple (color, new_cont) where new_cont indicates whether the returned color begins or continues a run.
DigitalArt.SymmetryColors.rblue — Method
rblue() -> HSLARandom blue: hue 190–260°, high saturation, mid lightness.
DigitalArt.SymmetryColors.rgreen — Method
rgreen() -> HSLARandom green: hue 80–160°, high saturation, low-to-mid lightness.
DigitalArt.SymmetryColors.rorange — Method
rorange() -> HSLARandom orange: hue 26–32°.
DigitalArt.SymmetryColors.rred — Method
rred() -> HSLARandom red: hue –11–11° (wraps around 0°), mid saturation and lightness.
DigitalArt.SymmetryColors.ryellow — Method
ryellow() -> HSLARandom yellow: hue 45–58°, high saturation, mid-to-high lightness.