我已经编写了一个绘图应用程序,可以将绘图转换为傅立叶级数,但是它在向内盘旋时做的很奇怪。由于某种原因,该系列的所有常量在大小上都是相似的(我认为这是错误的,但我可能是错误的)。这是我的代码:
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>
我似乎找不到该错误。我认为这可能与输入的比例有关,但这没有意义,因为在这种情况下单位是任意的。如果您知道我做错了什么,请告诉我。谢谢你的帮助!
最佳答案
deltaTime
的单位是毫秒。采样周期太大。
将时间除以1000.0可得到以秒为单位的时间:
var times_s = time/1000.0;
var pointX = constants[i][0] * cos(n * 2 * Math.PI * times_s) -
constants[i][1] * sin(n * 2 * Math.PI * times_s);
var pointY = constants[i][0] * sin(n * 2 * Math.PI * times_s) +
constants[i][1] * cos(n * 2 * Math.PI * times_s);
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 times_s = time/1000.0;
var pointX = constants[i][0] * cos(n * 2 * Math.PI * times_s) -
constants[i][1] * sin(n * 2 * Math.PI * times_s);
var pointY = constants[i][0] * sin(n * 2 * Math.PI * times_s) +
constants[i][1] * cos(n * 2 * Math.PI * times_s);
// 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);
}
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.9.0/p5.js"></script>