|
<html> |
|
<head> |
|
<title>Divided Lines</title> |
|
<meta charset="utf-8" /> |
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.5.16/d3.min.js"></script> |
|
</head> |
|
<style> |
|
svg { |
|
height: 500px; |
|
width: 500px; |
|
border: 1px solid gray; |
|
} |
|
</style> |
|
<body> |
|
|
|
<div id="viz"> |
|
<svg class="main"> |
|
</svg> |
|
</div> |
|
</body> |
|
<footer> |
|
<script> |
|
|
|
function dividedLine(parameters, points) { |
|
var currentParameters = parameters(points[0]) |
|
var currentPointsArray = [] |
|
dividedLinesData = [{dividedResponse: currentParameters, points: currentPointsArray}] |
|
points.forEach(function (point, i) { |
|
var newParameters = parameters(point) |
|
|
|
if (newParameters === currentParameters) { |
|
currentPointsArray.push(point) |
|
} |
|
else { |
|
var lastPoint = currentPointsArray[currentPointsArray.length - 1]; |
|
currentPointsArray = [lastPoint, point] |
|
dividedLinesData.push({dividedResponse: newParameters, points: currentPointsArray}) |
|
currentParameters = newParameters |
|
} |
|
}) |
|
return dividedLinesData.filter(function (d) {return d.points.length > 1}) |
|
} |
|
|
|
function randomLineGenerator(width, height, points) { |
|
var pointDataSet = [] |
|
var curY = 0.5 |
|
for (var x = 0; x< points; x++) { |
|
curY += Math.random() * 0.3 - 0.15; |
|
curY = Math.max(curY, 0.05) |
|
curY = Math.min(curY, 0.95) |
|
pointDataSet.push({ x: x / points * width, y: curY * height }) |
|
} |
|
return pointDataSet |
|
} |
|
|
|
function randomBoundingBoxes(width, height, boxes) { |
|
var column = height / boxes; |
|
var boundingBoxes = [] |
|
for (var x = 0; x< boxes; x++) { |
|
var x1 = 0 |
|
var y1 = column * x |
|
var x2 = width |
|
var y2 = y1 + column |
|
boundingBoxes.push([[x1,y1],[x2,y2]]) |
|
} |
|
return boundingBoxes |
|
} |
|
|
|
var lineData = randomLineGenerator(500,500,100); |
|
|
|
var boundingBoxes = randomBoundingBoxes(500,500,4); |
|
|
|
function parametersFromBoundingBoxes(point) { |
|
var bbResponse = 1; |
|
boundingBoxes.forEach(function (bb, i) { |
|
if (point.x >= bb[0][0] && point.x <= bb[1][0] && point.y >= bb[0][1] && point.y <= bb[1][1]) { |
|
bbResponse = i + 2 |
|
return |
|
} |
|
}) |
|
return bbResponse |
|
} |
|
|
|
var line = d3.svg.line() |
|
.x(function (d) {return d.x}) |
|
.y(function (d) {return d.y}) |
|
.interpolate("cardinal") |
|
|
|
d3.select("svg") |
|
.append("path") |
|
.attr("d", line(lineData)) |
|
.style("fill", "none") |
|
.style("stroke", "black") |
|
.style("stroke-width", 1) |
|
|
|
d3.select("svg") |
|
.selectAll("rect") |
|
.data(boundingBoxes) |
|
.enter() |
|
.append("rect") |
|
.attr("x", function (d) {return d[0][0]}) |
|
.attr("y", function (d) {return d[0][1]}) |
|
.attr("width", function (d) {return d[1][0] - d[0][0]}) |
|
.attr("height", function (d) {return d[1][1] - d[0][1]}) |
|
.style("fill", "yellow") |
|
.style("stroke", "gray") |
|
.style("fill-opacity", 0) |
|
.style("stroke-opacity", 0) |
|
|
|
var dLineData = dividedLine(parametersFromBoundingBoxes, lineData); |
|
|
|
var color = d3.scale.category20() |
|
|
|
d3.select("svg") |
|
.selectAll("path.segment") |
|
.data(dLineData) |
|
.enter() |
|
.append("path") |
|
.attr("d", function (d) {return line(d.points)}) |
|
.style("fill", "none") |
|
.style("stroke", function (d) {return d.dividedResponse ? color(d.dividedResponse) : "none"}) |
|
.style("stroke-width", 8) |
|
.style("stroke-opacity", 0.75) |
|
|
|
|
|
</script> |
|
</footer> |
|
|
|
</html> |