lttb.js 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556
  1. /**
  2. * Sample data with lttb(Largest-Triangle-Three-Buckets) algo (https://github.com/pingec/downsample-lttb).
  3. * Return the sampled index array.
  4. */
  5. export function lttb(I, X, Y, thresholds) {
  6. const length = I.length;
  7. if (thresholds >= length || thresholds === 0) {
  8. return I;
  9. }
  10. const x = (i) => X[I[i]] * 1;
  11. const y = (i) => Y[I[i]] * 1;
  12. const sampled = [];
  13. // Bucket size. Leave room for start and end data points.
  14. const every = (length - 2) / (thresholds - 2);
  15. let a = 0; // Initially a is the first point in the triangle.
  16. let maxArea;
  17. let area;
  18. let nextA;
  19. sampled.push(a); // Always add the first point.
  20. for (let i = 0; i < thresholds - 2; i++) {
  21. // Calculate point average for next bucket (containing c).
  22. let avgX = 0;
  23. let avgY = 0;
  24. let start = Math.floor((i + 1) * every) + 1;
  25. let end = Math.floor((i + 2) * every) + 1;
  26. end = Math.min(end, length);
  27. const size = end - start;
  28. for (; start < end; start++) {
  29. avgX += x(start);
  30. avgY += y(start);
  31. }
  32. avgX /= size;
  33. avgY /= size;
  34. // Get the range for this bucket.
  35. let frameStart = Math.floor((i + 0) * every) + 1;
  36. const frameEnd = Math.floor((i + 1) * every) + 1;
  37. // Point a.
  38. const pointA = [x(a), y(a)];
  39. maxArea = area = -1;
  40. for (; frameStart < frameEnd; frameStart++) {
  41. // Calculate triangle area over three buckets.
  42. area =
  43. Math.abs((pointA[0] - avgX) * (x(frameStart) - pointA[1]) -
  44. (pointA[0] - y(frameStart)) * (avgY - pointA[0])) * 0.5;
  45. if (area > maxArea) {
  46. maxArea = area;
  47. nextA = frameStart; // Next a is this b.
  48. }
  49. }
  50. sampled.push(nextA); // Pick this point from the bucket.
  51. a = nextA; // This a is the next a (chosen b).
  52. }
  53. sampled.push(length - 1); // Always add last.
  54. return sampled.map((a) => I[a]);
  55. }
  56. //# sourceMappingURL=lttb.js.map