Created
July 17, 2016 19:55
-
-
Save sifbuilder/c5e629b377ad6b8ff055d75fb9c17359 to your computer and use it in GitHub Desktop.
ringforce i, circumscribing rings in a voronoi triangles diagram of heavy seeds moving in a contained field area
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
ringforce, circumscribing rings in a voronoi triangles diagram of heavy seeds moving in a contained field area |
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
/* ------------------ */ | |
/* index-controls.js */ | |
/* ------------------ */ | |
// ---------------- // drag listeners | |
var dragstarted = function dragstarted(d) { | |
if (!d3.event.active) simulation.alphaTarget(0.3).restart() | |
} | |
function dragged(d) { | |
} | |
function dragended(d) { | |
if (!d3.event.active) simulation.alphaTarget(0); | |
} | |
// ---------------- // mouse listeners | |
function pauseEvent(e){ | |
if(e.stopPropagation) e.stopPropagation(); | |
if(e.preventDefault) e.preventDefault(); | |
e.cancelBubble=true; | |
e.returnValue=false; | |
return false; | |
} | |
function mousemove(svgElement) { | |
moving = 1 | |
mousePosition = d3.mouse(svgElement) // updateMousePos | |
var e = d3.event | |
pauseEvent(e) | |
} | |
function mouseleave() { | |
moving = 0 | |
// stopParticles(); | |
} | |
function mousedown() { | |
// mousedown = 1 | |
// updateMousePos(); | |
// startParticles(); | |
} | |
function mousedown() { | |
// touchstart = 1 | |
// updateMousePos(); | |
// startParticles(); | |
} | |
function touchmove(svgElement) { | |
moving = 1 | |
mousePosition = d3.mouse(svgElement) // updateMousePos | |
var e = d3.event | |
pauseEvent(e) | |
} | |
function mouseup() { | |
// mouseup = 1 | |
// stopParticles(); | |
} | |
function touchend() { | |
// touchend = 1 | |
// stopParticles(); | |
} |
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
/* ------------------ */ | |
/* index-data.js */ | |
/* ------------------ */ | |
// =================================== nodes | |
var nodes = []; | |
var links = []; | |
var nodesCollection = [{ | |
id: 0, | |
group: 1, | |
rotr: 100, | |
rtype: "circle", | |
color: "red", | |
offset: 20, | |
timelimit: 2000, | |
starttime: undefined, | |
elapsed: 0, | |
scale: 1, | |
move: false, | |
links: [{ | |
source: 0, // red | |
target: 1, // blue | |
index: 1, | |
}, | |
// { | |
// source: 0, // red | |
// target: 3, // black | |
// index: 2, | |
// }, | |
{ | |
source: 0, // red | |
target: 4, // grey | |
index: 2, | |
}], | |
charge: -2, | |
t: 1, | |
r: 2, | |
x: 15, | |
y: 50, | |
vx: 0, | |
vy: 0, | |
} | |
, { | |
id: 1, | |
group: 1, | |
rotr: 100, | |
rtype: "circle", | |
color: "blue", | |
offset: 20, | |
timelimit: 2000, | |
starttime: undefined, | |
elapsed: 0, | |
links: [ | |
{ | |
source: 1, // blue | |
target: 2, // green | |
index: 3, | |
}, | |
{ | |
source: 1, // blue | |
target: 3, // green | |
index: 4, | |
}, | |
], | |
charge: -1, | |
mass: 0, | |
r: 2, | |
t: 1, | |
x: 80, | |
y: 50, | |
vx: 0, | |
vy: 0, | |
scale: 1, | |
move: false, | |
} | |
, { | |
id: 2, // green | |
group: 1, | |
rotr: 100, | |
rtype: "circle", | |
color: "green", | |
offset: 20, | |
timelimit: 2000, | |
starttime: undefined, | |
elapsed: 0, | |
x: 80, | |
fy: 50, | |
vx: 0, | |
vy: 0, | |
links: [], | |
charge: 1, | |
mass: 0, | |
r: 2, | |
t: 1, | |
x: 60, | |
y: 50, | |
vx: 0, | |
vy: 0, | |
scale: 1, | |
move: false, | |
} | |
, { | |
id: 3, | |
group: 1, | |
rotr: 100, | |
rtype: "circle", | |
color: "black", | |
offset: 20, | |
timelimit: 2000, | |
starttime: undefined, | |
elapsed: 0, | |
links: [], | |
charge: -3, | |
mass: 0, | |
r: 2, | |
t: 1, | |
x: 90, | |
y: 50, | |
vx: 0, | |
vy: 0, | |
scale: 1, | |
move: false, | |
} | |
, { | |
id: 4, | |
group: 1, | |
rotr: 100, | |
rtype: "circle", | |
color: "grey", | |
offset: 20, | |
timelimit: 2000, | |
starttime: undefined, | |
elapsed: 0, | |
scale: 1, | |
move: false, | |
links: [], | |
charge: -2, | |
mass: 0, | |
r: 2, | |
t: 1, | |
x: 10, | |
y: 50, | |
vx: 0, | |
vy: 0, | |
} | |
] | |
var nodes = [] | |
nodes = [nodesCollection[0], | |
nodesCollection[1], | |
nodesCollection[2], | |
nodesCollection[3], | |
nodesCollection[4], | |
] | |
var links = nodes | |
.reduce(function(a, b, i, v) { | |
var ls = b.links | |
.filter(function(obj) { | |
return (nodes[obj.target] !== undefined) | |
}) | |
var ln = ls.map(function(d) { | |
return { | |
source: nodes[d.source], | |
target: nodes[d.target], | |
} | |
}) | |
return a.concat(ln) | |
}, []) | |
// =================================== voronoi | |
// create the Voronoi diagram: partitioning of a plane into regions based on distance to points in a specific subset of the plane | |
var getSeeds = function getSeeds(x0, y0, x1, y1, vx, vy) { | |
for (var i = 0, r = []; i < n; ++i) | |
r[i] = { | |
x: x0 + Math.random() * (x1 - x0), | |
y: y0 + Math.random() * (y1 - y0), | |
vx: vx || 0, | |
vy: vy || 0, | |
r: 0.5, | |
} | |
return r | |
} | |
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
/* ------------------ */ | |
/* index-elems.js */ | |
/* ------------------ */ | |
// ==================== lanes | |
var drawLanesSimulation = function drawLanesSimulation() { // drawLanesSimulation | |
simulationRolls | |
.on("tick", function() { | |
tickRollsForce(this.alpha()) | |
redrawLanesDiagram() | |
}) | |
.on("end", function() { | |
}) | |
} | |
var drawLanesDiagram = function drawLanesDiagram() { // drawLanesDiagram | |
var linkGroup = d3.select('svg').selectAll('g.links').data(['links']).enter().append("g").attr("class", "links") | |
var linkElements = d3.select('svg').select("g.links").selectAll("line").data(links) | |
linkElements.enter().append("line").call(drawLink) | |
linkElements.call(drawLink) | |
linkElements.exit().remove() | |
var nodeGroup = d3.select('svg').selectAll('g.nodes').data(['nodes']).enter().append("g").attr("class", "nodes") | |
var rectElements = d3.select('svg').select("g.nodes").selectAll("rect").data(nodes, function(d) { return d.id }) | |
rectElements.enter().append("rect").call(drawNodeRect) | |
rectElements.call(drawNodeRect) | |
rectElements.exit().remove() | |
var nodeElements = d3.select('svg').select("g.nodes").selectAll("circle").data(nodes, function(d) { return d.id }) | |
nodeElements.enter().append("circle").call(drawNodeCircle) | |
nodeElements.call(drawNodeCircle) | |
nodeElements.exit().remove() | |
var textElements = d3.select('svg').select("g.nodes").selectAll("text").data(nodes, function(d) { return d.id }) | |
textElements.enter().append("text").call(drawNodeText) | |
textElements.call(drawNodeText) | |
textElements.exit().remove() | |
} | |
var redrawLanesDiagram = function redrawLanesDiagram() { // redrawLanesDiagram | |
// nodes have been redefined in the simulation | |
var linkGroup = d3.select('svg').selectAll('g.links').data(['links']).enter().append("g").attr("class", "links") | |
var linkElements = d3.select('svg').select("g.links").selectAll("line").data(links) | |
linkElements.enter().append("line").call(redrawLink) | |
linkElements.call(redrawLink) | |
linkElements.exit().remove() | |
var nodeGroup = d3.select('svg').selectAll('g.nodes').data(['nodes']).enter().append("g").attr("class", "nodes") | |
var rectElements = d3.select('svg').select("g.nodes").selectAll("rect").data(nodes, function(d) { return d.id }) | |
rectElements.enter().append("rect").call(redrawNodeRect) | |
rectElements.call(redrawNodeRect) | |
rectElements.exit().remove() | |
var nodeElements = d3.select('svg').select("g.nodes").selectAll("circle").data(nodes, function(d) { return d.id }) | |
nodeElements.enter().append("circle").call(redrawNodeCircle) | |
nodeElements.call(redrawNodeCircle) | |
nodeElements.exit().remove() | |
var textElements = d3.select('svg').select("g.nodes").selectAll("text").data(nodes, function(d) { return d.id }) | |
textElements.enter().append("text").call(redrawNodeText) | |
textElements.call(redrawNodeText) | |
textElements.exit().remove() | |
} | |
function drawNodeRect(nodeRect) { // drawNodeRect | |
nodeRect | |
.attr("x", function(d) { return xa(d.x - d.r / 8) }) | |
.attr("y", function(d) { return ya(d.y) - (height / 2) }) // ya(d.y - d.r) }) | |
.attr("height", function (d) { return height }) // xa(2 * d.r) }) | |
.attr("width", function (d) { return ya(d.r / 4) }) | |
.attr("stroke-width", 1) | |
.style("stroke", "grey") | |
.style("fill", function(d) { return d.color }) | |
} | |
function redrawNodeRect(nodeRect) { // redrawNodeRect | |
nodeRect | |
.attr("x", function(d) { return xa(d.x - d.r / 8) }) | |
.attr("y", function(d) { return ya(d.y) - (height / 2) }) // ya(d.y - d.r) }) | |
.attr("height", function (d) { return height }) // xa(2 * d.r) }) | |
.attr("width", function (d) { return ya(d.r / 4) }) | |
.style("fill", function(d) { return "transparent" }) // d.color | |
.style("stroke", "transparent") // grey | |
} | |
function drawNodeText(nodeText) { // drawNodeText | |
nodeText | |
.attr("x", function(d) { return xa(d.x) }) | |
.attr("y", function(d) { return ya(d.y) }) | |
.text(function(d) { return "" + Math.round(xa(d.x)) + ":" + Math.round(ya(d.y))}) | |
.style("font-size", function(d) { return ma(d.t) }) | |
.style("font-family", "sans-serif") | |
.style("fill", "white") | |
.style("text-anchor", "middle") | |
} | |
function redrawNodeText(nodeText) { // redrawNodeText | |
nodeText | |
.attr("x", function(d) { return xa(d.x) }) | |
.attr("y", function(d) { return ya(d.y) }) | |
.text(function(d) { return "" + Math.round(xa(d.x)) + ":" + Math.round(ya(d.y))}) | |
.style("font-size", function(d) { return ma(d.t) }) | |
.style("fill", "transparent") // white | |
} | |
function drawLink(link) { // drawLink | |
link | |
.attr("x1", function(d) { return xa(d.source.x) }) | |
.attr("y1", function(d) { return ya(d.source.y) }) | |
.attr("x2", function(d) { return xa(d.target.x) }) | |
.attr("y2", function(d) { return ya(d.target.y) }) | |
.attr("stroke-width", 1) | |
.style("stroke", "red") | |
} | |
function redrawLink(link) { // redrawLink | |
link | |
.attr("x1", function(d) { return xa(d.source.x) }) | |
.attr("y1", function(d) { return ya(d.source.y) }) | |
.attr("x2", function(d) { return xa(d.target.x) }) | |
.attr("y2", function(d) { return ya(d.target.y) }) | |
.style("stroke", "transparent") // grey | |
.style("fill", function(d) { return "transparent" }) | |
} | |
function drawNodeCircle(nodeCircle) { // drawNodeCircle | |
nodeCircle | |
.attr("cx", function(d) { return xa(d.x) }) | |
.attr("cy", function(d) { return ya(d.y) }) | |
.attr("r", function(d) { return ma(d.r) }) | |
.style("fill", function(d) { return d.color }) | |
.call(d3.drag() | |
.on("start", dragstarted) | |
.on("drag", dragged) | |
.on("end", dragended)) | |
} | |
function redrawNodeCircle(nodeCircle) { // redrawNodeCircle | |
nodeCircle | |
.attr("cx", function(d) { return xa(d.x) }) | |
.attr("cy", function(d) { return ya(d.y) }) | |
.attr("r", function(d) { return ma(d.r) }) | |
.style("fill", function(d) { return "transparent" }) // d.color | |
.call(d3.drag() | |
.on("start", dragstarted) | |
.on("drag", dragged) | |
.on("end", dragended)) | |
} | |
// ==================== rings - voro | |
var drawVoroSimulation = function drawVoroSimulation() { // drawVoroSimulation | |
simulationVoro | |
.on("tick", function() { | |
contentionForce(this.alpha(), seeds, seedsArea) | |
tickVoroForce(this.alpha()) | |
redrawVoroDiagam() | |
}) | |
.on("end", function() { | |
}) | |
} | |
var drawVoroDiagam = function drawVoroDiagam() { // drawVoroDiagam | |
var rings = polygons.map(function(d) {return inscribeTriangle(xa(d[0][0]), ya(d[0][1]), xa(d[1][0]), ya(d[1][1]), xa(d[2][0]), ya(d[2][1]))}) | |
var rs = rings.map(function(d) { return d.radius }) | |
stateRing.radiusMin = Math.min(...rs) | |
stateRing.radiusMax = Math.max(...rs) | |
var seedsGroup = d3.select('svg').selectAll('g.seeds').data(['g_seeds']).enter().append("g").attr("class", "seeds") | |
var seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) | |
seedElements.enter().append("circle").call(drawSeed) | |
seedElements.call(drawSeed) | |
seedElements.exit().remove() | |
var polygonsGroup = d3.select('svg').selectAll('g.polygons').data(['g_polygons']).enter().append("g").attr("class", "polygons") | |
var polygonElements = d3.select('svg').select("g.polygons").selectAll("path").data(polygons) | |
polygonElements.enter().append("path").call(drawPolygon); | |
polygonElements.call(drawPolygon) | |
polygonElements.exit().remove() | |
var ringsGroup = d3.select('svg').selectAll('g.rings').data(['g_rings']).enter().append("g").attr("class", "rings") | |
var ringElements = d3.select('svg').select("g.rings").selectAll("circle").data(rings) | |
ringElements.enter().append("circle").call(drawRing) | |
ringElements.call(drawRing) | |
ringElements.exit().remove() | |
} | |
var redrawVoroDiagam = function redrawVoroDiagam() { // redrawVoroDiagam | |
var rings = polygons.map(function(d) {return inscribeTriangle(xa(d[0][0]), ya(d[0][1]), xa(d[1][0]), ya(d[1][1]), xa(d[2][0]), ya(d[2][1]))}) | |
var rs = rings.map(function(d) { return d.radius }) | |
stateRing.radiusMin = Math.min(...rs) | |
stateRing.radiusMax = Math.max(...rs) | |
var seedsGroup = d3.select('svg').selectAll('g.seeds').data(['g_seeds']).enter().append("g").attr("class", "seeds") | |
var seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) | |
seedElements = d3.select('svg').select("g.seeds").selectAll("circle").data(seeds) | |
seedElements.enter().append("circle").call(redrawSeed) | |
seedElements.call(redrawSeed); | |
seedElements.exit().remove() | |
var polygonsGroup = d3.select('svg').selectAll('g.polygons').data(['g_polygons']).enter().append("g").attr("class", "polygons") | |
var polygonElements = d3.select('svg').select("g.polygons").selectAll("path").data(polygons) | |
polygonElements.enter().append("path").call(redrawPolygon); | |
polygonElements.call(redrawPolygon) | |
polygonElements.exit().remove() | |
// projection | |
var ringsGroup = d3.select('svg').selectAll('g.rings').data(['g_rings']).enter().append("g").attr("class", "rings") | |
var ringElements = d3.select('svg').select("g.rings").selectAll("circle").data(rings) | |
ringElements.enter().append("circle").call(redrawRing) | |
ringElements.call(redrawRing) | |
ringElements.exit().remove() | |
} | |
function drawSeed(seed) { // drawSeed | |
seed | |
.attr("cx", function(d, i) { return d.x} ) | |
.attr("cy", function(d, i) { return d.y} ) | |
.attr("r", function(d, i) { return d.r }) | |
.style("fill", function(d, i) { return 'transparent' }) | |
.attr("stroke", "red") | |
} | |
function redrawSeed(seed) { // redrawSeed | |
seed | |
.attr("cx", function(d, i) { return xa(d.x)} ) | |
.attr("cy", function(d, i) { return ya(d.y)} ) | |
.attr("r", function(d, i) { return ma(d.r) }) | |
.style("fill", function(d, i) { return 'transparent' }) // gold | |
.attr("stroke", "transparent ") // "transparent" | |
} | |
function drawPolygon(polygon) { // drawPolygon | |
polygon | |
.attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; }) | |
.attr("stroke", "#000") | |
.style("fill", function(d, i) { return 'transparent' }) | |
} | |
function redrawPolygon(polygon) { // redrawPolygon | |
polygon | |
.attr("d", function(d) { | |
// return d ? "M" + d.join("L") + "Z" : null; }) | |
return d ? "M" + d.map(function(p) {return [xa(p[0]), ya(p[1])]}).join("L") + "Z" : null; }) | |
.attr("stroke", "transparent") // transparent brown | |
.style("fill", function(d, i) { return 'transparent' }) // transparent | |
} | |
function drawRing(ring) { // drawRing | |
ring | |
.attr('cx', function(d) {return d[0] }) | |
.attr('cy', function(d) {return d[1] }) | |
.attr('r', function(d) {return d.radius }) | |
.style("fill", function(d, i) { return 'transparent' }) | |
.attr("stroke", "grey") | |
} | |
function redrawRing(ring) { // redrawRing - no projection | |
ring | |
.attr('cx', function(d) {return d[0] }) | |
.attr('cy', function(d) {return d[1] }) | |
.attr('r', function(d) {return d.radius }) | |
.style("fill", function(d, i) { return 'transparent' }) // transparent // gold | |
.attr("stroke", function(d) { | |
var d = Math.floor(((d.radius - stateRing.radiusMin) / (stateRing.radiusMax - stateRing.radiusMin)) * 256) | |
var c = d3.interpolatePlasma(d / 256) | |
return c }) | |
} | |
function inscribeTriangle(x0, y0, x1, y1, x2, y2) { | |
var x01 = x0 - x1, y01 = y0 - y1, | |
x02 = x0 - x2, y02 = y0 - y2, | |
x12 = x1 - x2, y12 = y1 - y2, | |
l01 = Math.sqrt(x01 * x01 + y01 * y01), | |
l02 = Math.sqrt(x02 * x02 + y02 * y02), | |
l12 = Math.sqrt(x12 * x12 + y12 * y12), | |
k0 = l01 / (l01 + l02), | |
k1 = l12 / (l12 + l01), | |
center = segmentIntersection(x0, y0, x1 - k0 * x12, y1 - k0 * y12, x1, y1, x2 + k1 * x02, y2 + k1 * y02); | |
center.radius = Math.sqrt((l02 + l12 - l01) * (l12 + l01 - l02) * (l01 + l02 - l12) / (l01 + l02 + l12)) / 2; | |
return center; | |
} | |
function segmentIntersection(x0, y0, x1, y1, x2, y2, x3, y3) { | |
var x02 = x0 - x2, y02 = y0 - y2, | |
x10 = x1 - x0, y10 = y1 - y0, | |
x32 = x3 - x2, y32 = y3 - y2, | |
t = (x32 * y02 - y32 * x02) / (y32 * x10 - x32 * y10); | |
return [x0 + t * x10, y0 + t * y10]; | |
} | |
// ==================== common | |
function drawSvg(svgElement) { // drawNodeRect | |
svgElement | |
.attr("width", widthPct) | |
.attr("height", heightPct) | |
.style('border', '1px solid lightgrey') | |
.on("touchmove mousemove", function() {mousemove(this)}) | |
.on("mouseleave", function() {mouseleave(this)}) | |
.on("mousedown", function() {mousedown(this)}) | |
.on("touchstart", function() {touchstart(this)}) | |
.on("touchmove", function() {touchmove(this)}) | |
.on("mouseup", function() {mouseup(this)}) | |
.on("touchend", function() {touchend(this)}) | |
} |
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
/* ------------------ */ | |
/* index-lanes-tick.js */ | |
/* ------------------ */ | |
// ---------------- force field | |
function tickRollsForce(alpha) { | |
hpct = parseInt(svgElement.style("width"), 10) / 100 | |
vpct = parseInt(svgElement.style("height"), 10) / 100 | |
mpct = hpct + vpct / 2 | |
var dir = 0 | |
var k = 1 | |
var p = 0.01 | |
var c = 50 | |
var q = 1 | |
if (moving == 0) { | |
for (var i = 0; i < nodes.length; i++) { | |
if (nodes[i].fx === undefined) nodes[i].vxTmp = nodes[i].vx, nodes[i].fx = nodes[i].x, nodes[i].fxTmp = 'set' | |
if (nodes[i].fy === undefined) nodes[i].vyTmp = nodes[i].vy, nodes[i].fy = nodes[i].y, nodes[i].fyTmp = 'set' | |
} | |
} | |
if (moving == 1) { | |
for (var i = 0; i < nodes.length; i++) { | |
if (nodes[i].fxTmp === 'set') nodes[i].vx = nodes[i].vxTmp, nodes[i].fx = undefined, nodes[i].fxTmp = undefined | |
if (nodes[i].fyTmp === 'set') nodes[i].vy = nodes[i].vyTmp, nodes[i].fy = undefined, nodes[i].fyTmp = undefined | |
} | |
tickingNodes(alpha) | |
} | |
function tickingNodes(alpha) { // do when force is active | |
for (var i = 0, n = nodes.length, node; i < n; ++i) { | |
node = nodes[i]; | |
if (node.color == 'red') { // red | |
q = (node.x - c ) / c // -1 | 0 | +1 | |
node.vx = node.vx - q * p | |
node.x = node.x + node.vx | |
node.fy = node.y | |
} | |
if (node.color == 'blue') { // blue | |
q = (node.x - c ) / c // -1 | 0 | +1 | |
node.vx = node.vx - q * p | |
node.x = node.x + node.vx | |
node.fy = node.y | |
} | |
if (node.color == 'green') { // green | |
q = (node.x - c ) / c // -1 | 0 | +1 | |
node.vx = node.vx - q * p | |
node.x = node.x + node.vx | |
node.fy = node.y | |
} | |
if (node.color == 'black') { // black | |
node.fx = node.x | |
node.fy = node.y | |
} | |
if (node.color == 'grey') { // grey | |
node.fx = node.x | |
node.fy = node.y | |
} | |
} | |
} | |
} | |
function force3(alpha) { | |
node = nodes[2]; | |
if (node.vx > 0 && node.x >= 500) node.vx = -node.vx | |
if (node.vx < 0 && node.x <= 100) node.vx = -node.vx | |
} | |
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
/* ------------------ */ | |
/* index-rings-tick.js */ | |
/* ------------------ */ | |
function tickVoroForce(alpha) { // ticking force | |
hpct = parseInt(svgElement.style("width"), 10) / 100 | |
vpct = parseInt(svgElement.style("height"), 10) / 100 | |
mpct = hpct + vpct / 2 | |
var dir = 0 | |
var k = 1 | |
var p = 0.01 | |
var c = 50 | |
var q = 1 | |
if (moving == 0) { | |
for (var i = 0; i < seeds.length; i++) { | |
if (seeds[i].fx === undefined) seeds[i].vxTmp = seeds[i].vx, seeds[i].fx = seeds[i].x, seeds[i].fxTmp = 'set' | |
if (seeds[i].fy === undefined) seeds[i].vyTmp = seeds[i].vy, seeds[i].fy = seeds[i].y, seeds[i].fyTmp = 'set' | |
} | |
} | |
if (moving == 1) { | |
for (var i = 0; i < seeds.length; i++) { | |
if (seeds[i].fxTmp === 'set') seeds[i].vx = seeds[i].vxTmp, seeds[i].fx = undefined, seeds[i].fxTmp = undefined | |
if (seeds[i].fyTmp === 'set') seeds[i].vy = seeds[i].vyTmp, seeds[i].fy = undefined, seeds[i].fyTmp = undefined | |
} | |
tickingSeeds(alpha) | |
} | |
} | |
function tickingSeeds(alpha) { // tick when force is active | |
for (i = 0; i < seeds.length; i++) { | |
var randNormal = d3.randomNormal(1.3, 2) | |
var randNormal2 = d3.randomNormal(0.5, 1.8) | |
seeds[i].vx = randNormal() * (Math.random() - 0.5) | |
seeds[i].vy += randNormal2() | |
} | |
seedsArea = {x0: nodes[0].x, y0: 0, x1:nodes[1].x, y1: 100} | |
extent = [[seedsArea.x0 + 1, seedsArea.y0 + 1], [seedsArea.x1 + 1 , seedsArea.y1 - 1]] // abs | |
voro = d3.voronoi().extent(extent) | |
dia = voro(seeds.map(function(d) {return [d.x, d.y]})) // pass an array of coordinates [[,], [,]] | |
polygons = dia.triangles() | |
redrawVoroDiagam() // REDRAW DIAGRAM | |
} | |
function contentionForce(alpha, items, area) { // contentionForce | |
for (var i = 0, n = items.length, node, k = alpha * 0.1; i < n; ++i) { | |
var item = items[i] | |
if (item.vx > 0 && item.x >= area.x1) item.vx = -item.vx | |
if (item.vx< 0 && item.x <= area.x0) item.vx = -item.vx | |
if (item.vy > 0 && item.y >= area.y1) item.vy = -item.vy | |
if (item.vy < 0 && item.y <= area.y0) item.vy = -item.vy | |
if (Math.abs(item.vx) < 0.05) item.vx *= 2 | |
if (Math.abs(item.vy) < 0.05) item.vy *= 2 | |
if (Math.abs(item.vx) > 0.5) item.vx /= 2 | |
if (Math.abs(item.vy) > 0.5) item.vy /= 2 | |
} | |
} |
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
<html> | |
<meta http-equiv="content-type" content="text/html; charset=utf-8" /> | |
<body> | |
<script src="https://d3js.org/d3.v4.js"></script> | |
<!-- | |
<script src="d3.v4.js"></script> | |
--> | |
<script src="index-data.js" charset="utf-8"></script> | |
<script src="index-elems.js" charset="utf-8"></script> | |
<script src="index-controls.js" charset="utf-8"></script> | |
<script src="index-lanes-tick.js" charset="utf-8"></script> | |
<script src="index-rings-tick.js" charset="utf-8"></script> | |
<script src="index.js" charset="utf-8"></script> | |
</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
/* ------------------ */ | |
/* index.js */ | |
/* ------------------ */ | |
// STATE | |
var stateRing = {} | |
var widthPct = '80%' //'100%' // 640 // | |
var heightPct = '80%' // '100%' // 480 // | |
var animationStep = 500; | |
var centerx = widthPct / 2 | |
var centery = heightPct / 2 | |
var moving = 1 | |
var mousePosition = [] | |
// RENDER | |
var svgContainer = d3.select("body").selectAll('svg').data(['svg']) | |
var svgElement = svgContainer.enter().append("svg").attr("id", "svg").attr("class", "svg").call(drawSvg) | |
// relative per one factors | |
var hpct = parseInt(svgElement.style("width"), 10) / 100 | |
var vpct = parseInt(svgElement.style("height"), 10) / 100 | |
var mpct = hpct + vpct / 2 | |
// rel to abs coordinantes | |
var xa = function xa (d) { return d * hpct } | |
var ya = function ya (d) { return d * vpct } | |
var ma = function ma (d) { return d * mpct } | |
// abs coordinantes | |
var width = parseInt(svgElement.style("width"), 10) | |
var height = parseInt(svgElement.style("height"), 10) | |
stateRing.radiusMax = 0 | |
stateRing.radiusMin = 0 | |
stateRing.color = d3.interpolatePlasma | |
// console.log(color(3)) // 256 | |
// color( ((3*r)%10 / 10) + (Math.random()* 3 /10)) | |
// ==================================================================== simulationRolls | |
drawLanesDiagram() | |
var simulationRolls = d3.forceSimulation() | |
.alpha(1) // tick increments the current alpha by (alphaTarget - alpha) � alphaDecay | |
// tick then invokes each registered force, passing the new alpha | |
// tick decrements each node�s velocity by velocity � velocityDecay | |
// tick increments each node�s position by velocity | |
.alphaMin(0.001) // (0.001) | |
.alphaDecay(0.000228) // (0.0228) | |
.alphaTarget(0) | |
.velocityDecay(0.000) // (0.4) // each node�s velocity is multiplied by 1 - decay | |
simulationRolls | |
.nodes(nodes) | |
// .force("link", d3.forceLink().id(function(d) { return d.index; })) | |
// .force("charge", d3.forceManyBody().strength(-20)) // positive: attraction | |
.force("charge", d3.forceManyBody().strength(function(d) { return d.charge })) // positive: attraction | |
.force("collide", d3.forceCollide(function(d) {return 2 * d.r}).iterations(4)) // | |
// .force("center", d3.forceCenter(50, 50)) // | |
simulationRolls | |
.force("link") | |
// .links(links).strength(0) // .iterations(1).distance(5) | |
drawLanesSimulation() | |
// ==================================================================== voro sites | |
// ==================================================================== voro sites | |
// var voro = d3.voronoi().extent([[nodes[0].x, 1], [nodes[0].y, height - 1]]) | |
var voro // voronoi | |
var dia // voronoi diagram | |
var polygons // polygons on dia sites | |
var rings // circumscribed circles in polygons | |
var extent = [] // extend of diagram | |
var seedsArea = {} // {x0, y0, x1, y1} area where the seeds are located | |
var n = 100, // number of sites | |
seeds = new Array(n), // also seeds or generators) | |
color = "blue", // color of the ... | |
radius = 10 // radius of the ... | |
seedsArea = {x0: nodes[0].x, y0: 0, x1:nodes[1].x, y1: 100} | |
extent = [[seedsArea.x0 + 1, seedsArea.y0 + 1], [seedsArea.x1 + 1 , seedsArea.y1 - 1]] | |
voro = d3.voronoi().extent(extent) | |
seeds = getSeeds(seedsArea.x0, seedsArea.y0, seedsArea.x1, seedsArea.y1, 0, 0) // get seeds {x, y, vx, vy} // in data for simulation | |
dia = voro(seeds.map(function(d) {return [d.x, d.y]})) // pass an array of coordinates [[,], [,]] | |
polygons = dia.triangles() | |
rings = polygons.map(function(d) {return inscribeTriangle(d[0][0], d[0][1],d[1][0], d[1][1],d[2][0], d[2][1])}) | |
drawVoroDiagam() | |
var simulationVoro = d3.forceSimulation() | |
.alpha(1) // tick increments the current alpha by (alphaTarget - alpha) � alphaDecay | |
// tick then invokes each registered force, passing the new alpha | |
// tick decrements each node�s velocity by velocity � velocityDecay | |
// tick increments each node�s position by velocity | |
.alphaMin(0.001) // (0.001) | |
.alphaDecay(0.000228) // (0.0228) | |
.alphaTarget(0) | |
.velocityDecay(0.000) // (0.4) // each node�s velocity is multiplied by 1 - decay | |
// .initialize() | |
simulationVoro | |
.nodes(seeds) | |
.force("link", d3.forceLink().id(function(d) { return d.index; })) | |
// .force("charge", d3.forceManyBody().strength(-5)) // positive: attraction | |
// .force("charge", d3.forceManyBody().strength(function(d) { return d.charge })) // positive: attraction | |
.force("collide", d3.forceCollide(function(d) {return 2 * d.r}).iterations(4)) // | |
// .force("center", d3.forceCenter(50, 50)) // | |
simulationVoro | |
.force("link") | |
// .links(links).strength(0.5).iterations(1).distance(15) | |
drawVoroSimulation() | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment