-
Notifications
You must be signed in to change notification settings - Fork 1
/
collision.html
126 lines (103 loc) · 3.3 KB
/
collision.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
<!DOCTYPE html>
<meta charset="utf-8">
<body>
<script src="http://d3js.org/d3.v2.min.js?2.9.7"></script>
<script>
var width = 920,
height = 500;
var counter = -1;
var color = d3.scale.category10();
var quantity = 5; // 200
function makeColor() {
counter += 1;
return color(counter % 3);
}
var nodes = d3.range(quantity).map(function() { return {radius: Math.random() * 12 + 4, color: makeColor(), id : Math.random()}; }),
root = nodes[0];
console.log(nodes);
root.radius = 0;
root.fixed = true;
var force = d3.layout.force()
.gravity(0.05)
.charge(function(d, i) { return i ? 0 : 0; }) // was: return i ? 0 : 2000;
.nodes(nodes)
.size([width, height]);
force.start();
var svg = d3.select("body").append("svg:svg")
.attr("width", width)
.attr("height", height);
svg.selectAll("circle")
.data(nodes.slice(1), function (d) { return d.id; })
.enter().append("circle")
.attr("r", function(d) { return d.radius; })
.style("fill", function(d, i) { return d.color; });
force.on("tick", function(e) {
var q = d3.geom.quadtree(nodes),
i = 0,
n = nodes.length;
force.nodes(nodes);
force.start();
while (++i < n) q.visit(collide(nodes[i]));
circs = svg.selectAll("circle")
.on("click", function(d, i) {
//remove this node from the nodes list
//var nod = nodes[i]; // This is a shallow copy, or no copy at all. bad.
n = nodes[i];
nod1 = {color: n.color, radius: n.radius/2, id: Math.random(), x: n.x + n.radius, y: n.y + n.radius, weight: n.weight};
nod2 = {color: n.color, radius: n.radius/2, id: Math.random(), x: n.x - n.radius, y: n.y - n.radius, weight: n.weight};
//console.log(n);
//console.log(nod1);
//console.log(nod2);
// get rid of the node, and replace it with two half-sized ones
nodes.splice(i + 1, 1);
nodes.push(nod1);
nodes.push(nod2)
console.log(nodes);
})
.data(nodes.slice(1), function (d) { return d.id; });
circs
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; });
circs.enter().append("circle")
.attr("cx", function(d) { return d.x; })
.attr("cy", function(d) { return d.y; })
.attr("r", function(d) { return d.radius; })
.style("fill", function(d, i) { return makeColor(); });
circs.exit().remove();
});
//svg.on("mousemove", function() {
// var p1 = d3.mouse(this);
// root.px = p1[0];
// root.py = p1[1];
// force.resume();
//});
function addnode() {
for (i in d3.range(9)) {
nodes.push( {radius: Math.random() * 12 + 4, id: Math.random(), color: makeColor()} );
}
}
function collide(node) {
var r = node.radius + 16,
nx1 = node.x - r,
nx2 = node.x + r,
ny1 = node.y - r,
ny2 = node.y + r;
return function(quad, x1, y1, x2, y2) {
if (quad.point && (quad.point !== node)) {
var x = node.x - quad.point.x,
y = node.y - quad.point.y,
l = Math.sqrt(x * x + y * y), // distance between x and y
r = node.radius + quad.point.radius;
if (l < r) {
l = (l - r) / l * .5;
node.x -= x *= l; // x *= l; node.x -= x
node.y -= y *= l;
quad.point.x += x;
quad.point.y += y;
}
}
return x1 > nx2 || x2 < nx1 || y1 > ny2 || y2 < ny1;
};
}
</script>
<button id='zoomin' onclick='addnode()'>+</button>