Skip to content

Instantly share code, notes, and snippets.

@AHaliq
Last active December 10, 2019 08:44
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save AHaliq/6151cc5a3da6718724a8942e221f1a2e to your computer and use it in GitHub Desktop.
Save AHaliq/6151cc5a3da6718724a8942e221f1a2e to your computer and use it in GitHub Desktop.
Coding Train Challenge #125, fourier series implemented in functional style with waves in terms of amplitude, frequency and range
let STAGE_WIDTH = 800;
const STAGE_HEIGHT = 400;
const L_BORDER = 25;
const COLBG = 220;
const COL1 = 100;
const COL2 = 195;
const PIVOTRADI = 10;
const LINEGAP = 5;
let UNITRADI = 50;
let DW;
let RT_BORDER;
let LM_X = 0;
const LM_MAXT = 600;
let LM_T = 0;
let TICK = 0.03;
let D = [];
let wave = [];
let time = 0;
let presetIndex = 0;
const PRESETS = [
["square","4/(PI*((2*i)+1))","(2*i)+1","0"],
["sawtooth","2/(PI*(i+1))*pow(-1,(i+1))","i+1","0"],
["phased square","4/(PI*((2*i)+1))","(2*i)+1","PI/20"],
];
function setup() {
STAGE_WIDTH = windowWidth;
createCanvas(STAGE_WIDTH, STAGE_HEIGHT);
//D = [[50,1,0],[25,2,0],[10,3,0]] // manual diagram test
var gen = (n,a,f,p) => Array.apply(null, Array(n)).map((_,i)=>i).map(
(i) => [UNITRADI * eval(a), eval(f), eval(p)]);
let a_TXT = createInput();
let f_TXT = createInput();
let p_TXT = createInput();
let BTN = createButton("submit");
let TICK_SLIDER = createSlider(1,20,3);
let UNITRADI_SLIDER = createSlider(25,100,50);
let ITERATIONS_SLIDER = createSlider(1,20,3);
let SEL = createSelect();
PRESETS.map(([o]) => SEL.option(o));
const setupD = () => {
n = ITERATIONS_SLIDER.value();
D = gen(n,a_TXT.value(), f_TXT.value(), p_TXT.value());
DW = D.reduce((pr,[a,f,p]) => pr + abs(a),0);
updateBorder();
}
const setpresetText = () => {
a_TXT.value(PRESETS[presetIndex][1]);
f_TXT.value(PRESETS[presetIndex][2]);
p_TXT.value(PRESETS[presetIndex][3]);
}
setpresetText();
SEL.changed(() => {
presetIndex = PRESETS.reduce((pr,[name,a,f,p],i) =>
SEL.value() == name ? i : pr,-1);
setpresetText();
setupD();
});
BTN.mousePressed(() => setupD());
TICK_SLIDER.input(() => TICK = TICK_SLIDER.value()/100);
UNITRADI_SLIDER.input(() => {
UNITRADI = UNITRADI_SLIDER.value();
setupD();
});
ITERATIONS_SLIDER.input(() => {
setupD();
});
setupD();
}
function updateBorder() {
RT_BORDER = STAGE_WIDTH + LM_X - L_BORDER * 2;
}
function draw() {
background(COLBG);
translate(-LM_X + L_BORDER, STAGE_HEIGHT * 0.5);
if(LM_T < LM_MAXT) {
LM_T++;
}else {
LM_X++;
}// ease retract left min border
(([x,y]) => {
stroke(COL2);
noFill();
line(LM_X, 0, RT_BORDER, 0);
line(x,y,DW,y);
ellipse(DW,y,PIVOTRADI);
stroke(COL1);
beginShape();
wave.unshift(y);
wave = wave.splice(0, RT_BORDER - DW);
wave.map((y,i) => vertex(DW + i, y));
endShape();
}) (D.reduce(([x,y],[a,f,p],i) => {
let nx = x + a * cos(p + f * time);
let ny = y + a * sin(p + f * time);
// calculate pivot point
let olmx = LM_X;
LM_X = min(LM_X, x - abs(a));
if(olmx != LM_X || round((olmx - (x - abs(a)))*0.1) == 0) LM_T = 0;
updateBorder();
// calculate left minimum border
stroke(COL2);
noFill();
ellipse(nx,ny,PIVOTRADI);
ellipse(x,y,a * 2);
let rx = DW - ((D.length - 1) * LINEGAP) + (i * LINEGAP);
line(rx,y,rx,ny);
ellipse(rx,ny,LINEGAP);
fill(COL1);
stroke(COL1);
line(x,y,nx,ny);
return [nx, ny];
}, [0,0]));
time += TICK;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment