An improved divided line generator. This one uses a simple search function to find the point closest to the parameterized space that determines where lines are being divided. In this example there are four parameters: Before a certain point gets a thick grey line, above a certain threshold gets a red line, below a certain threshold gets a green line and past a certain point gets a dashed line.
Last active
June 6, 2016 16:35
-
-
Save emeeks/03396c05b39b8198685f3e46942c87e3 to your computer and use it in GitHub Desktop.
Divided Line II
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
<html> | |
<head> | |
<title>Divided Lines II</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 = [{key: [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]; | |
var pointA = lastPoint; | |
var pointB = point; | |
for (var x = 0; x<10; x++) { | |
var findPoints = simpleSearchFunction(pointA, pointB, currentParameters, parameters) | |
pointA = findPoints[0] | |
pointB = findPoints[1] | |
} | |
currentPointsArray.push(pointB) | |
currentPointsArray = [pointB, point] | |
dividedLinesData.push({key: [newParameters], points: currentPointsArray}) | |
currentParameters = newParameters | |
} | |
}) | |
return dividedLinesData.filter(function (d) {return d.points.length > 1}) | |
} | |
function simpleSearchFunction(pointA, pointB, current, parameters) { | |
var pointCX = (pointA.x + pointB.x) / 2 | |
var pointCY = (pointA.y + pointB.y) / 2 | |
if (parameters({x: pointCX, y: pointCY}) === current) { | |
return [{x: pointCX, y: pointCY}, pointB] | |
} | |
return [pointA, {x: pointCX, y: pointCY}] | |
} | |
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 parameters(point) { | |
if (point.x < 100) { | |
return "before" | |
} | |
if (point.x > 400) { | |
return "after" | |
} | |
if (point.y < 150) { | |
return "above" | |
} | |
if (point.y > 350) { | |
return "below" | |
} | |
return "normal" | |
} | |
var styleMap = { | |
before: {"stroke-width": 6, "stroke-opacity": 0.5}, | |
after: {"stroke-dasharray": "5 5"}, | |
above: {stroke: "red"}, | |
below: {stroke: "green"}, | |
normal: {} | |
} | |
var lineData = randomLineGenerator(500,500,100); | |
var line = d3.svg.line() | |
.x(function (d) {return d.x}) | |
.y(function (d) {return d.y}) | |
.interpolate("basis") | |
var dLineData = dividedLine(parameters, 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)}) | |
.each(function (d){ | |
var baseStyle = {fill: "none", stroke: "black", "stroke-width": 2} | |
d.key.forEach(function (p) { | |
Object.assign(baseStyle, styleMap[p]) | |
}) | |
d3.select(this).style(baseStyle) | |
}) | |
</script> | |
</footer> | |
</html> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment