I’m going through the mess of sketches I have and found an interesting one I got from the coding train. I modified it by adding a slider to increase the number of circles it uses. When the number of circles gets big, the square wave exhibits what’s called Gibbs Phenomenon. Somehow I got the bright idea to try to correct that by adding a filter to make the square wave mo square.
The problem I see is that the filter works for awhile and then it shrinks the size of the circles. Here’s the code I have. If anyone knows how to fix it, thanks for the hints.
// Fourier Series
// Daniel Shiffman
// https://thecodingtrain.com/CodingChallenges/125-fourier-series.html
// https://youtu.be/Mm2eYfj0SgA
// https://editor.p5js.org/codingtrain/sketches/SJ02W1OgV
import controlP5.*;
float time = 0;
FloatList wave;
float increment = 1; // = 0.025f;
//int n = 5;
//int n = 5;
Controls controls;
PFont font;
boolean Flag = false;
boolean Dummy = true;
int showControls;
boolean draggingZoomSlider = false;
boolean released = true;
float zoom = 3;
float tzoom = 4;
int harmonic;
void setup() {
//fullScreen(); // size(600, 400);
size(600, 400);
wave = new FloatList();
controls = new Controls();
showControls = 1;
}
void draw() {
background(0);
if (mousePressed) {
if( (showControls == 1) && (controls.isZoomSliderEvent(mouseX, mouseY)) && mouseX < width/2 && mouseY < height/2 ) {
draggingZoomSlider = true;
zoom = controls.getZoomValue(mouseY);
zoom += (tzoom - zoom) * 0.1;
harmonic =(int) (map(zoom,0,385,0,100));
println(harmonic);
}
else if (!draggingZoomSlider) {
}
}
if (showControls == 1) {
controls.render();
// toggle(Dummy);
}
controls.updateZoomSlider(zoom);
translate(width/2-150,height/2);
float x = 0;
float y = 0;
//n = (int)M;
// for (int i = 0; i < n; i++) {
for (int i = 0; i < harmonic; i++) {
float prevx = x;
float prevy = y;
float n = i * 2 + 1;
float radius = (75 * (4 / (n * PI)));
// float sigma = (n+1) * PI / harmonic+1; //wave.size();
float sigma = (n) * PI / harmonic+1; //wave.size();
for(int j = 0; j < harmonic - 60; j++){
sigma = map(sigma,0, 1.5,1.0,-1.0);
sigma = (sin(sigma)/sigma);
radius = (radius * sigma);
}
x += (radius * cos(n * time));
y += (radius * sin(n * time));
stroke(255, 100);
noFill();
ellipse(prevx, prevy, radius * 2, radius * 2);
stroke(255);
line(prevx, prevy, x, y);
}
// wave.insert(0, y);
// next 4 lines replace wave.insert(0,y)
// insert not working on Android
wave.set(0,y);
wave.reverse();
wave.append(y);
wave.reverse();
translate(200, 0);
line(x - 200, y, 0, wave.get(0));
beginShape();
noFill();
// for (int i = 0; i < wave.size(); i++) {
for (int i = 0; i < wave.size(); i++) {
vertex(i, (wave.get(i)));
}
endShape();
time += 0.035;
if (wave.size() > 250*2) {
for (int n = 250*2; n < wave.size(); n++) {
wave.remove(n);
}
}
}
Here’s the slider code:
/*
Kepler Visualization - Controls
GUI controls added by Lon Riesberg, Laboratory for Atmospheric and Space Physics
lon@ieee.org
April, 2012
Current release consists of a vertical slider for zoom control. The slider can be toggled
on/off by pressing the 'c' key.
Slide out controls that map to the other key bindings is currently being implemented and
will be released soon.
*/
class Controls {
int barWidth;
int barX; // x-coordinate of zoom control
int minY, maxY; // y-coordinate range of zoom control
float minZoomValue, maxZoomValue; // values that map onto zoom control
float valuePerY; // zoom value of each y-pixel
int sliderY; // y-coordinate of current slider position
float sliderValue; // value that corresponds to y-coordinate of slider
int sliderWidth, sliderHeight;
int sliderX; // x-coordinate of left-side slider edge
Controls () {
barX = 40;
barWidth = 15;
minY = 40;
maxY = minY + height/3 - sliderHeight/2;
minZoomValue = height - height;
maxZoomValue = height; // 300 percent
valuePerY = (maxZoomValue - minZoomValue) / (maxY - minY);
sliderWidth = 25;
sliderHeight = 10;
sliderX = ((barX + (barWidth/2)) - (sliderWidth/2));
sliderValue = minZoomValue;
sliderY = minY;
}
void render() {
// strokeWeight(1.5);
strokeWeight(1);
// stroke(105, 105, 105); // fill(0xff33ff99);
// stroke(0xff33ff99); // fill(0xff33ff99); 0xffff0000
/////// stroke(0xffff0000); ///red
// zoom control bar
fill(0, 0, 0, 0);
rect(barX, minY, barWidth, maxY-minY);
// slider
// fill(105, 105, 105); //0x3300FF00
/////////////// fill(0xffff0000); // 0xff33ff99//0x3300FF00
fill(255,255,255);
rect(sliderX, sliderY, sliderWidth, sliderHeight);
}
float getZoomValue(int y) {
if ((y >= minY) && (y <= (maxY - sliderHeight/2))) {
sliderY = (int) (y - (sliderHeight/2));
if (sliderY < minY) {
sliderY = minY;
}
sliderValue = (y - minY) * valuePerY + minZoomValue;
}
return sliderValue;
}
void updateZoomSlider(float value) {
int tempY = (int) (value / valuePerY) + minY;
if ((tempY >= minY) && (tempY <= (maxY-sliderHeight))) {
sliderValue = value;
sliderY = tempY;
}
}
boolean isZoomSliderEvent(int x, int y) {
int slop = 50; // number of pixels above or below slider that's acceptable. provided for ease of use.
int sliderTop = (int) (sliderY - (sliderHeight/2)) - slop;
int sliderBottom = sliderY + sliderHeight + slop;
return ((x >= sliderX) && (x <= (sliderX + sliderWidth)) && (y >= sliderTop) && (y <= sliderBottom) || draggingZoomSlider );
}
}```