diff --git a/devdocs/tools.txt b/devdocs/tools.txt index 8bbbef91..3f0919ba 100644 --- a/devdocs/tools.txt +++ b/devdocs/tools.txt @@ -603,4 +603,91 @@ select 58.43239007949476, 58.43239007949476 -from generate_series(1, 525600) s(i) \ No newline at end of file +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; + } + //============================================= \ No newline at end of file