Orthonormal Basis
Let \(\mathcal{H}\) be a Hilbert space with inner product \( \left<.,.\right>. \)
A family of vectors \(E = (e_i)_{i \in I} \subseteq \mathcal{H}\) is called an orthonormal system (ONS) if \(\left< e_i, e_j \right> = \delta_{ij}\) for all \(i,j \in I\). If the system spans the Hilbert space, \(\overline{\operatorname{span}(E)} = \mathcal{H}\), it is called an orthonormal basis (ONB).
Proposition.
An ONS \((e_k)_{k \in \mathbb{N}}\) is an ONB if and only if \[\sum_{k \in \mathbb{N}} \left< x, e_k \right> e_k = x\] for all \(x \in \mathcal{H}\) in \(\sqrt{\left<.,.\right>}\).
ONB on \(L^2([0, 2\pi], \mathbb{C}, \lambda)\)
The vector space \(L^2([0, 2\pi], \mathbb{C}, \lambda)\) contains all measurable functions from \([0, 2\pi]\) to \(\mathbb{C}\) with respect to the Lebesgue measure \(\lambda\) and the Borel sigma field. With the inner product \[\left< f, g \right> = \frac{1}{2\pi} \int_0^{2\pi} f(x) \overline{g(x)} d\lambda(x)\] it is a Hilbert space.
Proposition.
The set \(\{x \mapsto \exp(n i x) : n \in \mathbb{Z} \}\) is an ONB on \(L^2([0, 2\pi], \mathbb{C}, \lambda)\).
Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat.
So for a continuous 2d-curve \(f: [0, 2\pi] \to \mathbb{C}\) we can find coefficients \(c_n = \left< f, \exp(n i .)\right>\) such that \[f = \sum_{ n \in \mathbb{Z} } c_n \exp(n i .).\] But \(x \mapsto \exp(n i x) \) (\(n \neq 0\)) is a function that does \(n\) revolutions around the unit circle. Clockwise for negative and counterclockwise for positive \(n\). A complex coefficient only scales and rotates (changes the beginning) the circle.
This means we can find a center point \(c_0\) for the first circle, \(\{c_0 + c_1 \exp(i x): x \in [0, 2\pi] \} \). For a given timestep \(t \in [0, 2\pi]\) we choose the center point for the next circle as \(c_0 + c_1 \exp(i t)\), so we have \(\{c_0 + c_1 \exp(i t) + c_{-1} \exp(-i x)\}: x \in [0, 2\pi]\}\). We can continue in this fashion, using as many circles as we want and arrange them in arbitrary order. For the hello curve the order \(0, 1, -1, 2, -2, 3, -3, \dots\) was chosen.
Implementation
The integral can be readily approximated by the trapezoid rule for equally spaced atoms \[ \begin{align*} \int_D f(x) dx &\approx \sum_{i = 1}^T \frac{(t_{i+1} - t_i)(f(t_i) + f(t_{i+1}))}{2} \\ &\approx \Delta t \sum_{i = 1}^T f(t_i). \end{align*} \] To generate more points for a curve we can linearly interpolate.
The julia code is as simple as
T = length(points)
f = interpolate(points, Δt)
E = [exp(-2*π*im*n*t/T) for n in -depth:1:depth, t in 0:Δt:T]
return 1/length(f) * E * f
where we only have to be careful about the scaling and the interval sizes. (2*π*t/T ranges from \(0\) to \(2\pi\). The points of the curve are assumed to lie on \(0,1,\dots,T-1\) and are linearly interpolated on \([0,T]\) with stepsize Δt where the last point is the first one. As we integrate on \([0, 2\pi]\) we have the spacing of 2*π/(T/Δt) (\(\Delta t\) in above equation). 2*π cancels and T/Δt is the number of all interpolated points.)
Full code at my GitHub.