chartai 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/dist/chart-library.d.ts +1 -0
  2. package/dist/chart-library.d.ts.map +1 -1
  3. package/dist/chart-library.js +43 -11
  4. package/dist/chart-library.min.js +1 -1
  5. package/dist/charts/area.js +1 -1
  6. package/dist/charts/area.min.js +1 -1
  7. package/dist/charts/bar.js +1 -1
  8. package/dist/charts/bar.min.js +1 -1
  9. package/dist/charts/boids.js +9 -9
  10. package/dist/charts/boids.min.js +1 -1
  11. package/dist/charts/candlestick.js +5 -127
  12. package/dist/charts/candlestick.min.js +1 -32
  13. package/dist/charts/experimental/baseline-area.js +70 -0
  14. package/dist/charts/experimental/baseline-area.min.js +1 -0
  15. package/dist/charts/experimental/bubble.js +48 -0
  16. package/dist/charts/experimental/bubble.min.js +1 -0
  17. package/dist/charts/experimental/error-band.js +111 -0
  18. package/dist/charts/experimental/error-band.min.js +1 -0
  19. package/dist/charts/experimental/heatmap.js +69 -0
  20. package/dist/charts/experimental/heatmap.min.js +1 -0
  21. package/dist/charts/experimental/histogram.js +139 -0
  22. package/dist/charts/experimental/histogram.min.js +7 -0
  23. package/dist/charts/experimental/ohlc.js +132 -0
  24. package/dist/charts/experimental/ohlc.min.js +32 -0
  25. package/dist/charts/experimental/step.js +67 -0
  26. package/dist/charts/experimental/step.min.js +1 -0
  27. package/dist/charts/experimental/waterfall.js +121 -0
  28. package/dist/charts/experimental/waterfall.min.js +7 -0
  29. package/dist/charts/line.js +1 -1
  30. package/dist/charts/line.min.js +1 -1
  31. package/dist/charts/scatter.js +1 -1
  32. package/dist/charts/scatter.min.js +1 -1
  33. package/dist/{chunk-e7d3zgw5.min.js → chunk-0eh4rzy9.min.js} +1 -1
  34. package/dist/{chunk-a27be8p9.js → chunk-1ngxm8t2.js} +25 -1
  35. package/dist/chunk-50bcv2hw.min.js +2 -0
  36. package/dist/{chunk-dmaxrg6s.min.js → chunk-64q9a7nw.min.js} +1 -1
  37. package/dist/{chunk-me3qaz3m.min.js → chunk-bbyt23tw.min.js} +1 -1
  38. package/dist/chunk-cbydth3q.min.js +2 -0
  39. package/dist/chunk-cvtt04m6.min.js +2 -0
  40. package/dist/chunk-g2qmt43n.min.js +33 -0
  41. package/dist/{chunk-1p45ex5n.min.js → chunk-gm0d4cgx.min.js} +2 -2
  42. package/dist/chunk-mmsy3yqt.js +27 -0
  43. package/dist/{chunk-g6m56ptf.js → chunk-n8ew0z0e.js} +38 -10
  44. package/dist/chunk-t0kdz02m.js +129 -0
  45. package/dist/{chunk-bfyv7z27.min.js → chunk-wdfq2fpx.min.js} +1 -1
  46. package/dist/gpu-worker.js +8 -3
  47. package/dist/gpu-worker.min.js +1 -1
  48. package/dist/plugins/experimental/annotations.js +164 -0
  49. package/dist/plugins/experimental/annotations.min.js +1 -0
  50. package/dist/plugins/experimental/crosshair.js +82 -0
  51. package/dist/plugins/experimental/crosshair.min.js +1 -0
  52. package/dist/plugins/experimental/minimap.js +190 -0
  53. package/dist/plugins/experimental/minimap.min.js +1 -0
  54. package/dist/plugins/experimental/range-selector.js +220 -0
  55. package/dist/plugins/experimental/range-selector.min.js +1 -0
  56. package/dist/plugins/experimental/ruler.js +434 -0
  57. package/dist/plugins/experimental/ruler.min.js +59 -0
  58. package/dist/plugins/experimental/stats.js +229 -0
  59. package/dist/plugins/experimental/stats.min.js +8 -0
  60. package/dist/plugins/experimental/threshold.js +96 -0
  61. package/dist/plugins/experimental/threshold.min.js +1 -0
  62. package/dist/plugins/experimental/tooltip-pin.js +177 -0
  63. package/dist/plugins/experimental/tooltip-pin.min.js +1 -0
  64. package/dist/plugins/experimental/watermark.js +76 -0
  65. package/dist/plugins/experimental/watermark.min.js +1 -0
  66. package/dist/plugins/hover.d.ts.map +1 -1
  67. package/dist/plugins/hover.js +12 -30
  68. package/dist/plugins/hover.min.js +1 -1
  69. package/dist/plugins/labels-panel.js +3 -3
  70. package/dist/plugins/labels-panel.min.js +1 -1
  71. package/dist/plugins/labels.d.ts.map +1 -1
  72. package/dist/plugins/labels.js +3 -3
  73. package/dist/plugins/labels.min.js +1 -1
  74. package/dist/plugins/legend.d.ts.map +1 -1
  75. package/dist/plugins/legend.js +87 -16
  76. package/dist/plugins/legend.min.js +23 -7
  77. package/dist/plugins/zoom.js +2 -2
  78. package/dist/plugins/zoom.min.js +1 -1
  79. package/dist/types.d.ts +8 -0
  80. package/dist/types.d.ts.map +1 -1
  81. package/dist/worker-inline.d.ts +1 -1
  82. package/dist/worker-inline.d.ts.map +1 -1
  83. package/package.json +1 -1
  84. package/readme.md +6 -3
  85. package/dist/chunk-94kc81rr.min.js +0 -2
  86. package/dist/chunk-qr6mweck.min.js +0 -2
  87. /package/dist/{chunk-m17t3vjq.js → chunk-5gtx3pza.js} +0 -0
@@ -1,131 +1,9 @@
1
1
  import {
2
- BINARY_SEARCH,
3
- COMPUTE_WG,
4
- UNIFORM_STRUCT
5
- } from "../chunk-0jepamv9.js";
6
- import"../chunk-m17t3vjq.js";
7
-
8
- // src/shaders/candlestick.ts
9
- var CANDLE_TYPES = `
10
- struct CandleUniforms {
11
- maxSamples: f32,
12
- upColor: u32,
13
- downColor: u32,
14
- binSize: u32,
15
- interval: f32,
16
- _p0: u32, _p1: u32, _p2: u32,
17
- };
18
- struct CandleData {
19
- screenX: f32,
20
- barWidth: f32,
21
- low: f32,
22
- bodyBottom: f32,
23
- bodyTop: f32,
24
- high: f32,
25
- isUp: f32,
26
- };`;
27
- var EFFECTIVE_INTERVAL = `
28
- fn effectiveInterval() -> f32 {
29
- if (cu.interval > 0.0) { return cu.interval; }
30
- let raw = (u.viewMaxX - u.viewMinX) / u.width * f32(cu.binSize);
31
- let steps = array<f32, 20>(
32
- 1.0, 2.0, 5.0, 10.0, 15.0, 30.0,
33
- 60.0, 120.0, 300.0, 600.0, 900.0, 1800.0,
34
- 3600.0, 7200.0, 14400.0, 43200.0,
35
- 86400.0, 259200.0, 604800.0, 2592000.0
36
- );
37
- for (var i = 0u; i < 20u; i++) {
38
- if (steps[i] >= raw) { return steps[i]; }
39
- }
40
- return raw;
41
- }`;
42
- var CANDLESTICK_COMPUTE_SHADER = `${UNIFORM_STRUCT}${CANDLE_TYPES}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataClose: array<f32>;@group(0)@binding(3)var<storage,read_write> candleData: array<CandleData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> cu: CandleUniforms;@group(0)@binding(7)var<storage,read> dataOpen: array<f32>;@group(0)@binding(8)var<storage,read> dataHigh: array<f32>;@group(0)@binding(9)var<storage,read> dataLow: array<f32>;${BINARY_SEARCH}${EFFECTIVE_INTERVAL}@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let binIdx = id.x;let totalPixels = u32(u.width);let count = u.pointCount;if(count == 0u){if(binIdx < totalPixels){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){if(binIdx < totalPixels){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);}return;}let interval = effectiveInterval();let alignedStart = floor(u.viewMinX / interval)* interval;let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,totalPixels);if(binIdx >= numBins){return;}let binMinX = alignedStart + f32(binIdx)* interval;let binMaxX = binMinX + interval;if(binMinX >= u.viewMaxX){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);return;}let binMidX = binMinX + interval * 0.5;let screenX =(binMidX - u.viewMinX)/ viewRangeX;let barWidth = interval / viewRangeX;let onePixel = 1.0 / u.width;let bw = max(barWidth * 0.95,onePixel);let startIdx = lowerBound(binMinX,count);var endIdx = lowerBound(binMaxX,count);endIdx = min(endIdx,count);if(startIdx >= endIdx){var bestIdx: u32 = 0u;var bestDist: f32 = 1e10;var hit = false;if(startIdx < count){let bx = dataX[startIdx];let hw = interval * 0.5;if(binMinX < bx + hw && binMaxX > bx - hw){bestIdx = startIdx;bestDist = abs(bx - binMidX);hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = interval * 0.5;if(binMinX < bx + hw && binMaxX > bx - hw){let d = abs(bx - binMidX);if(!hit || d < bestDist){bestIdx = prev;}hit = true;}}if(!hit){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);return;}let o = dataOpen[bestIdx];let h = dataHigh[bestIdx];let l = dataLow[bestIdx];let c = dataClose[bestIdx];candleData[binIdx] = CandleData(screenX,bw,l,min(o,c),max(o,c),h,select(0.0,1.0,c>=o));return;}let o = dataOpen[startIdx];var h = dataHigh[startIdx];var l = dataLow[startIdx];let c = dataClose[endIdx - 1u];let rangeCount = endIdx - startIdx;let maxSamples = u32(cu.maxSamples);if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){h = max(h,dataHigh[idx]);l = min(l,dataLow[idx]);}}h = max(h,dataHigh[endIdx - 1u]);l = min(l,dataLow[endIdx - 1u]);}else{for(var i = startIdx;i < endIdx;i++){h = max(h,dataHigh[i]);l = min(l,dataLow[i]);}}candleData[binIdx] = CandleData(screenX,bw,l,min(o,c),max(o,c),h,select(0.0,1.0,c>=o));}`;
43
- var CANDLESTICK_RENDER_SHADER = `${UNIFORM_STRUCT}${CANDLE_TYPES}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> candleData: array<CandleData>;@group(0)@binding(2)var<uniform> cu: CandleUniforms;${EFFECTIVE_INTERVAL}struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)isUp: f32,@location(1)@interpolate(flat)isWick: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let viewRangeX = u.viewMaxX - u.viewMinX;let interval = effectiveInterval();let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,u32(u.width));let colIdx = vi / 30u;let localVi = vi % 30u;let section = localVi / 6u;let vertexType = localVi % 6u;if(colIdx >= numBins){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;out.isWick = 0.0;return out;}let cd = candleData[colIdx];if(cd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;out.isWick = 0.0;return out;}out.isUp = cd.isUp;out.isWick = select(0.0,1.0,section > 0u);let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let onePixelX = 1.0 / u.width;let onePixelY = 1.0 / u.height;var sLeft: f32;var sRight: f32;var sTop: f32;var sBottom: f32;if(section == 0u){let nb =(cd.bodyBottom - u.viewMinY)/ safeRangeY;let nt =(cd.bodyTop - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = cd.barWidth * 0.5;sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 1u){let nb =(cd.bodyTop - u.viewMinY)/ safeRangeY;let nt =(cd.high - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = max(onePixelX,cd.barWidth * 0.08);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 2u){let nb =(cd.low - u.viewMinY)/ safeRangeY;let nt =(cd.bodyBottom - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = max(onePixelX,cd.barWidth * 0.08);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 3u){let sy = 1.0 -(cd.high - u.viewMinY)/ safeRangeY;let wickHW = max(onePixelX,cd.barWidth * 0.08);let capHH = wickHW * u.width / u.height;sTop = sy - capHH;sBottom = sy + capHH;let hw = max(onePixelX * 2.0,cd.barWidth * 0.28);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else{let sy = 1.0 -(cd.low - u.viewMinY)/ safeRangeY;let wickHW = max(onePixelX,cd.barWidth * 0.08);let capHH = wickHW * u.width / u.height;sTop = sy - capHH;sBottom = sy + capHH;let hw = max(onePixelX * 2.0,cd.barWidth * 0.28);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}var positions = array<vec2f,6>(vec2f(sLeft,sBottom),vec2f(sRight,sBottom),vec2f(sLeft,sTop),vec2f(sLeft,sTop),vec2f(sRight,sBottom),vec2f(sRight,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(cu.upColor).rgb;let downRgb = unpack4x8unorm(cu.downColor).rgb;let base = select(downRgb,upRgb,in.isUp > 0.5);let color = select(base,base * 0.65,in.isWick > 0.5);return vec4f(color,0.92);}`;
44
-
45
- // src/charts/candlestick.ts
46
- var packRGB = (r, g, b) => (Math.round(r * 255) & 255 | (Math.round(g * 255) & 255) << 8 | (Math.round(b * 255) & 255) << 16 | 255 << 24) >>> 0;
47
- var BYTES_PER_CANDLE = 7 * 4;
48
- var CandlestickChart = {
49
- name: "candlestick",
50
- shaders: {
51
- compute: CANDLESTICK_COMPUTE_SHADER,
52
- render: CANDLESTICK_RENDER_SHADER
53
- },
54
- uniforms: [
55
- { name: "maxSamples", type: "f32", default: 1e4 },
56
- { name: "upColor", type: "u32", default: packRGB(0.2, 0.7, 0.3) },
57
- { name: "downColor", type: "u32", default: packRGB(0.9, 0.3, 0.3) },
58
- { name: "binSize", type: "u32", default: 8 },
59
- { name: "interval", type: "f32", default: 0 }
60
- ],
61
- buffers: [
62
- {
63
- name: "candleBuffer",
64
- bytes: ({ width }) => Math.max(16, width * BYTES_PER_CANDLE),
65
- usages: ["STORAGE"]
66
- }
67
- ],
68
- passes: [
69
- {
70
- type: "compute",
71
- shader: "compute",
72
- perSeries: true,
73
- dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
74
- bindings: [
75
- { binding: 0, source: "uniforms" },
76
- { binding: 1, source: "x-data" },
77
- { binding: 2, source: "y-data" },
78
- { binding: 3, source: "candleBuffer", write: true },
79
- { binding: 4, source: "series-info" },
80
- { binding: 5, source: "series-index" },
81
- { binding: 6, source: "custom-uniforms" },
82
- { binding: 7, source: "open-data" },
83
- { binding: 8, source: "high-data" },
84
- { binding: 9, source: "low-data" }
85
- ]
86
- },
87
- {
88
- type: "render",
89
- shader: "render",
90
- topology: "triangle-list",
91
- loadOp: "load",
92
- blend: {
93
- color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
94
- alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
95
- },
96
- draw: ({ width }) => width * 30,
97
- bindings: [
98
- { binding: 0, source: "uniforms" },
99
- { binding: 1, source: "candleBuffer" },
100
- { binding: 2, source: "custom-uniforms" }
101
- ]
102
- }
103
- ],
104
- computeBounds(series) {
105
- let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
106
- for (const s of series) {
107
- for (const x of s.rawX) {
108
- if (x < minX)
109
- minX = x;
110
- if (x > maxX)
111
- maxX = x;
112
- }
113
- for (const y of s.extra.high ?? []) {
114
- if (y > maxY)
115
- maxY = y;
116
- }
117
- for (const y of s.extra.low ?? []) {
118
- if (y < minY)
119
- minY = y;
120
- }
121
- }
122
- if (!isFinite(minX))
123
- return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
124
- const px = (maxX - minX) * 0.05 || 1;
125
- const py = (maxY - minY) * 0.1 || 1;
126
- return { minX: minX - px, maxX: maxX + px, minY: minY - py, maxY: maxY + py };
127
- }
128
- };
2
+ CandlestickChart,
3
+ packRGB
4
+ } from "../chunk-t0kdz02m.js";
5
+ import"../chunk-0jepamv9.js";
6
+ import"../chunk-5gtx3pza.js";
129
7
  export {
130
8
  packRGB,
131
9
  CandlestickChart
@@ -1,32 +1 @@
1
- import{c as v,d as K,e as H}from"../chunk-dmaxrg6s.js";import"../chunk-me3qaz3m.js";var b=`
2
- struct CandleUniforms {
3
- maxSamples: f32,
4
- upColor: u32,
5
- downColor: u32,
6
- binSize: u32,
7
- interval: f32,
8
- _p0: u32, _p1: u32, _p2: u32,
9
- };
10
- struct CandleData {
11
- screenX: f32,
12
- barWidth: f32,
13
- low: f32,
14
- bodyBottom: f32,
15
- bodyTop: f32,
16
- high: f32,
17
- isUp: f32,
18
- };`,B=`
19
- fn effectiveInterval() -> f32 {
20
- if (cu.interval > 0.0) { return cu.interval; }
21
- let raw = (u.viewMaxX - u.viewMinX) / u.width * f32(cu.binSize);
22
- let steps = array<f32, 20>(
23
- 1.0, 2.0, 5.0, 10.0, 15.0, 30.0,
24
- 60.0, 120.0, 300.0, 600.0, 900.0, 1800.0,
25
- 3600.0, 7200.0, 14400.0, 43200.0,
26
- 86400.0, 259200.0, 604800.0, 2592000.0
27
- );
28
- for (var i = 0u; i < 20u; i++) {
29
- if (steps[i] >= raw) { return steps[i]; }
30
- }
31
- return raw;
32
- }`,G=`${K}${b}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataClose: array<f32>;@group(0)@binding(3)var<storage,read_write> candleData: array<CandleData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> cu: CandleUniforms;@group(0)@binding(7)var<storage,read> dataOpen: array<f32>;@group(0)@binding(8)var<storage,read> dataHigh: array<f32>;@group(0)@binding(9)var<storage,read> dataLow: array<f32>;${H}${B}@compute @workgroup_size(${v})fn main(@builtin(global_invocation_id)id: vec3u){let binIdx = id.x;let totalPixels = u32(u.width);let count = u.pointCount;if(count == 0u){if(binIdx < totalPixels){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){if(binIdx < totalPixels){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);}return;}let interval = effectiveInterval();let alignedStart = floor(u.viewMinX / interval)* interval;let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,totalPixels);if(binIdx >= numBins){return;}let binMinX = alignedStart + f32(binIdx)* interval;let binMaxX = binMinX + interval;if(binMinX >= u.viewMaxX){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);return;}let binMidX = binMinX + interval * 0.5;let screenX =(binMidX - u.viewMinX)/ viewRangeX;let barWidth = interval / viewRangeX;let onePixel = 1.0 / u.width;let bw = max(barWidth * 0.95,onePixel);let startIdx = lowerBound(binMinX,count);var endIdx = lowerBound(binMaxX,count);endIdx = min(endIdx,count);if(startIdx >= endIdx){var bestIdx: u32 = 0u;var bestDist: f32 = 1e10;var hit = false;if(startIdx < count){let bx = dataX[startIdx];let hw = interval * 0.5;if(binMinX < bx + hw && binMaxX > bx - hw){bestIdx = startIdx;bestDist = abs(bx - binMidX);hit = true;}}if(startIdx > 0u){let prev = startIdx - 1u;let bx = dataX[prev];let hw = interval * 0.5;if(binMinX < bx + hw && binMaxX > bx - hw){let d = abs(bx - binMidX);if(!hit || d < bestDist){bestIdx = prev;}hit = true;}}if(!hit){candleData[binIdx] = CandleData(0.0,0.0,0.0,0.0,0.0,0.0,0.0);return;}let o = dataOpen[bestIdx];let h = dataHigh[bestIdx];let l = dataLow[bestIdx];let c = dataClose[bestIdx];candleData[binIdx] = CandleData(screenX,bw,l,min(o,c),max(o,c),h,select(0.0,1.0,c>=o));return;}let o = dataOpen[startIdx];var h = dataHigh[startIdx];var l = dataLow[startIdx];let c = dataClose[endIdx - 1u];let rangeCount = endIdx - startIdx;let maxSamples = u32(cu.maxSamples);if(maxSamples > 0u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){h = max(h,dataHigh[idx]);l = min(l,dataLow[idx]);}}h = max(h,dataHigh[endIdx - 1u]);l = min(l,dataLow[endIdx - 1u]);}else{for(var i = startIdx;i < endIdx;i++){h = max(h,dataHigh[i]);l = min(l,dataLow[i]);}}candleData[binIdx] = CandleData(screenX,bw,l,min(o,c),max(o,c),h,select(0.0,1.0,c>=o));}`,V=`${K}${b}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> candleData: array<CandleData>;@group(0)@binding(2)var<uniform> cu: CandleUniforms;${B}struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)isUp: f32,@location(1)@interpolate(flat)isWick: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;let viewRangeX = u.viewMaxX - u.viewMinX;let interval = effectiveInterval();let numBins = min(u32(ceil(viewRangeX / interval))+ 2u,u32(u.width));let colIdx = vi / 30u;let localVi = vi % 30u;let section = localVi / 6u;let vertexType = localVi % 6u;if(colIdx >= numBins){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;out.isWick = 0.0;return out;}let cd = candleData[colIdx];if(cd.barWidth <= 0.0){out.pos = vec4f(0.0,0.0,0.0,0.0);out.isUp = 0.0;out.isWick = 0.0;return out;}out.isUp = cd.isUp;out.isWick = select(0.0,1.0,section > 0u);let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let onePixelX = 1.0 / u.width;let onePixelY = 1.0 / u.height;var sLeft: f32;var sRight: f32;var sTop: f32;var sBottom: f32;if(section == 0u){let nb =(cd.bodyBottom - u.viewMinY)/ safeRangeY;let nt =(cd.bodyTop - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = cd.barWidth * 0.5;sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 1u){let nb =(cd.bodyTop - u.viewMinY)/ safeRangeY;let nt =(cd.high - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = max(onePixelX,cd.barWidth * 0.08);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 2u){let nb =(cd.low - u.viewMinY)/ safeRangeY;let nt =(cd.bodyBottom - u.viewMinY)/ safeRangeY;sBottom = 1.0 - nb;sTop = 1.0 - nt;let hw = max(onePixelX,cd.barWidth * 0.08);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else if(section == 3u){let sy = 1.0 -(cd.high - u.viewMinY)/ safeRangeY;let wickHW = max(onePixelX,cd.barWidth * 0.08);let capHH = wickHW * u.width / u.height;sTop = sy - capHH;sBottom = sy + capHH;let hw = max(onePixelX * 2.0,cd.barWidth * 0.28);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}else{let sy = 1.0 -(cd.low - u.viewMinY)/ safeRangeY;let wickHW = max(onePixelX,cd.barWidth * 0.08);let capHH = wickHW * u.width / u.height;sTop = sy - capHH;sBottom = sy + capHH;let hw = max(onePixelX * 2.0,cd.barWidth * 0.28);sLeft = cd.screenX - hw;sRight = cd.screenX + hw;}var positions = array<vec2f,6>(vec2f(sLeft,sBottom),vec2f(sRight,sBottom),vec2f(sLeft,sTop),vec2f(sLeft,sTop),vec2f(sRight,sBottom),vec2f(sRight,sTop));let sp = positions[vertexType];out.pos = vec4f(sp.x * 2.0 - 1.0,1.0 - sp.y * 2.0,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{let upRgb = unpack4x8unorm(cu.upColor).rgb;let downRgb = unpack4x8unorm(cu.downColor).rgb;let base = select(downRgb,upRgb,in.isUp > 0.5);let color = select(base,base * 0.65,in.isWick > 0.5);return vec4f(color,0.92);}`;var M=(q,J,Q)=>(Math.round(q*255)&255|(Math.round(J*255)&255)<<8|(Math.round(Q*255)&255)<<16|-16777216)>>>0,O=28,y={name:"candlestick",shaders:{compute:G,render:V},uniforms:[{name:"maxSamples",type:"f32",default:1e4},{name:"upColor",type:"u32",default:M(0.2,0.7,0.3)},{name:"downColor",type:"u32",default:M(0.9,0.3,0.3)},{name:"binSize",type:"u32",default:8},{name:"interval",type:"f32",default:0}],buffers:[{name:"candleBuffer",bytes:({width:q})=>Math.max(16,q*O),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:q})=>({x:Math.ceil(Math.max(1,q)/v)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"candleBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"series-index"},{binding:6,source:"custom-uniforms"},{binding:7,source:"open-data"},{binding:8,source:"high-data"},{binding:9,source:"low-data"}]},{type:"render",shader:"render",topology:"triangle-list",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:q})=>q*30,bindings:[{binding:0,source:"uniforms"},{binding:1,source:"candleBuffer"},{binding:2,source:"custom-uniforms"}]}],computeBounds(q){let J=1/0,Q=-1/0,Z=1/0,$=-1/0;for(let z of q){for(let j of z.rawX){if(j<J)J=j;if(j>Q)Q=j}for(let j of z.extra.high??[])if(j>$)$=j;for(let j of z.extra.low??[])if(j<Z)Z=j}if(!isFinite(J))return{minX:0,maxX:1,minY:0,maxY:1};let W=(Q-J)*0.05||1,k=($-Z)*0.1||1;return{minX:J-W,maxX:Q+W,minY:Z-k,maxY:$+k}}};export{M as packRGB,y as CandlestickChart};
1
+ import{b as a,c as b}from"../chunk-g2qmt43n.js";import"../chunk-64q9a7nw.js";import"../chunk-bbyt23tw.js";export{a as packRGB,b as CandlestickChart};
@@ -0,0 +1,70 @@
1
+ import {
2
+ LINE_COMPUTE_SHADER
3
+ } from "../../chunk-yabjrff2.js";
4
+ import {
5
+ COMPUTE_WG,
6
+ UNIFORM_STRUCT
7
+ } from "../../chunk-0jepamv9.js";
8
+ import"../../chunk-5gtx3pza.js";
9
+
10
+ // src/shaders/experimental/baseline-area.ts
11
+ var BASELINE_AREA_RENDER_SHADER = `${UNIFORM_STRUCT}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};struct BaselineAreaUniforms{maxSamplesPerPixel: u32,baseline: f32,positiveColor: u32,negativeColor: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> bau: BaselineAreaUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)seriesIdx: u32,@location(1)@interpolate(flat)valid: f32,@location(2)lineNormY: f32,@location(3)baselineNormY: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.valid = 0.0;out.lineNormY = 0.0;out.baselineNormY = 0.0;let maxCols = u32(u.width);if(vi >= maxCols * 2u){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = vi / 2u;let onLine =(vi % 2u)== 0u;let d = lineData[col];let viewRangeY = u.viewMaxY - u.viewMinY;let normBaseline = select(0.0,(bau.baseline - u.viewMinY)/ viewRangeY,viewRangeY > 0.0001);let baselineScreenY = 1.0 - normBaseline;let viewRangeX = u.viewMaxX - u.viewMinX;let leftBound = select(0.0,clamp((u.dataMinX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);let rightBound = select(1.0,clamp((u.dataMaxX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);var sx = clamp(d.screenX,leftBound,rightBound);let midScreenY =(d.minScreenY + d.maxScreenY)* 0.5;let lineNormY = 1.0 - midScreenY;var py = select(baselineScreenY,midScreenY,onLine);if(d.valid < 0.5 && vi > 0u){let prevCol =(vi - 1u)/ 2u;let pd = lineData[prevCol];sx = clamp(pd.screenX,leftBound,rightBound);let prevMidScreenY =(pd.minScreenY + pd.maxScreenY)* 0.5;py = select(baselineScreenY,prevMidScreenY,(vi - 1u)% 2u == 0u);}let clipX = sx * 2.0 - 1.0;let clipY = 1.0 - py * 2.0;out.valid = d.valid;out.lineNormY = lineNormY;out.baselineNormY = normBaseline;out.pos = vec4f(clipX,clipY,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.valid < 0.5){discard;}let packedColor = select(bau.negativeColor,bau.positiveColor,in.lineNormY > in.baselineNormY);let color = unpack4x8unorm(packedColor);return vec4f(color.rgb,0.8);}`;
12
+
13
+ // src/charts/experimental/baseline-area.ts
14
+ var packRGB = (r, g, b) => (Math.round(r * 255) & 255 | (Math.round(g * 255) & 255) << 8 | (Math.round(b * 255) & 255) << 16 | 255 << 24) >>> 0;
15
+ var BaselineAreaChart = {
16
+ name: "baseline-area",
17
+ shaders: {
18
+ compute: LINE_COMPUTE_SHADER,
19
+ render: BASELINE_AREA_RENDER_SHADER
20
+ },
21
+ uniforms: [
22
+ { name: "maxSamplesPerPixel", type: "u32", default: 1e4 },
23
+ { name: "baseline", type: "f32", default: 0 },
24
+ { name: "positiveColor", type: "u32", default: packRGB(0.2, 0.7, 0.4) },
25
+ { name: "negativeColor", type: "u32", default: packRGB(0.9, 0.3, 0.25) }
26
+ ],
27
+ buffers: [
28
+ {
29
+ name: "lineBuffer",
30
+ bytes: ({ width }) => Math.max(16, width * 4 * 4),
31
+ usages: ["STORAGE"]
32
+ }
33
+ ],
34
+ passes: [
35
+ {
36
+ type: "compute",
37
+ shader: "compute",
38
+ perSeries: true,
39
+ dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
40
+ bindings: [
41
+ { binding: 0, source: "uniforms" },
42
+ { binding: 1, source: "x-data" },
43
+ { binding: 2, source: "y-data" },
44
+ { binding: 3, source: "lineBuffer", write: true },
45
+ { binding: 4, source: "series-info" },
46
+ { binding: 5, source: "custom-uniforms" }
47
+ ]
48
+ },
49
+ {
50
+ type: "render",
51
+ shader: "render",
52
+ topology: "triangle-strip",
53
+ loadOp: "load",
54
+ blend: {
55
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
56
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
57
+ },
58
+ draw: ({ width }) => Math.max(0, width * 2),
59
+ bindings: [
60
+ { binding: 0, source: "uniforms" },
61
+ { binding: 1, source: "lineBuffer" },
62
+ { binding: 2, source: "series-info" },
63
+ { binding: 3, source: "custom-uniforms" }
64
+ ]
65
+ }
66
+ ]
67
+ };
68
+ export {
69
+ BaselineAreaChart
70
+ };
@@ -0,0 +1 @@
1
+ import{d as i}from"../../chunk-gm0d4cgx.js";import{f as o,g as n}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var r=`${n}struct LineData{screenX: f32,minScreenY: f32,maxScreenY: f32,valid: f32,};struct BaselineAreaUniforms{maxSamplesPerPixel: u32,baseline: f32,positiveColor: u32,negativeColor: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> lineData: array<LineData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> bau: BaselineAreaUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)seriesIdx: u32,@location(1)@interpolate(flat)valid: f32,@location(2)lineNormY: f32,@location(3)baselineNormY: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.valid = 0.0;out.lineNormY = 0.0;out.baselineNormY = 0.0;let maxCols = u32(u.width);if(vi >= maxCols * 2u){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = vi / 2u;let onLine =(vi % 2u)== 0u;let d = lineData[col];let viewRangeY = u.viewMaxY - u.viewMinY;let normBaseline = select(0.0,(bau.baseline - u.viewMinY)/ viewRangeY,viewRangeY > 0.0001);let baselineScreenY = 1.0 - normBaseline;let viewRangeX = u.viewMaxX - u.viewMinX;let leftBound = select(0.0,clamp((u.dataMinX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);let rightBound = select(1.0,clamp((u.dataMaxX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);var sx = clamp(d.screenX,leftBound,rightBound);let midScreenY =(d.minScreenY + d.maxScreenY)* 0.5;let lineNormY = 1.0 - midScreenY;var py = select(baselineScreenY,midScreenY,onLine);if(d.valid < 0.5 && vi > 0u){let prevCol =(vi - 1u)/ 2u;let pd = lineData[prevCol];sx = clamp(pd.screenX,leftBound,rightBound);let prevMidScreenY =(pd.minScreenY + pd.maxScreenY)* 0.5;py = select(baselineScreenY,prevMidScreenY,(vi - 1u)% 2u == 0u);}let clipX = sx * 2.0 - 1.0;let clipY = 1.0 - py * 2.0;out.valid = d.valid;out.lineNormY = lineNormY;out.baselineNormY = normBaseline;out.pos = vec4f(clipX,clipY,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.valid < 0.5){discard;}let packedColor = select(bau.negativeColor,bau.positiveColor,in.lineNormY > in.baselineNormY);let color = unpack4x8unorm(packedColor);return vec4f(color.rgb,0.8);}`;var l=(e,t,a)=>(Math.round(e*255)&255|(Math.round(t*255)&255)<<8|(Math.round(a*255)&255)<<16|-16777216)>>>0,m={name:"baseline-area",shaders:{compute:i,render:r},uniforms:[{name:"maxSamplesPerPixel",type:"u32",default:1e4},{name:"baseline",type:"f32",default:0},{name:"positiveColor",type:"u32",default:l(0.2,0.7,0.4)},{name:"negativeColor",type:"u32",default:l(0.9,0.3,0.25)}],buffers:[{name:"lineBuffer",bytes:({width:e})=>Math.max(16,e*4*4),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:e})=>({x:Math.ceil(Math.max(1,e)/o)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"lineBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"custom-uniforms"}]},{type:"render",shader:"render",topology:"triangle-strip",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:e})=>Math.max(0,e*2),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"lineBuffer"},{binding:2,source:"series-info"},{binding:3,source:"custom-uniforms"}]}]};export{m as BaselineAreaChart};
@@ -0,0 +1,48 @@
1
+ import {
2
+ COMPUTE_WG,
3
+ UNIFORM_STRUCT
4
+ } from "../../chunk-0jepamv9.js";
5
+ import"../../chunk-5gtx3pza.js";
6
+
7
+ // src/shaders/experimental/bubble.ts
8
+ var BUBBLE_COMPUTE_SHADER = `${UNIFORM_STRUCT}struct BubbleUniforms{dispatchXCount: u32,maxPointSize: f32,minPointSize: f32,_pad: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> bu: BubbleUniforms;@group(0)@binding(7)var<storage,read> dataR: array<f32>;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * bu.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;if(idx >= u.pointCount){return;}let x = dataX[idx];let y = dataY[idx];let r = dataR[idx];if(r <= 0.0){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let pixelX = i32(normX * f32(width));let pixelY = i32((1.0 - normY)* f32(height));let minDim = min(u.width,u.height);let maxRange = max(rangeX,rangeY);let rawRadius = r * minDim / maxRange;let radius = i32(clamp(rawRadius,bu.minPointSize,bu.maxPointSize));let iWidth = i32(width);let iHeight = i32(height);let borderR: f32 = max(1.0,f32(radius)* 0.08);let innerR = f32(radius)- borderR;for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){let dist2 = f32(dx * dx + dy * dy);if(dist2 > f32(radius * radius)){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){var fillColor: vec4f;if(dist2 > innerR * innerR){fillColor = vec4f(series.color.rgb * 0.5,0.95);}else{fillColor = vec4f(series.color.rgb,0.65);}textureStore(outputTex,vec2i(px,py),fillColor);}}}}`;
9
+
10
+ // src/charts/experimental/bubble.ts
11
+ var MAX_WG_DIM = 65535;
12
+ var BubbleChart = {
13
+ name: "bubble",
14
+ shaders: {
15
+ compute: BUBBLE_COMPUTE_SHADER
16
+ },
17
+ uniforms: [
18
+ { name: "dispatchXCount", type: "u32", default: 1 },
19
+ { name: "maxPointSize", type: "f32", default: 40 },
20
+ { name: "minPointSize", type: "f32", default: 2 }
21
+ ],
22
+ passes: [
23
+ {
24
+ type: "compute",
25
+ shader: "compute",
26
+ perSeries: true,
27
+ dispatch: ({ samples }) => {
28
+ const totalWG = Math.ceil(Math.max(1, samples) / COMPUTE_WG);
29
+ const wgX = Math.min(totalWG, MAX_WG_DIM);
30
+ const wgY = Math.ceil(totalWG / MAX_WG_DIM);
31
+ return { x: wgX, y: wgY, xCount: wgX * COMPUTE_WG };
32
+ },
33
+ bindings: [
34
+ { binding: 0, source: "uniforms" },
35
+ { binding: 1, source: "x-data" },
36
+ { binding: 2, source: "y-data" },
37
+ { binding: 3, source: "render-target", write: true },
38
+ { binding: 4, source: "series-info" },
39
+ { binding: 5, source: "series-index" },
40
+ { binding: 6, source: "custom-uniforms" },
41
+ { binding: 7, source: "r-data" }
42
+ ]
43
+ }
44
+ ]
45
+ };
46
+ export {
47
+ BubbleChart
48
+ };
@@ -0,0 +1 @@
1
+ import{f as i,g as t}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var a=`${t}struct BubbleUniforms{dispatchXCount: u32,maxPointSize: f32,minPointSize: f32,_pad: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> bu: BubbleUniforms;@group(0)@binding(7)var<storage,read> dataR: array<f32>;@compute @workgroup_size(${i})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * bu.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;if(idx >= u.pointCount){return;}let x = dataX[idx];let y = dataY[idx];let r = dataR[idx];if(r <= 0.0){return;}let width = u32(u.width);let height = u32(u.height);let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(x - u.viewMinX)/ rangeX;let normY =(y - u.viewMinY)/ rangeY;let pixelX = i32(normX * f32(width));let pixelY = i32((1.0 - normY)* f32(height));let minDim = min(u.width,u.height);let maxRange = max(rangeX,rangeY);let rawRadius = r * minDim / maxRange;let radius = i32(clamp(rawRadius,bu.minPointSize,bu.maxPointSize));let iWidth = i32(width);let iHeight = i32(height);let borderR: f32 = max(1.0,f32(radius)* 0.08);let innerR = f32(radius)- borderR;for(var dy = -radius;dy <= radius;dy++){for(var dx = -radius;dx <= radius;dx++){let dist2 = f32(dx * dx + dy * dy);if(dist2 > f32(radius * radius)){continue;}let px = pixelX + dx;let py = pixelY + dy;if(px >= 0 && px < iWidth && py >= 0 && py < iHeight){var fillColor: vec4f;if(dist2 > innerR * innerR){fillColor = vec4f(series.color.rgb * 0.5,0.95);}else{fillColor = vec4f(series.color.rgb,0.65);}textureStore(outputTex,vec2i(px,py),fillColor);}}}}`;var n=65535,x={name:"bubble",shaders:{compute:a},uniforms:[{name:"dispatchXCount",type:"u32",default:1},{name:"maxPointSize",type:"f32",default:40},{name:"minPointSize",type:"f32",default:2}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({samples:d})=>{let e=Math.ceil(Math.max(1,d)/i),r=Math.min(e,n),o=Math.ceil(e/n);return{x:r,y:o,xCount:r*i}},bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"render-target",write:!0},{binding:4,source:"series-info"},{binding:5,source:"series-index"},{binding:6,source:"custom-uniforms"},{binding:7,source:"r-data"}]}]};export{x as BubbleChart};
@@ -0,0 +1,111 @@
1
+ import {
2
+ BINARY_SEARCH,
3
+ COMPUTE_WG,
4
+ UNIFORM_STRUCT
5
+ } from "../../chunk-0jepamv9.js";
6
+ import"../../chunk-5gtx3pza.js";
7
+
8
+ // src/shaders/experimental/error-band.ts
9
+ var ERROR_BAND_COMPUTE_SHADER = `${UNIFORM_STRUCT}struct ErrorBandUniforms{maxSamplesPerPixel: u32,bandOpacity: f32,_p0: u32,_p1: u32,};struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> bandData: array<BandData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> eu: ErrorBandUniforms;@group(0)@binding(6)var<storage,read> loData: array<f32>;@group(0)@binding(7)var<storage,read> hiData: array<f32>;${BINARY_SEARCH}@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;if(pixelMaxX < u.dataMinX || pixelMinX > u.dataMaxX){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let lo = loData[bestIdx];let hi = hiData[bestIdx];let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let normY =(y - u.viewMinY)/ viewRangeY;let normLo =(lo - u.viewMinY)/ viewRangeY;let normHi =(hi - u.viewMinY)/ viewRangeY;bandData[outputIdx] = BandData(normX,1.0 - normLo,1.0 - normHi,1.0 - normY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];var dataMinLo = loData[startIdx];var dataMaxHi = hiData[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = eu.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);dataMinLo = min(dataMinLo,loData[idx]);dataMaxHi = max(dataMaxHi,hiData[idx]);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);dataMinLo = min(dataMinLo,loData[endIdx - 1u]);dataMaxHi = max(dataMaxHi,hiData[endIdx - 1u]);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);dataMinLo = min(dataMinLo,loData[i]);dataMaxHi = max(dataMaxHi,hiData[i]);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let normMinLo =(dataMinLo - u.viewMinY)/ viewRangeY;let normMaxHi =(dataMaxHi - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let loScreenY = 1.0 - normMinLo;let hiScreenY = 1.0 - normMaxHi;let centerScreenY = 1.0 -(normMinY + normMaxY)* 0.5;bandData[outputIdx] = BandData(normX,loScreenY,hiScreenY,centerScreenY,1.0);}`;
10
+ var ERROR_BAND_FILL_RENDER_SHADER = `${UNIFORM_STRUCT}struct ErrorBandUniforms{maxSamplesPerPixel: u32,bandOpacity: f32,_p0: u32,_p1: u32,};struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> bandData: array<BandData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> eu: ErrorBandUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)seriesIdx: u32,@location(1)@interpolate(flat)valid: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.valid = 0.0;let maxCols = u32(u.width);if(vi >= maxCols * 2u){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = vi / 2u;let onHi =(vi % 2u)== 0u;let d = bandData[col];let viewRangeX = u.viewMaxX - u.viewMinX;let leftBound = select(0.0,clamp((u.dataMinX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);let rightBound = select(1.0,clamp((u.dataMaxX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);var sx = clamp(d.screenX,leftBound,rightBound);var py = select(d.loScreenY,d.hiScreenY,onHi);if(d.valid < 0.5 && vi > 0u){let prevCol =(vi - 1u)/ 2u;let pd = bandData[prevCol];sx = clamp(pd.screenX,leftBound,rightBound);py = select(pd.loScreenY,pd.hiScreenY,(vi - 1u)% 2u == 0u);}let clipX = sx * 2.0 - 1.0;let clipY = 1.0 - py * 2.0;out.valid = d.valid;out.pos = vec4f(clipX,clipY,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.valid < 0.5){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,eu.bandOpacity);}`;
11
+ var ERROR_BAND_LINE_RENDER_SHADER = `${UNIFORM_STRUCT}struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> bandData: array<BandData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.alpha = 0.0;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx + 1u > maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = segIdx + endpoint;if(col >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let d = bandData[col];let d0 = bandData[segIdx];let d1 = bandData[segIdx + 1u];let segValid = min(d0.valid,d1.valid);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - d.centerScreenY * 2.0,0.0,segValid);out.alpha = segValid;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;
12
+
13
+ // src/charts/experimental/error-band.ts
14
+ var ErrorBandChart = {
15
+ name: "error-band",
16
+ shaders: {
17
+ compute: ERROR_BAND_COMPUTE_SHADER,
18
+ fill: ERROR_BAND_FILL_RENDER_SHADER,
19
+ line: ERROR_BAND_LINE_RENDER_SHADER
20
+ },
21
+ uniforms: [
22
+ { name: "maxSamplesPerPixel", type: "u32", default: 1e4 },
23
+ { name: "bandOpacity", type: "f32", default: 0.25 }
24
+ ],
25
+ buffers: [
26
+ {
27
+ name: "bandBuffer",
28
+ bytes: ({ width }) => Math.max(16, width * 5 * 4),
29
+ usages: ["STORAGE"]
30
+ }
31
+ ],
32
+ passes: [
33
+ {
34
+ type: "compute",
35
+ shader: "compute",
36
+ perSeries: true,
37
+ dispatch: ({ width }) => ({ x: Math.ceil(Math.max(1, width) / COMPUTE_WG) }),
38
+ bindings: [
39
+ { binding: 0, source: "uniforms" },
40
+ { binding: 1, source: "x-data" },
41
+ { binding: 2, source: "y-data" },
42
+ { binding: 3, source: "bandBuffer", write: true },
43
+ { binding: 4, source: "series-info" },
44
+ { binding: 5, source: "custom-uniforms" },
45
+ { binding: 6, source: "lo-data" },
46
+ { binding: 7, source: "hi-data" }
47
+ ]
48
+ },
49
+ {
50
+ type: "render",
51
+ shader: "fill",
52
+ topology: "triangle-strip",
53
+ loadOp: "load",
54
+ blend: {
55
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
56
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
57
+ },
58
+ draw: ({ width }) => Math.max(0, width * 2),
59
+ bindings: [
60
+ { binding: 0, source: "uniforms" },
61
+ { binding: 1, source: "bandBuffer" },
62
+ { binding: 2, source: "series-info" },
63
+ { binding: 3, source: "custom-uniforms" }
64
+ ]
65
+ },
66
+ {
67
+ type: "render",
68
+ shader: "line",
69
+ topology: "line-list",
70
+ loadOp: "load",
71
+ draw: ({ width }) => Math.max(0, (width - 1) * 2),
72
+ bindings: [
73
+ { binding: 0, source: "uniforms" },
74
+ { binding: 1, source: "bandBuffer" },
75
+ { binding: 2, source: "series-info" }
76
+ ]
77
+ }
78
+ ],
79
+ computeBounds(series) {
80
+ let minX = Infinity, maxX = -Infinity, minY = Infinity, maxY = -Infinity;
81
+ for (const s of series) {
82
+ for (const x of s.rawX) {
83
+ if (x < minX)
84
+ minX = x;
85
+ if (x > maxX)
86
+ maxX = x;
87
+ }
88
+ for (const y of s.extra.hi ?? []) {
89
+ if (y > maxY)
90
+ maxY = y;
91
+ }
92
+ for (const y of s.extra.lo ?? []) {
93
+ if (y < minY)
94
+ minY = y;
95
+ }
96
+ for (const y of s.rawY) {
97
+ if (y < minY)
98
+ minY = y;
99
+ if (y > maxY)
100
+ maxY = y;
101
+ }
102
+ }
103
+ if (!isFinite(minX))
104
+ return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
105
+ const py = (maxY - minY) * 0.1 || 1;
106
+ return { minX, maxX, minY: minY - py, maxY: maxY + py };
107
+ }
108
+ };
109
+ export {
110
+ ErrorBandChart
111
+ };
@@ -0,0 +1 @@
1
+ import{f as d,g as u,h as s}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var x=`${u}struct ErrorBandUniforms{maxSamplesPerPixel: u32,bandOpacity: f32,_p0: u32,_p1: u32,};struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var<storage,read_write> bandData: array<BandData>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> eu: ErrorBandUniforms;@group(0)@binding(6)var<storage,read> loData: array<f32>;@group(0)@binding(7)var<storage,read> hiData: array<f32>;${s}@compute @workgroup_size(${d})fn main(@builtin(global_invocation_id)id: vec3u){let outputIdx = id.x;let maxCols = u32(u.width);let count = u.pointCount;if(outputIdx >= maxCols || count == 0u){if(outputIdx < maxCols){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);}return;}let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;if(viewRangeX < 0.0001 || viewRangeY < 0.0001){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let relPx = f32(outputIdx);let pixelMinX = u.viewMinX +(relPx / u.width)* viewRangeX;let pixelMaxX = u.viewMinX +((relPx + 1.0)/ u.width)* viewRangeX;if(pixelMaxX < u.dataMinX || pixelMinX > u.dataMaxX){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let startIdx = lowerBound(pixelMinX,count);var endIdx = lowerBound(pixelMaxX,count);endIdx = min(endIdx,count);let centerX =(pixelMinX + pixelMaxX)* 0.5;if(startIdx >= endIdx){var bestIdx = startIdx;if(startIdx > 0u && startIdx < count){let distPrev = abs(dataX[startIdx - 1u] - centerX);let distCurr = abs(dataX[startIdx] - centerX);if(distPrev < distCurr){bestIdx = startIdx - 1u;}}else if(startIdx >= count && count > 0u){bestIdx = count - 1u;}if(bestIdx >= count){bandData[outputIdx] = BandData(-1.0,-1.0,-1.0,-1.0,0.0);return;}let y = dataY[bestIdx];let lo = loData[bestIdx];let hi = hiData[bestIdx];let normX =(dataX[bestIdx] - u.viewMinX)/ viewRangeX;let normY =(y - u.viewMinY)/ viewRangeY;let normLo =(lo - u.viewMinY)/ viewRangeY;let normHi =(hi - u.viewMinY)/ viewRangeY;bandData[outputIdx] = BandData(normX,1.0 - normLo,1.0 - normHi,1.0 - normY,1.0);return;}var dataMinY = dataY[startIdx];var dataMaxY = dataY[startIdx];var dataMinLo = loData[startIdx];var dataMaxHi = hiData[startIdx];let rangeCount = endIdx - startIdx;let maxSamples = eu.maxSamplesPerPixel;if(maxSamples > 1u && rangeCount > maxSamples){let stride = f32(rangeCount - 1u)/ f32(maxSamples - 1u);for(var s = 0u;s < maxSamples;s++){let idx = startIdx + u32(f32(s)* stride);if(idx < endIdx){let y = dataY[idx];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);dataMinLo = min(dataMinLo,loData[idx]);dataMaxHi = max(dataMaxHi,hiData[idx]);}}let lastY = dataY[endIdx - 1u];dataMinY = min(dataMinY,lastY);dataMaxY = max(dataMaxY,lastY);dataMinLo = min(dataMinLo,loData[endIdx - 1u]);dataMaxHi = max(dataMaxHi,hiData[endIdx - 1u]);}else{for(var i = startIdx + 1u;i < endIdx;i++){let y = dataY[i];dataMinY = min(dataMinY,y);dataMaxY = max(dataMaxY,y);dataMinLo = min(dataMinLo,loData[i]);dataMaxHi = max(dataMaxHi,hiData[i]);}}let normX =(centerX - u.viewMinX)/ viewRangeX;let normMinLo =(dataMinLo - u.viewMinY)/ viewRangeY;let normMaxHi =(dataMaxHi - u.viewMinY)/ viewRangeY;let normMinY =(dataMinY - u.viewMinY)/ viewRangeY;let normMaxY =(dataMaxY - u.viewMinY)/ viewRangeY;let loScreenY = 1.0 - normMinLo;let hiScreenY = 1.0 - normMaxHi;let centerScreenY = 1.0 -(normMinY + normMaxY)* 0.5;bandData[outputIdx] = BandData(normX,loScreenY,hiScreenY,centerScreenY,1.0);}`,v=`${u}struct ErrorBandUniforms{maxSamplesPerPixel: u32,bandOpacity: f32,_p0: u32,_p1: u32,};struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> bandData: array<BandData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(3)var<uniform> eu: ErrorBandUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)@interpolate(flat)seriesIdx: u32,@location(1)@interpolate(flat)valid: f32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.valid = 0.0;let maxCols = u32(u.width);if(vi >= maxCols * 2u){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = vi / 2u;let onHi =(vi % 2u)== 0u;let d = bandData[col];let viewRangeX = u.viewMaxX - u.viewMinX;let leftBound = select(0.0,clamp((u.dataMinX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);let rightBound = select(1.0,clamp((u.dataMaxX - u.viewMinX)/ viewRangeX,0.0,1.0),viewRangeX > 0.0001);var sx = clamp(d.screenX,leftBound,rightBound);var py = select(d.loScreenY,d.hiScreenY,onHi);if(d.valid < 0.5 && vi > 0u){let prevCol =(vi - 1u)/ 2u;let pd = bandData[prevCol];sx = clamp(pd.screenX,leftBound,rightBound);py = select(pd.loScreenY,pd.hiScreenY,(vi - 1u)% 2u == 0u);}let clipX = sx * 2.0 - 1.0;let clipY = 1.0 - py * 2.0;out.valid = d.valid;out.pos = vec4f(clipX,clipY,0.0,1.0);return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.valid < 0.5){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,eu.bandOpacity);}`,c=`${u}struct BandData{screenX: f32,loScreenY: f32,hiScreenY: f32,centerScreenY: f32,valid: f32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> bandData: array<BandData>;@group(0)@binding(2)var<storage,read> allSeries: array<SeriesInfo>;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32,@builtin(instance_index)series_idx: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = series_idx;out.alpha = 0.0;let maxCols = u32(u.width);let segIdx = vi / 2u;let endpoint = vi % 2u;if(segIdx + 1u > maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let col = segIdx + endpoint;if(col >= maxCols){out.pos = vec4f(0.0,0.0,0.0,0.0);return out;}let d = bandData[col];let d0 = bandData[segIdx];let d1 = bandData[segIdx + 1u];let segValid = min(d0.valid,d1.valid);out.pos = vec4f(d.screenX * 2.0 - 1.0,1.0 - d.centerScreenY * 2.0,0.0,segValid);out.alpha = segValid;return out;}@fragment fn fs(in: VertexOutput)-> @location(0)vec4f{if(in.alpha < 0.1){discard;}let series = allSeries[in.seriesIdx];return vec4f(series.color.rgb,1.0);}`;var Y={name:"error-band",shaders:{compute:x,fill:v,line:c},uniforms:[{name:"maxSamplesPerPixel",type:"u32",default:1e4},{name:"bandOpacity",type:"f32",default:0.25}],buffers:[{name:"bandBuffer",bytes:({width:e})=>Math.max(16,e*5*4),usages:["STORAGE"]}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({width:e})=>({x:Math.ceil(Math.max(1,e)/d)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"bandBuffer",write:!0},{binding:4,source:"series-info"},{binding:5,source:"custom-uniforms"},{binding:6,source:"lo-data"},{binding:7,source:"hi-data"}]},{type:"render",shader:"fill",topology:"triangle-strip",loadOp:"load",blend:{color:{srcFactor:"src-alpha",dstFactor:"one-minus-src-alpha"},alpha:{srcFactor:"one",dstFactor:"one-minus-src-alpha"}},draw:({width:e})=>Math.max(0,e*2),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"bandBuffer"},{binding:2,source:"series-info"},{binding:3,source:"custom-uniforms"}]},{type:"render",shader:"line",topology:"line-list",loadOp:"load",draw:({width:e})=>Math.max(0,(e-1)*2),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"bandBuffer"},{binding:2,source:"series-info"}]}],computeBounds(e){let n=1/0,o=-1/0,t=1/0,i=-1/0;for(let r of e){for(let a of r.rawX){if(a<n)n=a;if(a>o)o=a}for(let a of r.extra.hi??[])if(a>i)i=a;for(let a of r.extra.lo??[])if(a<t)t=a;for(let a of r.rawY){if(a<t)t=a;if(a>i)i=a}}if(!isFinite(n))return{minX:0,maxX:1,minY:0,maxY:1};let l=(i-t)*0.1||1;return{minX:n,maxX:o,minY:t-l,maxY:i+l}}};export{Y as ErrorBandChart};
@@ -0,0 +1,69 @@
1
+ import {
2
+ COMPUTE_WG,
3
+ UNIFORM_STRUCT
4
+ } from "../../chunk-0jepamv9.js";
5
+ import"../../chunk-5gtx3pza.js";
6
+
7
+ // src/shaders/experimental/heatmap.ts
8
+ var HEATMAP_COMPUTE_SHADER = `${UNIFORM_STRUCT}struct HeatmapUniforms{dispatchXCount: u32,gridColumns: u32,gridRows: u32,colorScale: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> hu: HeatmapUniforms;@group(0)@binding(7)var<storage,read> dataValue: array<f32>;fn viridis(t: f32)-> vec3f{let c0 = vec3f(0.267,0.005,0.329);let c1 = vec3f(0.229,0.322,0.545);let c2 = vec3f(0.128,0.566,0.551);let c3 = vec3f(0.370,0.789,0.383);let c4 = vec3f(0.993,0.906,0.144);let s = clamp(t,0.0,1.0)* 4.0;let i = u32(s);let f = s - f32(i);if(i == 0u){return mix(c0,c1,f);}if(i == 1u){return mix(c1,c2,f);}if(i == 2u){return mix(c2,c3,f);}return mix(c3,c4,clamp(f,0.0,1.0));}fn plasma(t: f32)-> vec3f{let c0 = vec3f(0.050,0.030,0.528);let c1 = vec3f(0.558,0.003,0.667);let c2 = vec3f(0.879,0.176,0.334);let c3 = vec3f(0.980,0.534,0.125);let c4 = vec3f(0.940,0.975,0.131);let s = clamp(t,0.0,1.0)* 4.0;let i = u32(s);let f = s - f32(i);if(i == 0u){return mix(c0,c1,f);}if(i == 1u){return mix(c1,c2,f);}if(i == 2u){return mix(c2,c3,f);}return mix(c3,c4,clamp(f,0.0,1.0));}fn applyColorScale(t: f32,scale: u32)-> vec3f{let tc = clamp(t,0.0,1.0);if(scale == 1u){return plasma(tc);}if(scale == 2u){return mix(vec3f(0.0,1.0,1.0),vec3f(1.0,0.0,1.0),tc);}if(scale == 3u){return mix(vec3f(1.0,1.0,0.0),vec3f(1.0,0.0,0.0),tc);}return viridis(tc);}@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * hu.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;if(idx >= u.pointCount){return;}let col = dataX[idx];let row = dataY[idx];let t = dataValue[idx];let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(col - u.viewMinX)/ rangeX;let normY =(row - u.viewMinY)/ rangeY;let centerX = normX * u.width;let centerY =(1.0 - normY)* u.height;let cellHalfW = 0.5 * u.width / rangeX;let cellHalfH = 0.5 * u.height / rangeY;let iWidth = i32(u.width);let iHeight = i32(u.height);let x0 = max(0,i32(centerX - cellHalfW));let x1 = min(iWidth - 1,i32(centerX + cellHalfW));let y0 = max(0,i32(centerY - cellHalfH));let y1 = min(iHeight - 1,i32(centerY + cellHalfH));if(x0 > x1 || y0 > y1){return;}let rgb = applyColorScale(t,hu.colorScale);let color = vec4f(rgb,1.0);for(var py = y0;py <= y1;py++){for(var px = x0;px <= x1;px++){textureStore(outputTex,vec2i(px,py),color);}}}`;
9
+
10
+ // src/charts/experimental/heatmap.ts
11
+ var MAX_WG_DIM = 65535;
12
+ var COLOR_SCALE_MAP = { viridis: 0, plasma: 1, cool: 2, warm: 3 };
13
+ var HeatmapChart = {
14
+ name: "heatmap",
15
+ shaders: {
16
+ compute: HEATMAP_COMPUTE_SHADER
17
+ },
18
+ install(chart) {
19
+ const cfg = chart.config;
20
+ if (typeof cfg.colorScale === "string") {
21
+ cfg.colorScale = COLOR_SCALE_MAP[cfg.colorScale] ?? 0;
22
+ }
23
+ },
24
+ uniforms: [
25
+ { name: "dispatchXCount", type: "u32", default: 1 },
26
+ { name: "gridColumns", type: "u32", default: 1 },
27
+ { name: "gridRows", type: "u32", default: 1 },
28
+ { name: "colorScale", type: "u32", default: 0 }
29
+ ],
30
+ passes: [
31
+ {
32
+ type: "compute",
33
+ shader: "compute",
34
+ perSeries: true,
35
+ dispatch: ({ samples }) => {
36
+ const totalWG = Math.ceil(Math.max(1, samples) / COMPUTE_WG);
37
+ const wgX = Math.min(totalWG, MAX_WG_DIM);
38
+ const wgY = Math.ceil(totalWG / MAX_WG_DIM);
39
+ return { x: wgX, y: wgY, xCount: wgX * COMPUTE_WG };
40
+ },
41
+ bindings: [
42
+ { binding: 0, source: "uniforms" },
43
+ { binding: 1, source: "x-data" },
44
+ { binding: 2, source: "y-data" },
45
+ { binding: 3, source: "render-target", write: true },
46
+ { binding: 4, source: "series-info" },
47
+ { binding: 5, source: "series-index" },
48
+ { binding: 6, source: "custom-uniforms" },
49
+ { binding: 7, source: "value-data" }
50
+ ]
51
+ }
52
+ ],
53
+ computeBounds(series) {
54
+ let maxCol = 0;
55
+ let maxRow = 0;
56
+ for (const s of series) {
57
+ for (const x of s.rawX)
58
+ if (x > maxCol)
59
+ maxCol = x;
60
+ for (const y of s.rawY)
61
+ if (y > maxRow)
62
+ maxRow = y;
63
+ }
64
+ return { minX: -0.5, maxX: maxCol + 0.5, minY: -0.5, maxY: maxRow + 0.5 };
65
+ }
66
+ };
67
+ export {
68
+ HeatmapChart
69
+ };
@@ -0,0 +1 @@
1
+ import{f as l,g as n}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var a=`${n}struct HeatmapUniforms{dispatchXCount: u32,gridColumns: u32,gridRows: u32,colorScale: u32,};@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> dataX: array<f32>;@group(0)@binding(2)var<storage,read> dataY: array<f32>;@group(0)@binding(3)var outputTex: texture_storage_2d<rgba8unorm,write>;@group(0)@binding(4)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(5)var<uniform> seriesIdx: SeriesIndex;@group(0)@binding(6)var<uniform> hu: HeatmapUniforms;@group(0)@binding(7)var<storage,read> dataValue: array<f32>;fn viridis(t: f32)-> vec3f{let c0 = vec3f(0.267,0.005,0.329);let c1 = vec3f(0.229,0.322,0.545);let c2 = vec3f(0.128,0.566,0.551);let c3 = vec3f(0.370,0.789,0.383);let c4 = vec3f(0.993,0.906,0.144);let s = clamp(t,0.0,1.0)* 4.0;let i = u32(s);let f = s - f32(i);if(i == 0u){return mix(c0,c1,f);}if(i == 1u){return mix(c1,c2,f);}if(i == 2u){return mix(c2,c3,f);}return mix(c3,c4,clamp(f,0.0,1.0));}fn plasma(t: f32)-> vec3f{let c0 = vec3f(0.050,0.030,0.528);let c1 = vec3f(0.558,0.003,0.667);let c2 = vec3f(0.879,0.176,0.334);let c3 = vec3f(0.980,0.534,0.125);let c4 = vec3f(0.940,0.975,0.131);let s = clamp(t,0.0,1.0)* 4.0;let i = u32(s);let f = s - f32(i);if(i == 0u){return mix(c0,c1,f);}if(i == 1u){return mix(c1,c2,f);}if(i == 2u){return mix(c2,c3,f);}return mix(c3,c4,clamp(f,0.0,1.0));}fn applyColorScale(t: f32,scale: u32)-> vec3f{let tc = clamp(t,0.0,1.0);if(scale == 1u){return plasma(tc);}if(scale == 2u){return mix(vec3f(0.0,1.0,1.0),vec3f(1.0,0.0,1.0),tc);}if(scale == 3u){return mix(vec3f(1.0,1.0,0.0),vec3f(1.0,0.0,0.0),tc);}return viridis(tc);}@compute @workgroup_size(${l})fn main(@builtin(global_invocation_id)id: vec3u){let series = allSeries[seriesIdx.index];let visStart = series.visibleRange.x;let visCount = series.visibleRange.y;let localIdx = id.y * hu.dispatchXCount + id.x;if(localIdx >= visCount){return;}let idx = visStart + localIdx;if(idx >= u.pointCount){return;}let col = dataX[idx];let row = dataY[idx];let t = dataValue[idx];let rangeX = u.viewMaxX - u.viewMinX;let rangeY = u.viewMaxY - u.viewMinY;if(rangeX < 0.0001 || rangeY < 0.0001){return;}let normX =(col - u.viewMinX)/ rangeX;let normY =(row - u.viewMinY)/ rangeY;let centerX = normX * u.width;let centerY =(1.0 - normY)* u.height;let cellHalfW = 0.5 * u.width / rangeX;let cellHalfH = 0.5 * u.height / rangeY;let iWidth = i32(u.width);let iHeight = i32(u.height);let x0 = max(0,i32(centerX - cellHalfW));let x1 = min(iWidth - 1,i32(centerX + cellHalfW));let y0 = max(0,i32(centerY - cellHalfH));let y1 = min(iHeight - 1,i32(centerY + cellHalfH));if(x0 > x1 || y0 > y1){return;}let rgb = applyColorScale(t,hu.colorScale);let color = vec4f(rgb,1.0);for(var py = y0;py <= y1;py++){for(var px = x0;px <= x1;px++){textureStore(outputTex,vec2i(px,py),color);}}}`;var u=65535,f={viridis:0,plasma:1,cool:2,warm:3},s={name:"heatmap",shaders:{compute:a},install(r){let e=r.config;if(typeof e.colorScale==="string")e.colorScale=f[e.colorScale]??0},uniforms:[{name:"dispatchXCount",type:"u32",default:1},{name:"gridColumns",type:"u32",default:1},{name:"gridRows",type:"u32",default:1},{name:"colorScale",type:"u32",default:0}],passes:[{type:"compute",shader:"compute",perSeries:!0,dispatch:({samples:r})=>{let e=Math.ceil(Math.max(1,r)/l),i=Math.min(e,u),c=Math.ceil(e/u);return{x:i,y:c,xCount:i*l}},bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"y-data"},{binding:3,source:"render-target",write:!0},{binding:4,source:"series-info"},{binding:5,source:"series-index"},{binding:6,source:"custom-uniforms"},{binding:7,source:"value-data"}]}],computeBounds(r){let e=0,i=0;for(let c of r){for(let t of c.rawX)if(t>e)e=t;for(let t of c.rawY)if(t>i)i=t}return{minX:-0.5,maxX:e+0.5,minY:-0.5,maxY:i+0.5}}};export{s as HeatmapChart};