Only works in full screen http://bl.ocks.org/ZJONSSON/raw/5581551/
Last active
December 17, 2015 08:39
-
-
Save ZJONSSON/5581551 to your computer and use it in GitHub Desktop.
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
body { | |
background: none repeat scroll 0 0 #DADADA; | |
color: #333333; | |
font-family: Helvetica,Arial,sans-serif; | |
font-size: 14px; | |
line-height: 1.4; | |
margin: 0; | |
padding: 0; | |
} | |
.top { | |
color: #EEEEEE; | |
background-color: #3F3F3F; | |
border-bottom: 2px solid #E17600; | |
padding: 5px; | |
height: 32px; | |
font-size: 24px; | |
text-align: center; | |
text-shadow: 2px 2px 1px #666666; | |
} | |
h2 { | |
margin-top: 0px; | |
margin-bottom: 5px; | |
} | |
#content { | |
background-color: #FFFFFF; | |
border: 1px solid #CCCCCC; | |
margin-left: auto; | |
margin-right: auto; | |
margin-top: 10px; | |
width: 900px; | |
padding: 10px; | |
} | |
.demo-container { | |
background: linear-gradient(#F6F6F6 0px, #FFFFFF 50px) repeat scroll 0 0 transparent; | |
border: 1px solid #DDDDDD; | |
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.15); | |
height: 300px; | |
margin: 10px auto 10px; | |
padding: 20px 15px 15px; | |
} | |
#placeholder { | |
height: 100%; | |
width: 100%; | |
} | |
.bottom { | |
color: #888888; | |
font-size: 12px; | |
text-align: center; | |
} | |
.bottom a { | |
color: #888888; | |
} | |
#threshold { | |
border: 0; | |
color: #f6931f; | |
font-weight: bold; | |
width: 60px; | |
} | |
hr { | |
margin-top: 15px; | |
margin-bottom: 5px; | |
border: 0; | |
height: 1px; | |
background: #333; | |
background-image: -webkit-linear-gradient(left, #ccc, #333, #ccc); | |
background-image: -moz-linear-gradient(left, #ccc, #333, #ccc); | |
background-image: -ms-linear-gradient(left, #ccc, #333, #ccc); | |
background-image: -o-linear-gradient(left, #ccc, #333, #ccc); | |
} | |
a { | |
color: #E17600; | |
} |
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
<!DOCTYPE html> | |
<html> | |
<head> | |
<meta charset='utf-8'> | |
<title>Flot - Downsampling Plugin</title> | |
<script type="text/javascript" src="http://code.jquery.com/jquery-1.9.1.min.js"></script> | |
<script type="text/javascript" src="http://www.flotcharts.org/flot/jquery.flot.js"></script> | |
<script type="text/javascript" src="simplify.js"></script> | |
<link rel="stylesheet" href="http://code.jquery.com/ui/1.10.2/themes/smoothness/jquery-ui.css" /> | |
<script src="http://code.jquery.com/ui/1.10.2/jquery-ui.js"></script> | |
<script type="text/javascript" src="https://raw.github.com/sveinn-steinarsson/flot-downsample/master/demo_data.js"></script> | |
<script type="text/javascript" src="https://raw.github.com/sveinn-steinarsson/flot-downsample/master/example.js"></script> | |
<link rel="stylesheet" type="text/css" href="example.css" /> | |
</head> | |
<body> | |
<div id="content"> | |
<h2>Simplification Example</h2> | |
<div class="demo-container"> | |
<div id="placeholder"></div> | |
</div> | |
<p> | |
<label for="data">Data:</label> | |
<select id="data"> | |
<option value="0">Demo 1</option> | |
<option value="1">Demo 2</option> | |
<option value="2">Demo 3</option> | |
</select> | |
<label for="threshold">Threshold:</label> | |
<input type="text" id="threshold" readonly/> (Total count: <span id="length">0</span>) | |
</p> | |
<div id="slider-threshold"></div> | |
<hr /> | |
<p> | |
This is a fork of <a href="https://github.com/sveinn-steinarsson/flot-downsample">flot-downsample</a> by <a href="https://github.com/sveinn-steinarsson">Sveinn Steinarsson</a>. I rewrote the simplification procedure to replicate <a href="http://www2.dcs.hull.ac.uk/CISRG/publications/DPs/DP10/DP10.html">Visvalningham's algorithm</a> similar to Mike Bostock's <a href="http://bost.ocks.org/mike/simplify/">simplify</a>. I decided to <a href="http://bl.ocks.org/ZJONSSON/raw/5581551/"></a>write it from scratch</a> to get better understanding of the dynamics. Mike's version uses bianry heap, which could be slightly more efficient than the bisect routine I apply in my example. | |
</div> | |
</body> | |
</html> |
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
(function ($) { | |
"use strict"; | |
// Calculates the area of a triangle formed by current point, last one and next one | |
function calcArea(d) { | |
if (!d.prev || !d.next) return; | |
var x2 = d[0], y2 = d[1], | |
x1 = d.prev[0], y1 = d.prev[1], | |
x3 = d.next[0], y3 = d.next[1]; | |
return 1/2 * Math.abs(x1*(y2-y3)+x2*(y3-y1)+x3*(y1-y2)); | |
} | |
function bisect(a,d,f) { | |
var lo = 0, hi = a.length; | |
while (lo < hi) { | |
var mid = lo + hi >>> 1; | |
if (f(a[mid]) < f(d)) lo = mid + 1; | |
else hi = mid; | |
} | |
return lo; | |
} | |
var area = function(d) { return d.area;}; | |
function simplify(data) { | |
// Start by taking a fresh copy just in case | |
data = data.map(function(d) { return [d[0],d[1]];}); | |
var triangles = [], | |
results = [], | |
first = data[0], | |
last = data[data.length-1]; | |
// We want first and last to be always included in filter | |
first.i = last.i = 0; | |
data.forEach(function(d,i) { | |
if ((d.next = data[i+1]) && (d.prev = data[i-1])) | |
relocate(d); | |
}); | |
function relocate(d) { | |
// If the area already exists, the element is in triangles and must be removed/replaced | |
if (d.area) triangles.splice(bisect(triangles,d,area),1); | |
// If we can calculate an area, we need to insert into triangles (sorted by area) | |
if (d.area = calcArea(d)) triangles.splice(bisect(triangles,d,area),0,d); | |
return d; | |
} | |
while(triangles.length) { | |
// Remove the top triangle (smallest area) and push to results | |
var t = triangles.splice(0,1)[0]; | |
results.push(t); | |
// Connect the adjecent points and relocate both | |
t.prev.next = relocate(t.next); | |
t.next.prev = relocate(t.prev); | |
} | |
// Finally we reverse the results so largest triangles are at the top | |
results = results.reverse() | |
.map(function(d,i) { d.i = i+2; return d; }) | |
.sort(function(a,b) { return a[0]-b[0]; }); | |
return [first].concat(results).concat([last]); | |
} | |
// Caches defined | |
var results = [], | |
lastData; | |
function processRawData ( plot, series ) { | |
// We cache the results, because we can. | |
if (lastData !== series.data[0]) { | |
lastData = series.data[0]; | |
results = simplify(series.data); | |
} | |
series.data = results.filter(function(d) { return d.i < series.downsample.threshold;}) | |
} | |
var options = { | |
series: { | |
downsample: { | |
threshold: 1000 // 0 disables downsampling for this series. | |
} | |
} | |
}; | |
function init(plot) { | |
plot.hooks.processRawData.push(processRawData); | |
} | |
$.plot.plugins.push({ | |
init: init, | |
options: options, | |
name: "downsample", | |
version: "0.1" | |
}); | |
})(jQuery); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment