I've created a unique drawing app that transforms sketches into Fourier series, but it's exhibiting an unusual behavior where it spirals inwards unexpectedly. Strangely, all the constants within the series are of similar size, which I suspect is incorrect, though I may be mistaken. Below is the code snippet:
var states = ["START", "DRAWING", "CIRCLES"];
var currentState = states[0];
var graph = [];
var constants = [];
// Half because ranging from -50 to 50
var halfNumCircles = 50;
var time = 0;
var deltaTime = 0.01;
// INITIAL SETUP
function setup() {
createCanvas(window.innerWidth, window.innerHeight);
angleMode(DEGREES);
frameRate(30);
cursor(CROSS);
}
// DRAWING LOOP
function draw() {
background(255);
// Axes
stroke(100);
line(width / 2, 0, width / 2, height);
line(0, height / 2, width, height / 2);
// Drawing
stroke(0);
if (currentState == states[1]) {
// Add mousepos to graph
graph.push([mouseX - width / 2, mouseY - height / 2]);
// Draw graph
for (let i = 0; i < graph.length - 1; i++) {
line(graph[i][0] + width / 2, graph[i][1] + height / 2,
graph[i + 1][0] + width / 2, graph[i + 1][1] + height / 2);
}
}
// Circles
stroke(0);
if (currentState == states[2]) {
// Starting at origin, draw lines to each boundary between circles
var points = [[0, 0]];
// For each constant, add a point
for (let i = 0; i < 2 * halfNumCircles + 1; i++) {
// n is 0,1,-1,2,-2...
var n = 0;
if (i % 2 == 0) {
n = -i / 2;
} else {
n = i / 2;
}
var pointX = constants[i][0] * cos(n * 2 * Math.PI * time) -
constants[i][1] * sin(n * 2 * Math.PI * time);
var pointY = constants[i][0] * sin(n * 2 * Math.PI * time) +
constants[i][1] * cos(n * 2 * Math.PI * time);
// Add new arrow to the last one
points.push([points[points.length - 1][0] + pointX, points[points.length - 1][1] + pointY]);
}
// Draw lines between points
for (let i = 0; i < points.length - 1; i++) {
line(points[i][0] + width / 2, points[i][1] + height / 2,
points[i + 1][0] + width / 2, points[i + 1][1] + height / 2)
}
// Increment time
time = (time + deltaTime);
}
}
// FOURIER SERIES OF FUNCTION
function getConstants(graph) {
// Returns array with constants
// Note that constants are complex numbers
// Set constants to 0, to be added to in the next loop
var constants = []
for (let i = 0; i < 2 * halfNumCircles + 1; i++) {
constants.push([0, 0]);
}
// For each constant
for (let c = -halfNumCircles; c <= halfNumCircles; c++) {
var deltaT = 1.0 / graph.length;
// Loop through the graph: sum of f(t)*e^{-c*2pi*i*t}*deltaT from 0 <= t <= 1
for (let i = 0; i < graph.length; i++) {
// Effective points on graph
var a = graph[i][0];
var b = graph[i][1];
var t = i / graph.length;
// Complex multiplication f(t)*e^{-c*2pi*i*t}
var xChange = a * cos(-c * 2 * Math.PI * t) - b * sin(-c * 2 * Math.PI * t);
var yChange = a * sin(-c * 2 * Math.PI * t) + b * cos(-c * 2 * Math.PI * t);
constants[c + halfNumCircles][0] += xChange * deltaT;
constants[c + halfNumCircles][1] += yChange * deltaT;
}
}
// Reorder from [...-2, -1, 0, 1, 2...] to [0, 1, -1, 2, -2...]
var orderedConstants = []
for (let i = 0; i < 2 * halfNumCircles + 1; i++) {
orderedConstants.push([0, 0]);
}
for (let i = 0; i < 2 * halfNumCircles + 1; i++) {
if (i % 2 == 0) {
orderedConstants[i] = constants[halfNumCircles - i / 2];
} else {
orderedConstants[i] = constants[halfNumCircles + (i + 1) / 2];
}
}
return orderedConstants;
}
// STATE CHANGING EVENTS
function mousePressed() {
// When clicked from start, start drawing
// When clicked from circles, reset
if (currentState == states[0]) {
currentState = states[1];
} else if (currentState == states[2]) {
currentState = states[0];
graph = [[]];
}
}
function mouseReleased() {
// When released, stop drawing, start circles
if (currentState == states[1]) {
currentState = states[2];
time = 0;
// Add first element of graph to the end, creating a loop
graph.push(graph[0]);
// Computationally intensive step
constants = getConstants(graph);
}
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Circle Drawing</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/p5.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.dom.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.6.0/addons/p5.sound.js" type="text/javascript"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/5.2.3/math.js" type="text/javascript"></script>
<script src="circles.js" type="text/javascript"></script>
<style media="screen">
body {
padding: 0;
margin: 0;
}
</style>
</head>
<body>
</body>
</html>
The bug has left me puzzled. I considered whether it could be related to input scale, but since the units are arbitrary in this instance, that wouldn't make sense. If you have any insight into what might be amiss, please share. Thank you for your assistance!