designcoding
Search
About Table of Contents Keywords Support designcoding!

Discrete Fourier Transform

May 8, 2025 | 3,493 views
Algorithms
epicycles | fourier | grasshopper | python

The Fourier Transform is a powerful mathematical technique that allows us to analyze the different frequency components within a signal or shape. Its discrete version, the Discrete Fourier Transform (DFT), is used when working with numerical data. I studied the Fourier Series here before. One of the most fascinating aspects of the DFT is that it can represent a signal or shape using rotating circles (or vectors). Each circle corresponds to a specific frequency, amplitude, and phase. When connected in sequence, these circles collectively recreate the original shape over time. With this approach, we can reconstruct even a complex curve using simple harmonic motion. As usual, I chose my website’s logo as the testing curve. Below is the result:

discrete fourier transform

For example, consider a closed curve. If we sample this curve into a list of points and represent each as a complex number (like x + iy), we can apply the DFT to extract the frequency components. 3Blue1Brown, Mathologer, and the Coding Train have beautiful videos on the math behind the DFT. I watch them with pure interest and excitement. The result of the DFT algorithm is a series of rotating vectors, each spinning at a specific rate. The tips of these vectors trace out the original shape as time progresses. The resulting animations are usually beautiful and deeply intuitive. Below is the Grasshopper definition and the Python code that calculates the rotating circles. It is a Python 3 component, so it may only run in Rhino 8. Below is the content of the Grasshopper Python component:

import cmath, math, Rhino
count = 200
points = [curve.PointAtNormalizedLength(i / float(count)) for i in range(count)]
samples = [complex(p.X, p.Y) for p in points]
def dft(signal, num_terms):
    N = len(signal)
    result = []
    for k in range(-num_terms//2, num_terms//2):
        c = complex(0, 0)
        for n in range(N):
            angle = -2 * math.pi * k * n / N
            c += signal[n] * cmath.exp(complex(0, angle))
        c /= N
        result.append((k, c))
    return result
fourier = dft(samples, N)
def epicycles(fourier, t):
    x, y = 0.0, 0.0
    vectors = []
    for freq, coef in sorted(fourier, key=lambda x: abs(x[1]), reverse=True):
        radius = abs(coef)
        phase = cmath.phase(coef)
        angle = 2 * math.pi * freq * t + phase
        dx = radius * math.cos(angle)
        dy = radius * math.sin(angle)
        start = complex(x, y)
        end = start + complex(dx, dy)
        vectors.append((start, end, radius))
        x, y = end.real, end.imag
    return vectors, complex(x, y)
vectors, tip = epicycles(fourier, t)
circles = []
lines = []
for start, end, radius in vectors:
    center = Rhino.Geometry.Point3d(start.real, start.imag, 0)
    endpoint = Rhino.Geometry.Point3d(end.real, end.imag, 0)
    circle = Rhino.Geometry.Circle(center, radius)
    line = Rhino.Geometry.Line(center, endpoint)
    circles.append(circle)
    lines.append(line)
tip_point = Rhino.Geometry.Point3d(tip.real, tip.imag, 0)
discrete fourier transform
discrete fourier transform
Discrete Fourier Transform Grasshopper definition with Python componentDownload

Related Posts

Scary Patterns

August 6, 2026

While digging through my archives, I found an old animation I made in 2023. Back then, I was generating patterns with Parakeet. Thanks to this talented add-on, I managed to create a nice pattern by dressing a different component onto a Snub Square tiling base….

Dual Polyhedra in Grasshopper

October 7, 2025

Exploring dual polyhedra in Grasshopper is an interesting topic. In this post, I try to generate the dual of any polyhedron using Rhino Python and possibly Grasshopper. I developed this code for Rhino Python earlier here, and now I have converted it into a Grasshopper-Python…

String Art in Rhino Python

June 19, 2025

String art is a captivating technique that combines geometry and aesthetics to recreate images using lines between pins. Here is a good reference to start studying it. In this post, I explored a custom Rhino Python script designed for Rhinoceros 7 and 8. It transforms…

Differential Growth

June 16, 2025

Differential growth is a process where different parts of a structure grow at different rates, leading to complex forms. After watching this, I decided to try it in Grasshopper. Here, differential growth mimics this behavior by applying rules such as Repulsion to avoid crowding or…

Socolar Tiling

May 10, 2025

An aperiodic tiling is a pattern that covers the plane without ever repeating itself (i.e., it is non-periodic). A few special shapes, arranged according to specific rules, can cover the entire plane, but the resulting pattern never repeats exactly. I challenged myself on a 3-day…

  • Search

  • Categories

    • Algorithms
    • Discourses
    • Fabrications
    • Studios
  • Monthly Archive

    • August 2026 (5)
    • October 2025 (1)
    • June 2025 (2)
    • May 2025 (2)
    • April 2025 (5)
    • December 2024 (40)
    • August 2024 (5)
    • July 2024 (6)
    • April 2024 (4)
    • March 2024 (10)
    • February 2024 (10)
    • January 2024 (8)
    • December 2023 (10)
    • August 2023 (3)
    • July 2023 (3)
    • June 2023 (7)
    • May 2023 (8)
    • April 2023 (7)
    • March 2023 (2)
    • February 2023 (2)
    • January 2023 (3)
    • December 2022 (6)
    • November 2022 (7)
    • January 2022 (1)
    • December 2021 (1)
    • October 2021 (3)
    • September 2021 (4)
    • August 2021 (4)
    • May 2019 (2)
    • April 2019 (1)
    • March 2019 (5)
    • January 2019 (2)
    • December 2018 (1)
    • November 2018 (4)
    • October 2018 (9)
    • July 2018 (1)
    • June 2018 (3)
    • May 2018 (1)
    • April 2018 (4)
    • February 2018 (2)
    • January 2018 (7)
    • August 2017 (9)
    • July 2017 (6)
    • October 2016 (1)
    • May 2015 (5)
    • April 2015 (8)
    • March 2015 (12)
    • February 2015 (4)
    • January 2015 (11)
    • November 2014 (1)
    • August 2014 (1)
    • June 2014 (2)
    • May 2014 (12)
    • April 2014 (5)
    • March 2014 (3)
    • February 2014 (6)
    • January 2014 (4)
    • December 2013 (5)
    • November 2013 (11)
    • October 2013 (2)
    • September 2013 (9)
    • August 2013 (4)
    • July 2013 (2)
    • June 2013 (14)
    • May 2013 (4)
    • April 2013 (10)
    • March 2013 (11)
    • February 2013 (11)
    • January 2013 (10)
    • December 2012 (10)
    • November 2012 (6)
    • October 2012 (13)
    • September 2012 (2)
    • August 2012 (5)
    • July 2012 (14)
    • June 2012 (6)
    • May 2012 (17)
    • April 2012 (15)
    • March 2012 (9)
    • February 2012 (16)
    • January 2012 (18)
    • December 2011 (20)
    • November 2011 (2)
  • Support designcoding!

    Enjoying designcoding? Support its future with a small donation on Patreon. Thank you!

    Patreon


    copyright 2026 designcoding.net | about | table of contents | keywords | privacy policy | end user license agreement