[d3js][javascript]Simulation of SYNC (Peskin model)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"> | |
<script> | |
window.addEventListener("load", function () { | |
"use strict"; | |
var canvas = document.createElement("canvas"); | |
document.body.appendChild(canvas); | |
canvas.width = canvas.height = 600; | |
var c2d = canvas.getContext("2d"); | |
var newNodes = function () { | |
var nodes = []; | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
nodes.push({voltage: Math.random() * 255}); | |
} | |
} | |
return nodes; | |
}; | |
var draw = function (nodes) { | |
c2d.clearRect(0, 0, 600, 600); | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
var node = nodes[x * 10 + y]; | |
c2d.save(); | |
c2d.translate(30 + x * 60, 30 + y * 60); | |
c2d.beginPath(); | |
c2d.arc(0, 0, node.voltage / 10, 0, Math.PI * 2, false); | |
c2d.closePath(); | |
c2d.fill(); | |
c2d.restore(); | |
} | |
} | |
}; | |
var syncNext = function (nodes) { | |
var charge = function (node) { | |
var v = node.voltage / 255; | |
return Math.log(Math.pow(Math.E, v) + (Math.E - 1) / 20) * 255; | |
}; | |
var nexts = []; | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
var node = nodes[x * 10 + y]; | |
nexts.push({voltage: charge(node)}); | |
} | |
} | |
/* | |
// propagate siblings only: late to sync all | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
var next = nexts[x * 10 + y]; | |
if (next.voltage < 255) continue; | |
var l = nexts[(x === 0 ? 9 : x - 1) * 10 + y]; | |
var r = nexts[(x === 9 ? 0 : x + 1) * 10 + y]; | |
var u = nexts[x * 10 + (y === 0 ? 9 : y - 1)]; | |
var d = nexts[x * 10 + (y === 9 ? 0 : y + 1)]; | |
l.voltage += next.voltage / 8; | |
r.voltage += next.voltage / 8; | |
u.voltage += next.voltage / 8; | |
d.voltage += next.voltage / 8; | |
} | |
} | |
*/ | |
// propagate all others: quickly sync all | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
var next = nexts[x * 10 + y]; | |
if (next.voltage < 255) continue; | |
nexts.forEach(function (n, i) { | |
if (i !== x * 10 + y) n.voltage += next.voltage / 100; | |
}); | |
} | |
} | |
// fire | |
for (var x = 0; x < 10; x++) { | |
for (var y = 0; y < 10; y++) { | |
var next = nexts[x * 10 + y]; | |
if (next.voltage > 255) next.voltage = 0; | |
} | |
} | |
return nexts; | |
}; | |
var current = newNodes(); | |
draw(current); | |
var id = setInterval(function () { | |
current = syncNext(current); | |
draw(current); | |
}, 100); | |
}, false); | |
</script> | |
</head> | |
<body> | |
</body> | |
</html> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<!doctype html> | |
<html> | |
<head> | |
<meta charset="utf-8"/> | |
<script src="http://d3js.org/d3.v3.min.js"></script> | |
<script> | |
window.addEventListener("load", function (ev) { | |
"use strict"; | |
// stage | |
var chart = d3.select("body").append("svg") | |
.attr("width", 960).attr("height", 760) | |
.append("g").attr("transform", "translate(80, 80)"); | |
var x = d3.scale.linear().domain([0, 200]).range([0, 800]); | |
var y = d3.scale.linear().domain([0, 1.2]).range([600, 0]); | |
var xaxis = d3.svg.axis().scale(x).ticks(10).orient("botton"); | |
var yaxis = d3.svg.axis().scale(y).ticks(12).orient("left"); | |
chart.append("g").attr("class", "x axis") | |
.attr("transform", "translate(0, 600)").call(xaxis); | |
chart.append("g").attr("class", "y axis") | |
.attr("transform", "translate(0, 0)").call(yaxis); | |
// sync simulation data | |
var charge = function (y) { | |
//return Math.sin(Math.asin(y) + Math.PI/20); | |
return Math.log(Math.pow(Math.E, y) + (Math.E - 1) / 20); | |
}; | |
var propagate = function (y, otherys) { | |
//return y; | |
return otherys.reduce(function (y, oy) { | |
return y + (oy === 0 ? 0.1 : 0); | |
}, y); | |
}; | |
var fire = function (y) { | |
return y >= 1 ? 0 : y; | |
}; | |
var dataA = [{x: 0, y: 0}]; | |
var dataB = [{x: 0, y: 0.33}]; | |
var dataC = [{x: 0, y: 0.66}]; | |
for (var i = 0; i < 200; i++) { | |
var lastA = dataA[dataA.length - 1]; | |
var lastB = dataB[dataB.length - 1]; | |
var lastC = dataC[dataC.length - 1]; | |
// charge | |
var chargeA = charge(lastA.y); | |
var chargeB = charge(lastB.y); | |
var chargeC = charge(lastC.y); | |
// propagate | |
var propA = propagate(chargeA, [lastB.y, lastC.y]); | |
var propB = propagate(chargeB, [lastA.y, lastC.y]); | |
var propC = propagate(chargeC, [lastA.y, lastC.y]); | |
var nextA = {x: lastA.x + 1, y: fire(propA)}; | |
var nextB = {x: lastB.x + 1, y: fire(propB)}; | |
var nextC = {x: lastC.x + 1, y: fire(propC)}; | |
dataA.push(nextA); | |
dataB.push(nextB); | |
dataC.push(nextC); | |
} | |
// plot lines | |
var line = d3.svg.line().x(function (d) {return x(d.x);}). | |
y(function (d) {return y(d.y);}); | |
chart.append("path").attr("class", "dataA").attr("d", line(dataA)); | |
chart.append("path").attr("class", "dataB").attr("d", line(dataB)); | |
chart.append("path").attr("class", "dataC").attr("d", line(dataC)); | |
}, false); | |
</script> | |
<style> | |
path.dataA { | |
stroke: red; | |
fill: none; | |
} | |
path.dataB { | |
stroke: blue; | |
fill: none; | |
} | |
path.dataC { | |
stroke: green; | |
fill: none; | |
} | |
</style> | |
</head> | |
<body> | |
<h1>Simulation of SYNC</h1> | |
</body> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Peskin's capacitor sync model from Steven Strogatz book "SYNC".
demo