Skip to content

Instantly share code, notes, and snippets.

@8one6
Created May 21, 2013 03:37
Show Gist options
  • Save 8one6/5617335 to your computer and use it in GitHub Desktop.
Save 8one6/5617335 to your computer and use it in GitHub Desktop.
Can you find the "true" cluster?

This page shows 55 points. 50 of them are placed randomly uniformly on the canvas. The remaining 5 are placed in a "cluster" somewhere on the canvas such that the expected density of the "cluster" is approximately 3 times higher than the density of the background noise. If you double click anywhere within the region that defines the "true" cluster, the cluster dots will turn red and will be ringed in red. If you miss, your "incorrect" guess region will be highlighted in blue.

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN"
"http://www.w3.org/TR/html4/strict.dtd">
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>D3 Playground</title>
<script src="http://d3js.org/d3.v3.min.js" charset="utf-8"></script>
<link rel="stylesheet" type="text/css" href="style.css" />
</head>
<body>
<script type="text/javascript">
function makeRandData(numPts) {
var myData = [];
for (var i = 0; i<numPts; i++) {
myData.push({
"x" : Math.random(),
"y" : Math.random()
});
}
return myData;
}
var clusterCx = Math.random();
var clusterCy = Math.random();
var clusterRad = 0.1;
function makeClusterData(cx, cy, numPts, radius) {
var myData = [];
for (var i = 0; i<numPts; i++) {
var radPct = Math.random();
var rad = Math.sqrt(radPct * radius * radius);
var angle = 2 * Math.PI * Math.random();
var x = cx + (rad * Math.cos(angle));
var y = cy + (rad * Math.sin(angle))
if (0 < x && x < 1 && 0 < y && y < 1) {
myData.push({
"x" : x,
"y" : y
});
}
}
return myData
}
var randData = makeRandData(50);
var clusterData = makeClusterData(clusterCx, clusterCy, 5, clusterRad);
var r = 4;
var pad = 30;
var h = 350;
var w = 350;
var th = h + (2*pad);
var tw = w + (2*pad);
var xScale = d3.scale.linear()
.domain([0,1])
.range([pad,pad+w]);
var yScale = d3.scale.linear()
.domain([0,1])
.range([pad+h,pad]);
var svg = d3.select("body").append("svg")
.attr("height", th)
.attr("width", tw);
var clusterCirclesGroup = svg.append("g");
var clusterCircles = clusterCirclesGroup.selectAll("circle")
.data(clusterData)
.enter()
.append("circle")
.attr("cx", function (d,i) { return xScale(d.x) })
.attr("cy", function (d,i) { return yScale(d.y) })
.attr("r", r)
.attr("class", "dot");
var randCirclesGroup = svg.append("g");
var randCircles = randCirclesGroup.selectAll("circle")
.data(randData)
.enter()
.append("circle")
.attr("cx", function (d,i) { return xScale(d.x) })
.attr("cy", function (d,i) { return yScale(d.y) })
.attr("r", r)
.attr("class", "dot");
var squareBackgroundGroup = svg.append("g");
var squareBackground = squareBackgroundGroup
.append("rect")
.attr("x", 0)
.attr("y", 0)
.attr("height", th)
.attr("width", tw)
.attr("class", "squareBackground")
.on("dblclick", miss);
var clusterCircleOutlineGroup = svg.append("g");
var clusterCircleOutline = clusterCircleOutlineGroup
.append("ellipse")
.attr("cx", xScale(clusterCx))
.attr("cy", yScale(clusterCy))
.attr("rx", w * clusterRad)
.attr("ry", h * clusterRad)
.attr("class", "clusterOutline")
.on("dblclick", hit);
function hit (d,i) {
clusterCircleOutline
.transition()
.style("opacity", 1)
.duration(1000)
clusterCircles
.transition()
.style("fill", "#F00")
.duration(1000)
}
function miss (d,i) {
var here = d3.mouse(this)
svg
.append("ellipse")
.attr("cx", here[0])
.attr("cy", here[1])
.attr("rx", 0)
.attr("ry", 0)
.attr("class", "miss")
.transition()
.attr("rx", h * clusterRad)
.attr("ry", w * clusterRad)
}
</script>
</body>
</html>
svg .dot {
fill: #B8DBFF;
stroke: #666;
}
svg .clusterOutline {
fill: rgba(255,255, 255, 0);
stroke: #F00;
stroke-width: 5;
opacity: 0.0;
}
svg .squareBackground {
fill: #F00;
opacity: 0.0;
}
svg .miss {
fill: #B8DBFF;
opacity: 0.5;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment