[ Launch: blob pointers ] 4689087 by enjalot
-
-
Save enjalot/4689087 to your computer and use it in GitHub Desktop.
blob pointers
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
{"description":"blob pointers","endpoint":"","display":"svg","public":true,"require":[],"fileconfigs":{"config.json":{"default":true,"vim":false,"emacs":false,"fontSize":12},"inlet.js":{"default":true,"vim":false,"emacs":false,"fontSize":12},"_.md":{"default":true,"vim":false,"emacs":false,"fontSize":12},"leap.js":{"default":true,"vim":false,"emacs":false,"fontSize":12}},"play":false,"loop":false,"restart":true,"autoinit":true,"pause":true,"loop_type":"period","bv":false,"nclones":15,"clone_opacity":0.4,"duration":3000,"ease":"linear","dt":0.01,"editor_editor":{"coffee":false,"vim":true,"emacs":false,"width":853,"height":627,"hide":true},"fullscreen":false,"thumbnail":"http://i.imgur.com/SwaSWf5.png"} |
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
//appearance | |
var rx = 15; | |
var ry = 15; | |
var boid_fill = "#05A212"; | |
var boid_fill_opacity = 0.1232; | |
var boid_path_fill = "#007718"; | |
var boid_path_opacity = 0.1; | |
//number of boids | |
var n = 10; | |
var svg = d3.select("svg"); | |
tributary.updated = []; | |
tributary.events.off("leap"); | |
tributary.events.on("leap", function(d) { | |
//console.log(d); | |
var len = d.pointables.length; | |
if(len > n) len = n; | |
tributary.updated = d3.range(n).map(function() {return 0;}) | |
//TODO: do this d3 selection style | |
for(var i = len; i--;) { | |
var pointer = d.pointables[i]; | |
var pos = pointer.tipPosition; | |
//console.log(pos); | |
//cube.position.set(pos[0], pos[1], pos[2]); | |
tributary.pointers[i].x = 2*pos[0] + tributary.sw/2; | |
tributary.pointers[i].y = -pos[1] + tributary.sh/2; | |
tributary.updated[i] = 1; | |
} | |
//not using the t parameter | |
tributary.run(svg, 0); | |
}) | |
var filler = d3.scale.linear() | |
//.domain([-max_speed, max_speed]) | |
.domain([0, tributary.sw/2]) | |
.interpolate(d3.interpolateLab) | |
.range(["#FF4646", "#00CCFF"]); | |
var join = { | |
//r: desired_separation | |
r: 699 | |
} | |
//some defaults | |
var w = tributary.sw; //get screen width and height | |
var h = tributary.sh; | |
tributary.init = function(g) { | |
//setup the nodes | |
/* | |
tributary.nodes = d3.range(n).map(function() { | |
var x = Math.random() * w, y = Math.random() * h; | |
var b = boid() | |
.position([Math.random() * w, Math.random() * h]) | |
.velocity([Math.random() * 2 - 1, Math.random() * 2 - 1]) | |
.gravityCenter(mouse) | |
return b; | |
}); | |
*/ | |
tributary.pointers = d3.range(n).map(function() { | |
var x = Math.random() * w, y = Math.random() * h; | |
var p = {x:x, y:y} | |
return p; | |
}) | |
tributary.updated = d3.range(n).map(function() {return 0;}) | |
/* | |
var vertices = tributary.nodes.map(function(boid) { | |
return boid(tributary.nodes); | |
}); | |
*/ | |
//render the boids as ellipses | |
var gs = g.selectAll("g.node") | |
.data(tributary.pointers) | |
.enter().append("g").classed("node", true); | |
//need a path for each potential pair | |
var paths = g.selectAll("path.lava") | |
.data(d3.range(n*n)) | |
.enter().append("path") | |
.attr("class", function(d,i) { | |
var j = i % n; | |
var k = parseInt(i/n); | |
return "lava" + j + "_" + k; | |
}) | |
.style("fill", boid_path_fill) | |
.style("fill-opacity", boid_path_opacity); | |
/* | |
//mouse interaction stuff | |
function nullGravity() { | |
mouse[0] = mouse[1] = null; | |
} | |
d3.select("svg").on("mousemove", function() { | |
var m = d3.mouse(this); | |
mouse[0] = m[0]; | |
mouse[1] = m[1]; | |
last_mouse[0] = m[0]; | |
last_mouse[1] = m[1]; | |
}) | |
.on("mouseout", nullGravity); | |
*/ | |
}; | |
//update the simulation while the play button is running. | |
tributary.run = function(g,t) { | |
//var len = tributary.nodes.length; | |
var len = tributary.pointers.length; | |
var b, j, pos, npos; | |
g.selectAll("path") | |
//turn off all paths (they will be turned on iff in range) | |
.style("display", "none") | |
//restyle all paths (so we can see color changes when scrubbing, this is less efficient) | |
.style("fill", boid_path_fill) | |
.style("fill-opacity", boid_path_opacity) | |
for (var i = -1; ++i < len;) { | |
//b = tributary.nodes[i]; | |
p = tributary.pointers[i]; | |
//TODO: get boid neighbors with quadtree | |
//pos = b.position(); | |
pos = p; | |
for(j=0; j < len; j++) { | |
if(i === j) { continue; } | |
//npos = tributary.nodes[j].position(); | |
npos = tributary.pointers[j]; | |
if(dist(pos, npos) < join.r) {//desired_separation) { | |
//close enough | |
update(g, i + "_" + j, {x: pos.x, y: pos.y, r: 26}, | |
{x: npos.x, y: npos.y, r: 20}); | |
} | |
} | |
} | |
}; | |
function dist(a,b) { | |
var dx = a.x - b.x, | |
dy = a.y - b.y; | |
//if (dx > w / 2) dx = w - dx; | |
//if (dy > h / 2) dy = h - dy; | |
return Math.sqrt(dx * dx + dy * dy); | |
} | |
var update = function(g, id, a, b) { | |
var originDistance = a.r - b.r; | |
a.area = Math.PI * Math.pow(a.r, 2); | |
b.area = Math.PI * Math.pow(b.r, 2); | |
var afterCircleArea = a.area - b.area; | |
var distance = calculateDistance(a,b); | |
var distanceDiff = distance - originDistance; | |
if(distanceDiff < 1) { distanceDiff = 1 } | |
var dontdraw = false; | |
if(distance > 2*join.r + a.r + b.r) { | |
//console.log("MAY DAY") | |
dontdraw = true; | |
} | |
var inds = id.split("_"); | |
if(!tributary.updated[+inds[0]] || !tributary.updated[+inds[1]]) | |
dontdraw = true; | |
var angle = calculateAngle(a,b); | |
b.h = 0; | |
b.k = 0 - a.r + b.r - distanceDiff; | |
//console.log(b.k, join.r) | |
var triangleA = a.r + join.r; // Side a | |
var triangleB = b.r + join.r; // Side b | |
var triangleC = Math.abs(b.k - 0); // Side c | |
var triangleP = (triangleA + triangleB + triangleC) / 2; // Triangle half perimeter | |
var triangleArea = Math.sqrt(triangleP * (triangleP - triangleA) * (triangleP - triangleB) * (triangleP - triangleC)); // Triangle area | |
if (triangleC >= triangleA) | |
{ | |
var triangleH = 2 * triangleArea / triangleC; // Triangle height | |
var triangleD = Math.sqrt(Math.pow(triangleA, 2) - Math.pow(triangleH, 2)); // Big circle bisection of triangleC | |
} | |
else | |
{ | |
var triangleH = 2 * triangleArea / triangleA; // Triangle height | |
var triangleD = Math.sqrt(Math.pow(triangleC, 2) - Math.pow(triangleH, 2)); // Small circle bisection of triangleA | |
} | |
a.tan = triangleH / triangleD; | |
a.angle = Math.atan(a.tan); | |
a.sin = Math.sin(a.angle); | |
a.intersectX = a.sin * a.r; | |
a.cos = Math.cos(a.angle); | |
a.intersectY = a.cos * a.r; | |
join.x = 0 + a.sin * (a.r + join.r); | |
join.y = 0 - a.cos * (a.r + join.r); | |
var coord1 = { | |
x: -a.intersectX, | |
y: -a.intersectY | |
}; | |
var coord2 = { | |
x: a.intersectX, | |
y: -a.intersectY | |
} | |
b.tan = (b.k - join.y) / (b.h - join.x); | |
b.angle = Math.atan(b.tan); | |
b.intersectX = join.x - Math.cos(b.angle) * (join.r); | |
b.intersectY = join.y - Math.sin(b.angle) * (join.r); | |
var lavaPathD = "M " + coord1.x + " " + coord1.y + " A " + a.r + " " + a.r + " 0 1 0 " + coord2.x + " " + coord2.y; | |
if (join.x - join.r <= 0 && b.k < join.y) | |
{ | |
var crossOverY = circleYFromX(join, 0); | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y + crossOverY); | |
lavaPathD += "m 0 -" + (crossOverY * 2); | |
} | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + b.intersectX + " " + b.intersectY; | |
var largeArcFlag = 1; | |
if (join.y < b.k) | |
{ | |
largeArcFlag = 0; | |
} | |
lavaPathD += "a " + b.r + " " + b.r + " 0 " + largeArcFlag + " 0 " + (b.intersectX * -2) + " 0"; | |
if (join.x - join.r <= 0 && b.k < join.y) | |
{ | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 0 " + (join.y - crossOverY); | |
lavaPathD += "m 0 " + (crossOverY * 2); | |
} | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y; | |
lavaPathD += "A " + join.r + " " + join.r + " 0 0 1 " + coord1.x + " " + coord1.y; | |
var lavaPath = g.select("path.lava" + id) | |
if(!dontdraw) { | |
lavaPath | |
.attr("transform", function() { | |
var translate = "translate(" + [a.x, a.y] + ")"; | |
var rotate = "rotate(" + [angle, 0, 0] + ")"; | |
return translate + rotate; | |
}) | |
.attr("d", lavaPathD) | |
.style("display", "") | |
} else { | |
lavaPath.style("display", "none"); | |
} | |
} | |
function calculateDistance(origin, point) { | |
var xx = point.x - origin.x; | |
var yy = point.y - origin.y; | |
return Math.sqrt(xx*xx + yy*yy) | |
} | |
function calculateAngle(origin, point) | |
{ | |
var tan = (point.y - origin.y) / (point.x - origin.x); | |
var angle = Math.atan(tan) / Math.PI * 180 + 90; | |
if (point.x < origin.x) | |
{ | |
angle += 180; | |
} | |
return angle; | |
} | |
function circleYFromX (circle, x) | |
{ | |
return Math.sqrt(Math.pow(circle.r, 2) - Math.pow(x - circle.x, 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
if(!tributary.leap) tributary.leap = {}; | |
// Support both the WebSocket and MozWebSocket objects | |
if ((typeof(WebSocket) == 'undefined') && | |
(typeof(MozWebSocket) != 'undefined')) { | |
WebSocket = MozWebSocket; | |
} | |
// Create the socket with event handlers | |
tributary.leap.init = function() { | |
if(tributary.ws) { | |
tributary.ws.close(); | |
} | |
console.log("Starting"); | |
//Create and open the socket | |
tributary.ws = new WebSocket("ws://localhost:6437/"); | |
ws = tributary.ws; | |
// On successful connection | |
ws.onopen = function(event) { | |
//document.getElementById("connection").innerHTML = "WebSocket connection open!"; | |
//$("#textoutput").html("Open...") | |
console.log("Open"); | |
}; | |
// On message received | |
ws.onmessage = function(event) { | |
tributary.events.trigger("leap", JSON.parse(event.data)); | |
}; | |
// On socket close | |
ws.onclose = function(event) { | |
ws = null; | |
} | |
//On socket error | |
ws.onerror = function(event) { | |
console.error("Received error"); | |
}; | |
} | |
tributary.leap.init(); | |
tributary.events.on("restart", function() { | |
tributary.leap.init(); | |
}) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment