Skip to content

Instantly share code, notes, and snippets.

@ZJONSSON
Last active December 17, 2015 08:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ZJONSSON/5581551 to your computer and use it in GitHub Desktop.
Save ZJONSSON/5581551 to your computer and use it in GitHub Desktop.
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;
}
<!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>
(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