# Shiffman's Fourier Series

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);

}

x += (radius * cos(n * time));
y += (radius * sin(n * time));

stroke(255, 100);
noFill();
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 );
}
}`````````

i m not sure i see the problem when running the code, looks good to me

however, could it be you use (int) in place of round() or even keep evrything as float?

``````
println((int) 1.8f);
println(round(1.8f));
``````

Sounds like you tried it. I’m not sure about consistency in float or int?

If you slide the slider almost to max, the circles shrink including the main circle. Yeah its a square wave but …

It does have a cool feature though. If you slide it to max and release, it snaps back to min and you get a single sine wave.