Last active
January 10, 2026 18:21
-
-
Save Gro-Tsen/6bdb99090c41705b5ba64ab0fb7a3590 to your computer and use it in GitHub Desktop.
Fourier transform of a decagon and related images
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| gcc -o d10fourier d10fourier.c -O6 -Wall -std=c99 -pedantic -Wextra -lm -DTEN=10 -DPIC_WIDTH=1920 -DPIC_HEIGHT=1080 -DFRAME_COUNT=1440 | |
| parallel -j 8 ./d10fourier {} ::: $(seq 0 719) | |
| ffmpeg -framerate 24 -i d10fourier-%04d.png -video_size 1920x1080 -c:v libx265 -preset slower -crf 27 -pix_fmt yuv420p d10fourier.mp4 | |
| gcc -o d14fourier d10fourier.c -O6 -Wall -std=c99 -pedantic -Wextra -lm -DTEN=14 -DPIC_WIDTH=1920 -DPIC_HEIGHT=1080 -DFRAME_COUNT=1440 | |
| parallel -j 8 ./d14fourier {} ::: $(seq 0 719) | |
| ffmpeg -framerate 24 -i d14fourier-%04d.png -video_size 1920x1080 -c:v libx265 -preset slower -crf 27 -pix_fmt yuv420p d14fourier.mp4 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // d10fourier.c - compute the Fourier transform of a regular decagon | |
| // David A. Madore <http://www.madore.org/~david/> | |
| // Initially written 2018-04-22 (based on an earlier e8fourier program) | |
| // This version 2026-01-10 | |
| /* This program is in the Public Domain. However, I would appreciate | |
| * being credited if significant parts of it are being used | |
| * somewhere. */ | |
| /* The author of this program disclaims all warranties with regard to | |
| * this software, including all implied warranties of merchantability | |
| * and fitness for a particular purpose: in no event shall the author | |
| * be liable for any damages arising out of or in connection with the | |
| * use or performance of this software. If you need this sort of | |
| * legalese, you are an idiot and you should not use a computer. */ | |
| /* Compile with something like | |
| gcc -o d10fourier d10fourier.c -O6 -Wall -std=c99 -Wextra -lm | |
| * The "convert" program from ImageMagick is used to convert .ppm to | |
| * .png (this should be easy to change, search for "convert" in | |
| * main()). Various compile-time adjustable parameters are below. */ | |
| #ifndef PIC_WIDTH | |
| #define PIC_WIDTH 1920 // Image width | |
| #endif | |
| #ifndef PIC_HEIGHT | |
| #define PIC_HEIGHT 1080 // Image height | |
| #endif | |
| #ifndef PIC_SCALE | |
| #define PIC_SCALE 16 // Pixels per unit distance | |
| #endif | |
| #ifndef FRAME_COUNT | |
| #define FRAME_COUNT 1440 // Frame count for a full cycle | |
| #endif | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <string.h> | |
| #include <math.h> | |
| #include <assert.h> | |
| #include <time.h> | |
| #include <unistd.h> | |
| #include <errno.h> | |
| #include <sys/types.h> | |
| #include <sys/wait.h> | |
| #ifndef TEN | |
| #define TEN 10 | |
| #endif | |
| #define DIM 2 | |
| #ifndef M_PI | |
| // Stupid <math.h> does not define this by order of the assholes who | |
| // removed this from the C99 standard. | |
| #define M_PI 3.141592653589793238462643383279502884 | |
| #endif | |
| double vecs[TEN][DIM]; | |
| int | |
| main (int argc, char *argv[]) | |
| { | |
| int frameno = 0; | |
| char havearg = 0; | |
| if ( argc >= 2 ) | |
| { | |
| havearg = 1; | |
| sscanf (argv[1], "%d", &frameno); | |
| } | |
| double phaseshift = (double)frameno / FRAME_COUNT; | |
| for ( int k=0 ; k<TEN ; k++ ) | |
| { | |
| vecs[k][0] = cos(M_PI*2*k/TEN); | |
| vecs[k][1] = sin(M_PI*2*k/TEN); | |
| } | |
| char buf[255]; | |
| if ( havearg ) | |
| snprintf (buf, sizeof(buf), "d%02dfourier-%04d.ppm", TEN, frameno); | |
| else | |
| snprintf (buf, sizeof(buf), "d%02dfourier.ppm", TEN); | |
| FILE *ppmf = fopen (buf, "w"); | |
| if ( ! ppmf ) | |
| { | |
| fprintf (stderr, "Failed to open %s for writing: %s\n", | |
| buf, strerror(errno)); | |
| exit (EXIT_FAILURE); | |
| } | |
| fprintf (ppmf, "P3\n%d %d 255\n", PIC_WIDTH, PIC_HEIGHT); | |
| for ( int l=0 ; l<PIC_HEIGHT ; l++ ) | |
| { | |
| for ( int k=0 ; k<PIC_WIDTH ; k++ ) | |
| { | |
| double v[DIM]; | |
| v[0] = ((k-PIC_WIDTH/2-0.5)/PIC_SCALE); | |
| v[1] = ((PIC_HEIGHT/2-0.5-l)/PIC_SCALE); | |
| double val = 0; | |
| for ( int r=0 ; r<TEN/2 ; r++ ) | |
| { | |
| double dot = 0; | |
| for ( int i=0 ; i<DIM ; i++ ) | |
| dot += vecs[r][i] * v[i]; | |
| dot += ((r%2) ? -2*phaseshift : 2*phaseshift); | |
| val += 2*cos(M_PI*dot); | |
| } | |
| // Fourier transform takes values between -10 and 10. | |
| assert (val >= -TEN && val <= TEN); | |
| #if 0 // Color gradient (blue for negative, black for zero, white for positive) | |
| if ( val < 0. ) | |
| { | |
| int i = (int)((val+TEN)*255/(TEN+0.)); | |
| fprintf (ppmf, " %d %d %d", 0, 0, 255-i); | |
| } | |
| else | |
| { | |
| int i = (int)((val)*255/(TEN+0.)); | |
| fprintf (ppmf, " %d %d %d", i, i, i); | |
| } | |
| #elif 0 // Black for negative, white for positive | |
| if ( val < -0.3 ) | |
| fprintf (ppmf, " %d %d %d", 0, 0, 0); | |
| else if ( val > 0.3 ) | |
| fprintf (ppmf, " %d %d %d", 255, 255, 255); | |
| else | |
| { | |
| int i = (int)((val+0.3)*425.); | |
| assert (i>=0 && i<=255); | |
| fprintf (ppmf, " %d %d %d", i, i, i); | |
| } | |
| #else // White for [-1,1], black outside of [-1.5,1.5] | |
| if ( val >= -1 && val <= 1 ) | |
| fprintf (ppmf, " %d %d %d", 255, 255, 255); | |
| else if ( val > 1.5 || val < -1.5 ) | |
| fprintf (ppmf, " %d %d %d", 0, 0, 0); | |
| else | |
| { | |
| int i = (int)(255-(fabs(val)-1.)*510.); | |
| assert (i>=0 && i<=255); | |
| fprintf (ppmf, " %d %d %d", i, i, i); | |
| } | |
| #endif | |
| } | |
| fprintf (ppmf, "\n"); | |
| } | |
| fclose (ppmf); | |
| // Now convert PPM image to PNG. | |
| pid_t convpid = fork (); | |
| if ( convpid < 0 ) | |
| { | |
| fprintf (stderr, "Failed to fork: %s\n", strerror(errno)); | |
| exit (EXIT_FAILURE); | |
| } | |
| if ( convpid == 0 ) | |
| { | |
| char buf2[255]; | |
| if ( havearg ) | |
| snprintf (buf2, sizeof(buf2), "d%02dfourier-%04d.png", TEN, frameno); | |
| else | |
| snprintf (buf2, sizeof(buf2), "d%02dfourier.png", TEN); | |
| execlp ("convert", "convert", buf, buf2, (char *)NULL); | |
| fprintf (stderr, "Failed to execlp: %s\n", strerror(errno)); | |
| exit (EXIT_FAILURE); | |
| } | |
| else | |
| { | |
| waitpid (convpid, NULL, 0); | |
| unlink (buf); | |
| } | |
| exit (EXIT_SUCCESS); | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment