(https://codepen.io/johnslipper/details/eYgZMRL)
var context = new AudioContext();
let dampening = 1;
function pluck(frequency) {
var pluck = context.createScriptProcessor(4096, 0, 1);
var N = Math.round(context.sampleRate / frequency);
var y = new Float32Array(N);
for (let i = 0; i < N; i++) {if (window.CP.shouldStopExecution(0)) break;
y[i] = Math.random() * 2 - 1;
}
window.CP.exitedLoop(0);let n = 0;
pluck.onaudioprocess = function (e) {
var output = e.outputBuffer.getChannelData(0);
for (let i = 0; i < e.outputBuffer.length; i++) {if (window.CP.shouldStopExecution(1)) break;
y[n] = (y[n] + y[(n + 1) % N]) / 2;
output[i] = y[n];
y[n] *= dampening;
n++;
if (n >= N) n = 0;
}window.CP.exitedLoop(1);
};
var bandpass = context.createBiquadFilter();
bandpass.type = "bandpass";
bandpass.frequency.value = frequency;
bandpass.Q.value = 1;
pluck.connect(bandpass);
setTimeout(() => {
pluck.disconnect();
}, 2000);
setTimeout(() => {
bandpass.disconnect();
}, 2000);
return bandpass;
}
function strum(fret, stringCount = 6, stagger = 150) {
dampening = 1;
var dst = context.destination;
for (let index = 0; index < stringCount; index++) {if (window.CP.shouldStopExecution(2)) break;
if (Number.isFinite(fret[index])) {
setTimeout(() => {
pluck(getFrequency(index, fret[index])).connect(dst);
}, stagger * index);
}
}window.CP.exitedLoop(2);
}
function getFrequency(string, fret) {
var A = 120;
var offsets = [-5, 0, 5, 10, 14, 19];
return A * Math.pow(2, (fret + offsets[string]) / 12);
}
context.resume().then(strum([0,2,2,1,0,0]));
!!! The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead.
(The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead.)
It is a very successful webaudio guitar application. How can I change it?
I get convergence, nevertheless, the results are never the same when the algorithm is refreshed. This occurs even when the data observations is the same dataset. Can anyone tell me where my methodology is wrong? For the life of me I can't figure out where the process is wrong.
function kmeans2(k, data, canvas, converge) {
this.canvas = jsHS.GetDimensions(canvas);
this.k = k;
this.centroids = []; // Array of centroids
this.centroids2compare = [];
this.data = data;
this.converge = converge;
this.init();
}
kmeans2.prototype.distance = function () {
var dif = 0,
iArray = jsHS.isArray(arguments);
if (iArray) {
if (arguments.length > 2) {
for (var i = 0; i < arguments.length; i+2) {
var p0 = arguments[i],
p1 = arguments[i + 1];
dif += Math.pow(p0[0] - p1[0], 2);
dif += Math.pow(p0[1] - p1[1], 2);
}
}
else {
var pd0 = arguments[0],
pd1 = arguments[1];
dif += Math.pow(pd0[0] - pd1[0], 2);
dif += Math.pow(pd0[1] - pd1[1], 2);
}
}
return Math.sqrt(dif);
};
kmeans2.prototype.Means = function (Array) {
var bin = 0;
[].forEach.call(Array, function(a){
bin += a;
});
return bin / Array.length;
};
kmeans2.prototype.init = function () {
for (var l = 0; l < this.k; l++) {
var dataItem = this.data[Math.floor(Math.random() * this.data.length)];
this.centroids.push(dataItem);
}
for (var i = 0; i < this.centroids.length; i++) {
if (i > 0) {
var distance = this.distance(this.centroids[i], this.centroids[i - 1]);
console.log(distance);
}
}
this.clusterCentroids(); // return centroid center after calculating means.
};
kmeans2.prototype.clusterCentroids = function () {
var points0 = [];
this.centroids2compare = this.centroids;
// Find distances between centroid and observations.
for (var d = 0; d < this.data.length; d++) {
var cinbin = [];
for (var c0 = 0; c0 < this.k; c0++) {
var dis = this.distance(this.centroids[c0], this.data[d]);
cinbin.push({ 'cid': c0, 'distance': dis });
}
var minResult = cinbin.reduce((cid, obj) => {
return obj.distance < cid.distance ? obj : cid;
});
points0.push({ 'id': d, 'datapoint': this.data[d], 'centroid': minResult.cid });
}
// Assign observations their appropriate centroid.
var centroidBin = [];
for (var c = 0; c < this.k; c++) {
var cb = [];
for (var p = 0; p < points0.length; p++) {
if (c === points0[p].centroid) {
cb.push(points0[p]);
}
}
centroidBin.push(cb);
}
// Calculate the mean distance between centroids and its assigned observations.
this.centroids = [];
for (var bin = 0; bin < centroidBin.length; bin++) {
var xAxis = [],
yAxis = [],
cb0 = centroidBin[bin];
[].forEach.call(cb0, function (dp) {
xAxis.push(dp.datapoint[0]);
yAxis.push(dp.datapoint[1]);
});
var xMean = this.Means(xAxis);
var yMean = this.Means(yAxis);
this.centroids.push([xMean, yMean]);
}
// Test for convergence. If stored centroids equal new centroids then convergence is achieved.
if (JSON.stringify(this.centroids2compare) !== JSON.stringify(this.centroids)) {
this.centroids2compare = [];
points0 = [];
this.clusterCentroids();
}
else {
this.converge(centroidBin, this.centroids);
}
};
window['jsHS']['kmeans2'] = kmeans2;
Implementation
var k50 = new jsi.kmeans2(5, Array50, canvas, function (con, centroids) {
var count50 = 0;
var cmark = {
x: 0,
y: 0,
rad:0,
clr: null,
setArc: function () {
ctx.beginPath();
ctx.arc(this.x, this.y, this.rad, 0, Math.PI * 2, true);
ctx.fillStyle = this.clr;
ctx.fill();
}
};
[].forEach.call(centroids, (c) => {
cmark.x = c[0];
cmark.y = c[1];
cmark.clr = '#0B6623';
cmark.rad = 25;
cmark.setArc();
});
});
This example plots the centroids on a canvas area fine enough but when the browser refreshes the centroids change.
I haven't looked much at your code, but I know that the k-means algorithm tends to give different results when you run it several times. This is because it's highly dependent on where the first centroids (which are selected randomly) are located.
The algorithm can find a local minimum and get "stuck" there, and terminate.
There's no guarantee that you will find the global minimum the first time you run it.
var imagething;
var kernel = [[1, 2, 1], [2, 4, 2], [1, 2, 1]];
var sum_of_elements = 0;
var mult_factor = 0.0625;
var bias = 0;
function preload() {
imagething = loadImage('data/image.png');
}
function setup() {
createCanvas(1000, 1000);
imagething.loadPixels();
image(imagething, 0, 0);
makeBlurred(imagething, 1);
image(imagething, 512, 0);
}
function imageIndex(img, x, y) {
return 4 * (x + y * img.width);
}
function makeBlurred() {
for(var i = 0; i < kernel.length; i++) {
for(var j = 0; j < kernel.length; j++) {
sum_of_elements += kernel[i][j];
}
}
for(var x = 0; x < imagething.width; x++) {
for(var y = 0; y < imagething.height; y++) {
var red = 0;
var green = 0;
var blue = 0;
for(var i = 0; i < kernel.length; i++) {
for(var j = 0; j < kernel.length; j++) {
var imageX = (x - kernel.length / 2 + i + imagething.width) % imagething.width;
var imageY = (y - kernel.length / 2 + j + imagething.height) % imagething.height;
var RGB = imageIndex(imagething, imageX, imageY);
var pix = imagething.pixels;
var R = pix[RGB];
var G = pix[RGB + 1];
var B = pix[RGB + 2];
console.log("Start: ",R,G,B);
red += (R * kernel[i][j]);
green += (G * kernel[i][j]);
blue += (B * kernel[i][j]);
}
}
var outR;
var outG;
var outB;
outR = Math.min(Math.max(Math.round(red * mult_factor), 0), 255);
outG = Math.min(Math.max(Math.round(green * mult_factor), 0), 255);
outB = Math.min(Math.max(Math.round(blue * mult_factor), 0), 255);
console.log("End: ", outR, outG, outB);
pix[RGB] = outR;
pix[RGB + 1] = outG;
pix[RGB + 2] = outB;
imagething.updatePixels();
}
}
}
So I am referencing this blog post on kernel-based image processing and I am trying to blur my image. I am using the blur matrix and I use the original image and it should turn out like this but it ends up like this so I must be doing something wrong. Help is much appreciated :)
My problem is this:
Suppose this class, it's an example of my true code:
class TileMap {
constructor ( w, h ) {
this.tiles = [];
// init the matrix
for (var i = 0; i < h; i++) {
var a = [];
for (var j = 0; j < w; j++) {
a.push(0);
}
this.tiles[i] = a;
}
}
setTile (x, y, tile) {
this.tiles[y][x] = tile;
}
doSomething () {
this.setTile(0, 0, 1);
this.setTile(0, 1, 2);
}
}
// What's happening is when I use like this:
var player = {};
player.map = new TileMap(32, 90, 90);
player.map.doSomething();
console.log("before Tile[0][0] = " + player.map.tiles[0][0]);
player.map.setTile(0, 0, 3);
console.log("after Tile[0][0] = " + player.map.tiles[0][0]);
Shows me the follow output:
before Tile[0][0] = 1
after Tile[0][0] = 1
The matrix are modified but turn back to before values.
What should I do? (NOTE I'm not familiar with javascript but with language like C++)
I do not understand what is wrong. I added to your code the player object.
class TileMap{
constructor ( w, h ){
this.tiles = [];
//init the matrix
for (var i = 0; i < h; i++)
{
var a = [];
for (var j = 0; j < w; j++)
a.push(0);
this.tiles[i] = a;
}
}
setTile (x, y, tile){
this.tiles[y][x] = tile;
}
doSomething (){
this.setTile(0,0, 1);
this.setTile(0,1, 2);
}
}
//What's happening is when I use like this:
var player = {};
player.map = new TileMap(32,90,90);
player.map.doSomething();
console.log("before Tile[0][0] = "+player.map.tiles[0][0]);
player.map.setTile(0,0, 3);
console.log("after Tile[0][0] = "+player.map.tiles[0][0]);
I am continuing to animate a model of a transportation system. The code builds stations, connects them with lines, builds "pods" to run along them, then works out the shortest path between random start and end stations.
jsfiddle
The problems I am having are
a) the pods are traveling one at a time, rather than simultaneously.
b) the pod color is supposed to be related to the number of passengers, but this is clearly not happening.
c) I suspect I am producing a bottleneck in calculating the animation points, as it seems to run more hesitantly than it should.
I would also like to be able to flag the arrival of each pod, so that it can be reloaded, and start a new journey.
Something is wrong with the animation section, but I can't work out what. Any help would be appreciated!
animate();
var lastTime = 0;
var speed = 1; // higher is slower
function animate(time) {
for (var i = 0; i < podArray.length; i++) {
var aPod = podArray[i];
// calculate incremental points along the path
var points = calcWaypoints(aPod.wayStations);
// return if the desired time hasn't elapsed
if ((time - lastTime) < speed) {
requestAnimationFrame(animate);
return;
}
lastTime = time;
//function animate(){
ctx3.clearRect(0, 0, layer3.width, layer3.height);
if (t < points.length - 1) {
requestAnimationFrame(animate);
}
// draw pod from the last waypoint to the current waypoint
ctx3.beginPath();
ctx3.moveTo(aPod.startX, aPod.startY); //(points[t - 1].x, points[t - 1].y);
ctx3.arc(points[t].x, points[t].y, 4, 0, Math.PI * 2, true);
ctx3.fillStyle = aPod.color;
ctx3.fill();
t++;
}
}
a) Your calcWaypoints function takes a parameter that is a list of waystation, and then you ignore that parameter and calculate all points for all pods. This is creating one big array of all points, starting with the first pod's points, then the 2nd's, etc. This is why it starts with the first, then the 2nd then the third.
function calcWaypoints(nextArray) {
var frams = 100;
var waypoints = [];
for (var i = 1; i < nextArray.length; i++) {
var pt0 = nextArray[i - 1];
var pt1 = nextArray[i];
var dx = pt1[0] - pt0[0];
var dy = pt1[1] - pt0[1];
for (var j = 0; j < frams; j++) {
var x = pt0[0] + dx * j / frams //+ dxOff;
var y = pt0[1] + dy * j / frams //+ dyOff;
waypoints.push({
x: x,
y: y
});
};
}
return waypoints;
}
b) This has the same cause as the previous, because you are using the same points for each pod, the pods are written over one another. In addition, you are clearing the canvas between each point. This clear should be moved out of the loop. ctx3.clearRect(0, 0, layer3.width, layer3.height);
c) For some reason you are re-calculating all points with every call to animate. You should calculate them all upfront once and then not in animate. You are also creating way too many calls to requestAnimationFrame in your loop.
I hacked together a few of the above changes and it is working. You should still clean it up a lot more:
layer1 = document.getElementById('layer1');
ctx1 = layer1.getContext('2d');
layer2 = document.getElementById('layer2');
ctx2 = layer2.getContext('2d');
layer3 = document.getElementById('layer3');
ctx3 = layer3.getContext('2d');
window.requestAnimFrame = (function (callback) {
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function (callback) {
window.setTimeout(callback, 1000 / 60);
};
})();
//STATIONS*************************************
var station = [
['A', 150, 100],
['B', 300, 100],
['C', 200, 175],
['D', 100, 250],
['E', 300, 250],
['G', 400, 250],
['F', 350, 200],
['Airport', 500, 200],
['Central', 500, 350]
];
function draw2() {
for (var i = 0; i < station.length; i++) {
var radius = 10;
ctx2.beginPath();
ctx2.arc(station[i][1], station[i][2], radius, 0, 2 * Math.PI);
ctx2.stroke();
ctx2.fillStyle = 'yellow';
ctx2.fill();
//ADD STATION LETTERS
ctx2.font = '10pt Calibri';
ctx2.fillStyle = 'black';
ctx2.textAlign = 'center';
ctx2.fillText(station[i][0], station[i][1], (station[i][2]) + 4);
}
}
draw2();
//END STATIONS*************************************
//START LINES**************************************
var lineArray = [
['A', 'B', ],
['B', 'A', 'C'],
['C', 'B', 'D', 'E'],
['D', 'C', 'E'],
['E', 'D', 'F', 'G', 'Central'],
['F', 'E', 'G'],
['G', 'F', 'E', 'Airport'],
['Airport', 'G', 'Central'],
['Central', 'E', 'Airport']
];
function drawLines() {
for (m = 0; m < lineArray.length; m++) {
ctx1.lineWidth = 1;
ctx1.beginPath();
for (p = 1; p < lineArray[m].length; p++) {
var startStat = lineArray[m][0];
var stat = lookUp(startStat);
var beginX = station[stat][1];
var beginY = station[stat][2];
ctx1.moveTo(beginX, beginY);
var endStat = lineArray[m][p];
var endSt = lookUp(endStat);
var closeX = station[endSt][1];
var closeY = station[endSt][2];
ctx1.lineTo(closeX, closeY);
}
ctx1.stroke();
}
}
drawLines();
//END LINES*************************************
//SHORTEST PATH*********************************
function Graph() {
var neighbors = this.neighbors = {}; // Key = vertex, value = array of neighbors.
this.addEdge = function (u, v) {
if (neighbors[u] === undefined) { // Add the edge u -> v.
neighbors[u] = [];
}
neighbors[u].push(v);
if (neighbors[v] === undefined) { // Also add the edge v -> u in order
neighbors[v] = []; // to implement an undirected graph.
} // For a directed graph, delete
neighbors[v].push(u); // these four lines.
};
return this;
}
function shortestPath(graph, source, target) {
var stationPath = [];
var coordPath = [];
if (source == target) { // Delete these four lines if
print(source); // you want to look for a cycle
return; // when the source is equal to
} // the target.
var queue = [source],
visited = {
source: true
},
predecessor = {},
tail = 0;
while (tail < queue.length) {
var u = queue[tail++], // Pop a vertex off the queue.
neighbors = graph.neighbors[u];
for (var i = 0; i < neighbors.length; ++i) {
var v = neighbors[i];
if (visited[v]) {
continue;
}
visited[v] = true;
if (v === target) { // Check if the path is complete.
var path = [v]; // If so, backtrack through the path.
while (u !== source) {
path.push(u);
u = predecessor[u];
}
path.push(u);
path.reverse();
print(path.join(' → '));
//console.log('Path: ' + path);
for (s = 1; s < path.length; s++) {
stationPath.push(path[s]);
}
//console.log('Waypoints: ' + stationPath);
for (t = 0; t < stationPath.length; t++) {
staCo = lookUp(stationPath[t]);
staCoX = station[staCo][1];
staCoY = station[staCo][2];
coordPath.push([staCoX, staCoY]);
}
//console.log(coordPath);
return coordPath;
}
predecessor[v] = u;
queue.push(v);
}
}
print('there is no path from ' + source + ' to ' + target);
}
function print(s) { // A quick and dirty way to display output.
s = s || '';
document.getElementById('display').innerHTML += s + '<br>';
}
function findShortestPath(s1, s2) {
var graph = new Graph();
for (w = 0; w < lineArray.length; w++) {
var baseStation = lineArray[w][0];
for (z = 1; z < lineArray[w].length; z++) {
graph.addEdge(baseStation, lineArray[w][z]);
}
}
return (shortestPath(graph, s1, s2));
};
function lookUp(sta) {
//console.log(sta);
for (n = 0; n < station.length; n++) {
if (sta == station[n][0]) {
return n;
break;
}
}
}
//BUILD PODS*************************************
var podArray = [];
function Pod(startX, startY, wayStations, riders, color) {
this.startX = startX;
this.startY = startY;
this.wayStations = wayStations;
this.riders = riders;
this.color = color;
}
var colorArray = ['gold', 'orange', 'red', 'green', 'blue', 'black'];
function randomPass() {
occ = 1 + Math.floor(Math.random() * 6);
return occ;
}
//PROGRAM PODS*********************************************
for (i = 0; i < 3; i++) { //NUMBER OF PODS
//Start Station
var startOff = Math.floor(Math.random() * station.length);
var begSta = station[startOff][0];
var fromX = station[startOff][1];
var fromY = station[startOff][2];
//END STATION
var destNum = Math.floor(Math.random() * station.length);
while (startOff == destNum) {
destNum = Math.floor(Math.random() * station.length);
}
var endSta = station[destNum][0];
function getWayStations(beg, end) {
var fsp = findShortestPath(beg, end);
var nextArray = [];
nextArray.push([fromX, fromY]);
for (var f = 0; f < fsp.length; f++) {
nextArray.push(fsp[f]);
}
return nextArray;
}
//LOAD POD DATA
podArray.push(new Pod(
startX = fromX,
startY = fromY,
wayStations = getWayStations(begSta, endSta),
riders = randomPass(),
color = colorArray[riders - 1]))
}
//END PROGRAM PODS*********************************************
// calc waypoints traveling along nextArray
function calcWaypoints(nextArray) {
var frams = 100;
var waypoints = [];
for (var i = 1; i < nextArray.length; i++) {
var pt0 = nextArray[i - 1];
var pt1 = nextArray[i];
var dx = pt1[0] - pt0[0];
var dy = pt1[1] - pt0[1];
for (var j = 0; j < frams; j++) {
var x = pt0[0] + dx * j / frams //+ dxOff;
var y = pt0[1] + dy * j / frams //+ dyOff;
waypoints.push({
x: x,
y: y
});
};
}
return (waypoints);
}
animate();
var lastTime = 0;
var speed = 1; // higher is slower
function animate(time) {
// return if the desired time hasn't elapsed
if ((time - lastTime) < speed) {
requestAnimationFrame(animate);
return;
}
lastTime = time;
ctx3.clearRect(0, 0, layer3.width, layer3.height);
var callAgain = false;
for (var i = 0; i < podArray.length; i++) {
var aPod = podArray[i];
// calculate incremental points along the path
var points = calcWaypoints(aPod.wayStations);
if (t < points.length - 1) {
callAgain = true;
}
// draw pod from the last waypoint to the current waypoint
if(points.length > t){
ctx3.beginPath();
ctx3.moveTo(aPod.startX, aPod.startY); //(points[t - 1].x, points[t - 1].y);
ctx3.fillStyle = aPod.color;
ctx3.arc(points[t].x, points[t].y, 4, 0, Math.PI * 2, true);
ctx3.fill();
}
}
t++;
if(callAgain) requestAnimationFrame(animate);
}
<canvas id='layer1' style='z-index: 2;
position:absolute;
left:0px;
top:0px;
' height='600px' width='1000'>This text is displayed if your browser does not support HTML5 Canvas.</canvas>
<canvas id='layer2' style='z-index: 3;
position:absolute;
left:0px;
top:0px;
' height='600px' width='1000'>This text is displayed if your browser does not support HTML5 Canvas.</canvas>
<canvas id='layer3' style='z-index: 1;
position:absolute;
left:0px;
top:0px;
' height='600px' width='1000'>This text is displayed if your browser does not support HTML5 Canvas.</canvas>
<div id="display">
</id>