()
| 2802 | } |
| 2803 | |
| 2804 | function recomputeRenderSeries(): void { |
| 2805 | const zoomRange = zoomState?.getRange() ?? null; |
| 2806 | const baseXDomain = computeBaseXDomain(currentOptions, runtimeRawBoundsByIndex); |
| 2807 | const visibleX = computeVisibleXDomain(baseXDomain, zoomRange); |
| 2808 | |
| 2809 | // Add buffer zone (±10% beyond visible range) for caching |
| 2810 | const bufferFactor = 0.1; |
| 2811 | const visibleSpan = visibleX.max - visibleX.min; |
| 2812 | const bufferSize = visibleSpan * bufferFactor; |
| 2813 | const bufferedMin = visibleX.min - bufferSize; |
| 2814 | const bufferedMax = visibleX.max + bufferSize; |
| 2815 | |
| 2816 | // Sampling scale behavior: |
| 2817 | // - Use `samplingThreshold` as baseline at full span. |
| 2818 | // - As zoom span shrinks, raise the threshold so fewer points are dropped (more detail). |
| 2819 | // - Clamp to avoid huge allocations / pathological thresholds. |
| 2820 | const MIN_TARGET_POINTS = 2; |
| 2821 | const MAX_TARGET_POINTS_ABS = 200_000; |
| 2822 | const MAX_TARGET_MULTIPLIER = 32; |
| 2823 | const spanFracSafe = Math.max(1e-3, Math.min(1, visibleX.spanFraction)); |
| 2824 | |
| 2825 | const next: ResolvedChartGPUOptions['series'][number][] = new Array(runtimeBaseSeries.length); |
| 2826 | |
| 2827 | for (let i = 0; i < runtimeBaseSeries.length; i++) { |
| 2828 | const s = runtimeBaseSeries[i]!; |
| 2829 | |
| 2830 | if (s.type === 'pie') { |
| 2831 | next[i] = s; |
| 2832 | continue; |
| 2833 | } |
| 2834 | |
| 2835 | // Fast path: no zoom window / full span. Use baseline resolved `data` (already sampled by resolver). |
| 2836 | const isFullSpan = |
| 2837 | zoomRange == null || |
| 2838 | (Number.isFinite(zoomRange.start) && |
| 2839 | Number.isFinite(zoomRange.end) && |
| 2840 | zoomRange.start <= 0 && |
| 2841 | zoomRange.end >= 100); |
| 2842 | if (isFullSpan) { |
| 2843 | next[i] = s; |
| 2844 | continue; |
| 2845 | } |
| 2846 | |
| 2847 | // Candlestick series: OHLC-specific slicing + sampling. |
| 2848 | if (s.type === 'candlestick') { |
| 2849 | const rawOHLC = |
| 2850 | (runtimeRawDataByIndex[i] as ReadonlyArray<OHLCDataPoint> | null) ?? |
| 2851 | ((s.rawData ?? s.data) as ReadonlyArray<OHLCDataPoint>); |
| 2852 | // Slice to buffered range for sampling |
| 2853 | const bufferedOHLC = sliceVisibleRangeByOHLC(rawOHLC, bufferedMin, bufferedMax); |
| 2854 | |
| 2855 | const sampling = s.sampling; |
| 2856 | const baseThreshold = s.samplingThreshold; |
| 2857 | |
| 2858 | const baseT = Number.isFinite(baseThreshold) ? Math.max(1, baseThreshold | 0) : 1; |
| 2859 | const maxTarget = Math.min(MAX_TARGET_POINTS_ABS, Math.max(MIN_TARGET_POINTS, baseT * MAX_TARGET_MULTIPLIER)); |
| 2860 | const target = clampInt(Math.round(baseT / spanFracSafe), MIN_TARGET_POINTS, maxTarget); |
| 2861 |
no test coverage detected