Skip to content

Instantly share code, notes, and snippets.

@lorenzopub
Created October 11, 2016 14:10
Show Gist options
  • Save lorenzopub/5ad723dcf82c6bd24b9d4a57f591b6f6 to your computer and use it in GitHub Desktop.
Save lorenzopub/5ad723dcf82c6bd24b9d4a57f591b6f6 to your computer and use it in GitHub Desktop.
Divided Line
license: mit

Here's an initial stab at building a Divided Line generator. The basic idea is to create a generator that takes a set of parameters and returns an array of coordinates corresponding to the segments of that line that exist within the parameters sent. In this example, I sample the previous point along with the first one so that the corresponding line can be drawn from the earlier position to the current one. Notice with the cardinal interpolation that the line doesn't interpolate properly at the junctions between the lines (the original interpolation is drawn as the black background line). This is more pronounced with basis interpolation.

Most of the code is for randomly generating points and bounding boxes...

forked from emeeks's block: Divided Line

forked from anonymous's block: Divided Line

<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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment