MCPcopy Index your code
hub / github.com/ChartGPU/ChartGPU / lttbIndicesForDataPoints

Function lttbIndicesForDataPoints

src/data/lttbSample.ts:88–172  ·  view source on GitHub ↗
(data: ReadonlyArray<DataPoint>, targetPoints: number)

Source from the content-addressed store, hash-verified

86}
87
88function lttbIndicesForDataPoints(data: ReadonlyArray<DataPoint>, targetPoints: number): Int32Array {
89 const n = data.length;
90 const lastIndex = n - 1;
91
92 if (targetPoints <= 0 || n === 0) return new Int32Array(0);
93 if (targetPoints === 1) return new Int32Array([0]);
94 if (targetPoints === 2) return n >= 2 ? new Int32Array([0, lastIndex]) : new Int32Array([0]);
95 if (n <= targetPoints) {
96 const indices = new Int32Array(n);
97 for (let i = 0; i < n; i++) indices[i] = i;
98 return indices;
99 }
100
101 const indices = new Int32Array(targetPoints);
102 indices[0] = 0;
103 indices[targetPoints - 1] = lastIndex;
104
105 const bucketSize = (n - 2) / (targetPoints - 2);
106
107 let a = 0;
108 let out = 1;
109
110 const pLast = data[lastIndex]!;
111 const lastX = isTupleDataPoint(pLast) ? pLast[0] : pLast.x;
112 const lastY = isTupleDataPoint(pLast) ? pLast[1] : pLast.y;
113
114 for (let bucket = 0; bucket < targetPoints - 2; bucket++) {
115 // Current bucket: candidate points are [rangeStart, rangeEndExclusive) and never include lastIndex.
116 let rangeStart = Math.floor(bucketSize * bucket) + 1;
117 let rangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 1)) + 1, lastIndex);
118 if (rangeStart >= rangeEndExclusive) {
119 // Defensive: ensure at least one candidate point.
120 rangeStart = Math.min(rangeStart, lastIndex - 1);
121 rangeEndExclusive = Math.min(rangeStart + 1, lastIndex);
122 }
123
124 // Next bucket for average: [nextRangeStart, nextRangeEndExclusive)
125 const nextRangeStart = Math.floor(bucketSize * (bucket + 1)) + 1;
126 const nextRangeEndExclusive = Math.min(Math.floor(bucketSize * (bucket + 2)) + 1, lastIndex);
127
128 // If there are no points in the next bucket, use the last point as the average.
129 let avgX = lastX;
130 let avgY = lastY;
131 if (nextRangeStart < nextRangeEndExclusive) {
132 let sumX = 0;
133 let sumY = 0;
134 let avgCount = 0;
135 for (let i = nextRangeStart; i < nextRangeEndExclusive; i++) {
136 const p = data[i]!;
137 const x = isTupleDataPoint(p) ? p[0] : p.x;
138 const y = isTupleDataPoint(p) ? p[1] : p.y;
139 sumX += x;
140 sumY += y;
141 avgCount++;
142 }
143 if (avgCount > 0) {
144 avgX = sumX / avgCount;
145 avgY = sumY / avgCount;

Callers 1

lttbSampleFunction · 0.85

Calls 1

isTupleDataPointFunction · 0.70

Tested by

no test coverage detected