chartai 0.1.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 (116) hide show
  1. package/dist/chart-library.d.ts +34 -146
  2. package/dist/chart-library.d.ts.map +1 -1
  3. package/dist/chart-library.js +411 -322
  4. package/dist/chart-library.min.js +1 -1
  5. package/dist/charts/area.d.ts +6 -0
  6. package/dist/charts/area.d.ts.map +1 -0
  7. package/dist/charts/area.js +65 -0
  8. package/dist/charts/area.min.js +1 -0
  9. package/dist/charts/bar.d.ts +11 -0
  10. package/dist/charts/bar.d.ts.map +1 -0
  11. package/dist/charts/bar.js +65 -0
  12. package/dist/charts/bar.min.js +1 -0
  13. package/dist/charts/boids.js +167 -0
  14. package/dist/charts/boids.min.js +18 -0
  15. package/dist/charts/candlestick.d.ts +21 -0
  16. package/dist/charts/candlestick.d.ts.map +1 -0
  17. package/dist/charts/candlestick.js +10 -0
  18. package/dist/charts/candlestick.min.js +1 -0
  19. package/dist/charts/experimental/baseline-area.js +70 -0
  20. package/dist/charts/experimental/baseline-area.min.js +1 -0
  21. package/dist/charts/experimental/bubble.js +48 -0
  22. package/dist/charts/experimental/bubble.min.js +1 -0
  23. package/dist/charts/experimental/error-band.js +111 -0
  24. package/dist/charts/experimental/error-band.min.js +1 -0
  25. package/dist/charts/experimental/heatmap.js +69 -0
  26. package/dist/charts/experimental/heatmap.min.js +1 -0
  27. package/dist/charts/experimental/histogram.js +139 -0
  28. package/dist/charts/experimental/histogram.min.js +7 -0
  29. package/dist/charts/experimental/ohlc.js +132 -0
  30. package/dist/charts/experimental/ohlc.min.js +32 -0
  31. package/dist/charts/experimental/step.js +67 -0
  32. package/dist/charts/experimental/step.min.js +1 -0
  33. package/dist/charts/experimental/waterfall.js +121 -0
  34. package/dist/charts/experimental/waterfall.min.js +7 -0
  35. package/dist/charts/line.d.ts +12 -0
  36. package/dist/charts/line.d.ts.map +1 -0
  37. package/dist/charts/line.js +62 -0
  38. package/dist/charts/line.min.js +1 -0
  39. package/dist/charts/scatter.d.ts +11 -0
  40. package/dist/charts/scatter.d.ts.map +1 -0
  41. package/dist/charts/scatter.js +46 -0
  42. package/dist/charts/scatter.min.js +1 -0
  43. package/dist/chunk-0eh4rzy9.min.js +2 -0
  44. package/dist/chunk-0jepamv9.js +7 -0
  45. package/dist/chunk-1ngxm8t2.js +129 -0
  46. package/dist/chunk-50bcv2hw.min.js +2 -0
  47. package/dist/chunk-5gtx3pza.js +9 -0
  48. package/dist/chunk-64q9a7nw.min.js +2 -0
  49. package/dist/chunk-831dem4f.js +4 -0
  50. package/dist/chunk-93yrr7er.js +35 -0
  51. package/dist/chunk-bbyt23tw.min.js +2 -0
  52. package/dist/chunk-cbydth3q.min.js +2 -0
  53. package/dist/chunk-cvtt04m6.min.js +2 -0
  54. package/dist/chunk-g2qmt43n.min.js +33 -0
  55. package/dist/chunk-gm0d4cgx.min.js +2 -0
  56. package/dist/chunk-mmsy3yqt.js +27 -0
  57. package/dist/chunk-n8ew0z0e.js +637 -0
  58. package/dist/chunk-t0kdz02m.js +129 -0
  59. package/dist/chunk-wdfq2fpx.min.js +2 -0
  60. package/dist/chunk-yabjrff2.js +11 -0
  61. package/dist/gpu-worker.js +630 -686
  62. package/dist/gpu-worker.min.js +1 -1
  63. package/dist/msg.d.ts +33 -0
  64. package/dist/msg.d.ts.map +1 -0
  65. package/dist/plugins/coords.d.ts +18 -0
  66. package/dist/plugins/coords.d.ts.map +1 -0
  67. package/dist/plugins/experimental/annotations.js +164 -0
  68. package/dist/plugins/experimental/annotations.min.js +1 -0
  69. package/dist/plugins/experimental/crosshair.js +82 -0
  70. package/dist/plugins/experimental/crosshair.min.js +1 -0
  71. package/dist/plugins/experimental/minimap.js +190 -0
  72. package/dist/plugins/experimental/minimap.min.js +1 -0
  73. package/dist/plugins/experimental/range-selector.js +220 -0
  74. package/dist/plugins/experimental/range-selector.min.js +1 -0
  75. package/dist/plugins/experimental/ruler.js +434 -0
  76. package/dist/plugins/experimental/ruler.min.js +59 -0
  77. package/dist/plugins/experimental/stats.js +229 -0
  78. package/dist/plugins/experimental/stats.min.js +8 -0
  79. package/dist/plugins/experimental/threshold.js +96 -0
  80. package/dist/plugins/experimental/threshold.min.js +1 -0
  81. package/dist/plugins/experimental/tooltip-pin.js +177 -0
  82. package/dist/plugins/experimental/tooltip-pin.min.js +1 -0
  83. package/dist/plugins/experimental/watermark.js +76 -0
  84. package/dist/plugins/experimental/watermark.min.js +1 -0
  85. package/dist/plugins/hover.d.ts +15 -2
  86. package/dist/plugins/hover.d.ts.map +1 -1
  87. package/dist/plugins/hover.js +75 -14
  88. package/dist/plugins/hover.min.js +1 -1
  89. package/dist/plugins/labels-panel.d.ts +4 -0
  90. package/dist/plugins/labels-panel.d.ts.map +1 -0
  91. package/dist/plugins/labels-panel.js +122 -0
  92. package/dist/plugins/labels-panel.min.js +1 -0
  93. package/dist/plugins/labels.d.ts +17 -2
  94. package/dist/plugins/labels.d.ts.map +1 -1
  95. package/dist/plugins/labels.js +11 -99
  96. package/dist/plugins/labels.min.js +1 -1
  97. package/dist/plugins/legend.d.ts +16 -0
  98. package/dist/plugins/legend.d.ts.map +1 -0
  99. package/dist/plugins/legend.js +353 -0
  100. package/dist/plugins/legend.min.js +37 -0
  101. package/dist/plugins/shared.d.ts +7 -0
  102. package/dist/plugins/shared.d.ts.map +1 -0
  103. package/dist/plugins/zoom.d.ts +10 -2
  104. package/dist/plugins/zoom.d.ts.map +1 -1
  105. package/dist/plugins/zoom.js +63 -62
  106. package/dist/plugins/zoom.min.js +1 -1
  107. package/dist/types.d.ts +187 -0
  108. package/dist/types.d.ts.map +1 -0
  109. package/dist/types.js +0 -0
  110. package/dist/types.min.js +0 -0
  111. package/dist/worker-inline.d.ts +1 -1
  112. package/dist/worker-inline.d.ts.map +1 -1
  113. package/package.json +11 -11
  114. package/readme.md +54 -42
  115. package/dist/chunk-bgfkgcmg.js +0 -25
  116. package/dist/chunk-cj3zanvs.min.js +0 -2
@@ -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};
@@ -0,0 +1,139 @@
1
+ import {
2
+ COMPUTE_WG,
3
+ UNIFORM_STRUCT
4
+ } from "../../chunk-0jepamv9.js";
5
+ import"../../chunk-5gtx3pza.js";
6
+
7
+ // src/shaders/experimental/histogram.ts
8
+ var HIST_UNIFORMS_STRUCT = `struct HistUniforms {
9
+ binCount: u32,
10
+ minValue: f32,
11
+ maxValue: f32,
12
+ _p0: f32,
13
+ };
14
+ `;
15
+ var HIST_CLEAR_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read_write> histBuffer: array<u32>;@group(0)@binding(2)var<uniform> hu: HistUniforms;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;if(idx < 4096u){histBuffer[idx] = 0u;}}`;
16
+ var HIST_COUNT_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@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_write> histBuffer: array<atomic<u32>>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(${COMPUTE_WG})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;if(range <= 0.0){return;}let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let binF =(x - minVal)/ range * f32(binCount);let bin = u32(clamp(binF,0.0,f32(binCount)- 1.0));if(bin < 4096u){atomicAdd(&histBuffer[bin],1u);}}`;
17
+ var HIST_FIND_MAX_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read_write> maxBuffer: array<u32>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(1)fn main(){let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let safeBins = min(binCount,4096u);var maxVal = 0u;for(var i = 0u;i < safeBins;i++){let v = histBuffer[i];if(v > maxVal){maxVal = v;}}maxBuffer[0] = maxVal;}`;
18
+ var HIST_RENDER_SHADER = `${UNIFORM_STRUCT}${HIST_UNIFORMS_STRUCT}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read> maxBuffer: array<u32>;@group(0)@binding(3)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(4)var<uniform> si: SeriesIndex;@group(0)@binding(5)var<uniform> hu: HistUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = si.index;let colIdx = vi / 6u;let vertexType = vi % 6u;let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let maxCount = maxBuffer[0];if(colIdx >= binCount || colIdx >= 4096u || maxCount == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let count = histBuffer[colIdx];if(count == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let binLeft = minVal + f32(colIdx)/ f32(binCount)* range;let binRight = minVal + f32(colIdx + 1u)/ f32(binCount)* range;let screenLeft =(binLeft - u.viewMinX)/ safeRangeX;let screenRight =(binRight - u.viewMinX)/ safeRangeX;let screenBottom = 1.0 -(0.0 - u.viewMinY)/ safeRangeY;let screenTop = 1.0 -(f32(count)- u.viewMinY)/ safeRangeY;var positions = array<vec2f,6>(vec2f(screenLeft,screenBottom),vec2f(screenRight,screenBottom),vec2f(screenLeft,screenTop),vec2f(screenLeft,screenTop),vec2f(screenRight,screenBottom),vec2f(screenRight,screenTop));let screenPos = positions[vertexType];out.pos = vec4f(screenPos.x * 2.0 - 1.0,1.0 - screenPos.y * 2.0,0.0,1.0);out.alpha = 1.0;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,0.85);}`;
19
+
20
+ // src/charts/experimental/histogram.ts
21
+ var HistogramChart = {
22
+ name: "histogram",
23
+ shaders: {
24
+ clear: HIST_CLEAR_SHADER,
25
+ count: HIST_COUNT_SHADER,
26
+ findMax: HIST_FIND_MAX_SHADER,
27
+ render: HIST_RENDER_SHADER
28
+ },
29
+ uniforms: [
30
+ { name: "binCount", type: "u32", default: 0 },
31
+ { name: "minValue", type: "f32", default: 0 },
32
+ { name: "maxValue", type: "f32", default: 0 }
33
+ ],
34
+ buffers: [
35
+ {
36
+ name: "histBuffer",
37
+ bytes: () => 4096 * 4,
38
+ usages: ["STORAGE"]
39
+ },
40
+ {
41
+ name: "maxBuffer",
42
+ bytes: () => 4,
43
+ usages: ["STORAGE"]
44
+ }
45
+ ],
46
+ passes: [
47
+ {
48
+ type: "compute",
49
+ shader: "clear",
50
+ perSeries: true,
51
+ dispatch: () => ({ x: Math.ceil(4096 / COMPUTE_WG) }),
52
+ bindings: [
53
+ { binding: 0, source: "uniforms" },
54
+ { binding: 1, source: "histBuffer", write: true },
55
+ { binding: 2, source: "custom-uniforms" }
56
+ ]
57
+ },
58
+ {
59
+ type: "compute",
60
+ shader: "count",
61
+ perSeries: true,
62
+ dispatch: ({ samples }) => ({ x: Math.ceil(Math.max(1, samples) / COMPUTE_WG) }),
63
+ bindings: [
64
+ { binding: 0, source: "uniforms" },
65
+ { binding: 1, source: "x-data" },
66
+ { binding: 2, source: "histBuffer", write: true },
67
+ { binding: 3, source: "custom-uniforms" }
68
+ ]
69
+ },
70
+ {
71
+ type: "compute",
72
+ shader: "findMax",
73
+ perSeries: true,
74
+ dispatch: () => ({ x: 1 }),
75
+ bindings: [
76
+ { binding: 0, source: "uniforms" },
77
+ { binding: 1, source: "histBuffer" },
78
+ { binding: 2, source: "maxBuffer", write: true },
79
+ { binding: 3, source: "custom-uniforms" }
80
+ ]
81
+ },
82
+ {
83
+ type: "render",
84
+ shader: "render",
85
+ topology: "triangle-list",
86
+ loadOp: "load",
87
+ blend: {
88
+ color: { srcFactor: "src-alpha", dstFactor: "one-minus-src-alpha" },
89
+ alpha: { srcFactor: "one", dstFactor: "one-minus-src-alpha" }
90
+ },
91
+ perSeries: true,
92
+ draw: () => 4096 * 6,
93
+ bindings: [
94
+ { binding: 0, source: "uniforms" },
95
+ { binding: 1, source: "histBuffer" },
96
+ { binding: 2, source: "maxBuffer" },
97
+ { binding: 3, source: "series-info" },
98
+ { binding: 4, source: "series-index" },
99
+ { binding: 5, source: "custom-uniforms" }
100
+ ]
101
+ }
102
+ ],
103
+ computeBounds(series) {
104
+ let minX = Infinity;
105
+ let maxX = -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
+ }
114
+ if (!isFinite(minX)) {
115
+ return { minX: 0, maxX: 1, minY: 0, maxY: 1 };
116
+ }
117
+ const range = maxX - minX;
118
+ if (range <= 0) {
119
+ return { minX: minX - 0.5, maxX: minX + 0.5, minY: 0, maxY: 1 };
120
+ }
121
+ const approxBins = 512;
122
+ const counts = new Int32Array(approxBins);
123
+ for (const s of series) {
124
+ for (const x of s.rawX) {
125
+ const bin = Math.min(approxBins - 1, Math.max(0, Math.floor((x - minX) / range * approxBins)));
126
+ counts[bin]++;
127
+ }
128
+ }
129
+ let maxCount = 0;
130
+ for (let i = 0;i < approxBins; i++) {
131
+ if (counts[i] > maxCount)
132
+ maxCount = counts[i];
133
+ }
134
+ return { minX, maxX, minY: 0, maxY: Math.max(1, Math.ceil(maxCount * 1.1)) };
135
+ }
136
+ };
137
+ export {
138
+ HistogramChart
139
+ };
@@ -0,0 +1,7 @@
1
+ import{f as t,g as u}from"../../chunk-64q9a7nw.js";import"../../chunk-bbyt23tw.js";var f=`struct HistUniforms {
2
+ binCount: u32,
3
+ minValue: f32,
4
+ maxValue: f32,
5
+ _p0: f32,
6
+ };
7
+ `,c=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read_write> histBuffer: array<u32>;@group(0)@binding(2)var<uniform> hu: HistUniforms;@compute @workgroup_size(${t})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;if(idx < 4096u){histBuffer[idx] = 0u;}}`,v=`${u}${f}@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_write> histBuffer: array<atomic<u32>>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(${t})fn main(@builtin(global_invocation_id)id: vec3u){let idx = id.x;let count = u.pointCount;if(idx >= count){return;}let x = dataX[idx];let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;if(range <= 0.0){return;}let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let binF =(x - minVal)/ range * f32(binCount);let bin = u32(clamp(binF,0.0,f32(binCount)- 1.0));if(bin < 4096u){atomicAdd(&histBuffer[bin],1u);}}`,d=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read_write> maxBuffer: array<u32>;@group(0)@binding(3)var<uniform> hu: HistUniforms;@compute @workgroup_size(1)fn main(){let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let safeBins = min(binCount,4096u);var maxVal = 0u;for(var i = 0u;i < safeBins;i++){let v = histBuffer[i];if(v > maxVal){maxVal = v;}}maxBuffer[0] = maxVal;}`,m=`${u}${f}@group(0)@binding(0)var<uniform> u: Uniforms;@group(0)@binding(1)var<storage,read> histBuffer: array<u32>;@group(0)@binding(2)var<storage,read> maxBuffer: array<u32>;@group(0)@binding(3)var<storage,read> allSeries: array<SeriesInfo>;@group(0)@binding(4)var<uniform> si: SeriesIndex;@group(0)@binding(5)var<uniform> hu: HistUniforms;struct VertexOutput{@builtin(position)pos: vec4f,@location(0)alpha: f32,@location(1)@interpolate(flat)seriesIdx: u32,};@vertex fn vs(@builtin(vertex_index)vi: u32)-> VertexOutput{var out: VertexOutput;out.seriesIdx = si.index;let colIdx = vi / 6u;let vertexType = vi % 6u;let binCount = select(u32(u.width),hu.binCount,hu.binCount > 0u);let maxCount = maxBuffer[0];if(colIdx >= binCount || colIdx >= 4096u || maxCount == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let count = histBuffer[colIdx];if(count == 0u){out.pos = vec4f(0.0,0.0,0.0,0.0);out.alpha = 0.0;return out;}let useCustomRange = hu.minValue < hu.maxValue;let minVal = select(u.dataMinX,hu.minValue,useCustomRange);let maxVal = select(u.dataMaxX,hu.maxValue,useCustomRange);let range = maxVal - minVal;let viewRangeX = u.viewMaxX - u.viewMinX;let viewRangeY = u.viewMaxY - u.viewMinY;let safeRangeX = select(viewRangeX,1.0,viewRangeX < 0.0001);let safeRangeY = select(viewRangeY,1.0,viewRangeY < 0.0001);let binLeft = minVal + f32(colIdx)/ f32(binCount)* range;let binRight = minVal + f32(colIdx + 1u)/ f32(binCount)* range;let screenLeft =(binLeft - u.viewMinX)/ safeRangeX;let screenRight =(binRight - u.viewMinX)/ safeRangeX;let screenBottom = 1.0 -(0.0 - u.viewMinY)/ safeRangeY;let screenTop = 1.0 -(f32(count)- u.viewMinY)/ safeRangeY;var positions = array<vec2f,6>(vec2f(screenLeft,screenBottom),vec2f(screenRight,screenBottom),vec2f(screenLeft,screenTop),vec2f(screenLeft,screenTop),vec2f(screenRight,screenBottom),vec2f(screenRight,screenTop));let screenPos = positions[vertexType];out.pos = vec4f(screenPos.x * 2.0 - 1.0,1.0 - screenPos.y * 2.0,0.0,1.0);out.alpha = 1.0;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,0.85);}`;var R={name:"histogram",shaders:{clear:c,count:v,findMax:d,render:m},uniforms:[{name:"binCount",type:"u32",default:0},{name:"minValue",type:"f32",default:0},{name:"maxValue",type:"f32",default:0}],buffers:[{name:"histBuffer",bytes:()=>16384,usages:["STORAGE"]},{name:"maxBuffer",bytes:()=>4,usages:["STORAGE"]}],passes:[{type:"compute",shader:"clear",perSeries:!0,dispatch:()=>({x:Math.ceil(4096/t)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer",write:!0},{binding:2,source:"custom-uniforms"}]},{type:"compute",shader:"count",perSeries:!0,dispatch:({samples:r})=>({x:Math.ceil(Math.max(1,r)/t)}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"x-data"},{binding:2,source:"histBuffer",write:!0},{binding:3,source:"custom-uniforms"}]},{type:"compute",shader:"findMax",perSeries:!0,dispatch:()=>({x:1}),bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer"},{binding:2,source:"maxBuffer",write:!0},{binding:3,source:"custom-uniforms"}]},{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"}},perSeries:!0,draw:()=>24576,bindings:[{binding:0,source:"uniforms"},{binding:1,source:"histBuffer"},{binding:2,source:"maxBuffer"},{binding:3,source:"series-info"},{binding:4,source:"series-index"},{binding:5,source:"custom-uniforms"}]}],computeBounds(r){let e=1/0,a=-1/0;for(let i of r)for(let n of i.rawX){if(n<e)e=n;if(n>a)a=n}if(!isFinite(e))return{minX:0,maxX:1,minY:0,maxY:1};let g=a-e;if(g<=0)return{minX:e-0.5,maxX:e+0.5,minY:0,maxY:1};let o=512,l=new Int32Array(o);for(let i of r)for(let n of i.rawX){let b=Math.min(o-1,Math.max(0,Math.floor((n-e)/g*o)));l[b]++}let s=0;for(let i=0;i<o;i++)if(l[i]>s)s=l[i];return{minX:e,maxX:a,minY:0,maxY:Math.max(1,Math.ceil(s*1.1))}}};export{R as HistogramChart};