This commit is contained in:
@@ -603,4 +603,91 @@ select
|
||||
58.43239007949476,
|
||||
58.43239007949476
|
||||
|
||||
from generate_series(1, 525600) s(i)
|
||||
from generate_series(1, 525600) s(i)
|
||||
|
||||
|
||||
|
||||
JAVASCRIPT DOWNSAMPLING TOOL
|
||||
//====================
|
||||
//https://github.com/joshcarr/largest-triangle-three-buckets.js/blob/master/lib/largest-triangle-three-buckets.js
|
||||
'use strict';
|
||||
|
||||
function largestTriangleThreeBuckets( data, threshold, xAccessor, yAccessor ) {
|
||||
|
||||
var floor = Math.floor,
|
||||
abs = Math.abs,
|
||||
dataLength = data.length,
|
||||
sampled = [],
|
||||
sampledIndex = 0,
|
||||
every = ( dataLength - 2 ) / ( threshold - 2 ), // Bucket size. Leave room for start and end data points
|
||||
a = 0, // Initially a is the first point in the triangle
|
||||
maxAreaPoint,
|
||||
maxArea,
|
||||
area,
|
||||
nextA,
|
||||
i,
|
||||
avgX = 0,
|
||||
avgY = 0,
|
||||
avgRangeStart,
|
||||
avgRangeEnd,
|
||||
avgRangeLength,
|
||||
rangeOffs,
|
||||
rangeTo,
|
||||
pointAX,
|
||||
pointAY;
|
||||
|
||||
if ( threshold >= dataLength || threshold === 0 ) {
|
||||
return data; // Nothing to do
|
||||
}
|
||||
|
||||
sampled[ sampledIndex++ ] = data[ a ]; // Always add the first point
|
||||
|
||||
for ( i = 0; i < threshold - 2; i++ ) {
|
||||
|
||||
// Calculate point average for next bucket (containing c)
|
||||
avgX = 0;
|
||||
avgY = 0;
|
||||
avgRangeStart = floor( ( i + 1 ) * every ) + 1;
|
||||
avgRangeEnd = floor( ( i + 2 ) * every ) + 1;
|
||||
avgRangeEnd = avgRangeEnd < dataLength ? avgRangeEnd : dataLength;
|
||||
|
||||
avgRangeLength = avgRangeEnd - avgRangeStart;
|
||||
|
||||
for ( ; avgRangeStart < avgRangeEnd; avgRangeStart++ ) {
|
||||
avgX += data[ avgRangeStart ][ xAccessor ] * 1; // * 1 enforces Number (value may be Date)
|
||||
avgY += data[ avgRangeStart ][ yAccessor ] * 1;
|
||||
}
|
||||
avgX /= avgRangeLength;
|
||||
avgY /= avgRangeLength;
|
||||
|
||||
// Get the range for this bucket
|
||||
rangeOffs = floor( ( i + 0 ) * every ) + 1;
|
||||
rangeTo = floor( ( i + 1 ) * every ) + 1;
|
||||
|
||||
// Point a
|
||||
pointAX = data[ a ][ xAccessor ] * 1; // enforce Number (value may be Date)
|
||||
pointAY = data[ a ][ yAccessor ] * 1;
|
||||
|
||||
maxArea = area = -1;
|
||||
|
||||
for ( ; rangeOffs < rangeTo; rangeOffs++ ) {
|
||||
// Calculate triangle area over three buckets
|
||||
area = abs( ( pointAX - avgX ) * ( data[ rangeOffs ][ yAccessor ] - pointAY ) -
|
||||
( pointAX - data[ rangeOffs ][ xAccessor ] ) * ( avgY - pointAY )
|
||||
) * 0.5;
|
||||
if ( area > maxArea ) {
|
||||
maxArea = area;
|
||||
maxAreaPoint = data[ rangeOffs ];
|
||||
nextA = rangeOffs; // Next a is this b
|
||||
}
|
||||
}
|
||||
|
||||
sampled[ sampledIndex++ ] = maxAreaPoint; // Pick this point from the bucket
|
||||
a = nextA; // This a is the next a (chosen b)
|
||||
}
|
||||
|
||||
sampled[ sampledIndex++ ] = data[ dataLength - 1 ]; // Always add last
|
||||
|
||||
return sampled;
|
||||
}
|
||||
//=============================================
|
||||
Reference in New Issue
Block a user