blazeplot 0.1.1 → 0.1.3
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.
- package/README.md +20 -50
- package/dist/core/DataCursor.d.ts +2 -2
- package/dist/core/DataCursor.d.ts.map +1 -1
- package/dist/core/MinMaxPyramid.d.ts +7 -3
- package/dist/core/MinMaxPyramid.d.ts.map +1 -1
- package/dist/core/RingBuffer.d.ts +1 -0
- package/dist/core/RingBuffer.d.ts.map +1 -1
- package/dist/core/SeriesStore.d.ts +3 -3
- package/dist/core/SeriesStore.d.ts.map +1 -1
- package/dist/core/StaticDataset.d.ts +14 -0
- package/dist/core/StaticDataset.d.ts.map +1 -0
- package/dist/core/index.d.ts +2 -1
- package/dist/core/index.d.ts.map +1 -1
- package/dist/core/types.d.ts +14 -0
- package/dist/core/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +189 -96
- package/dist/index.js.map +1 -1
- package/dist/ui/Chart.d.ts.map +1 -1
- package/package.json +2 -3
- package/ROADMAP.md +0 -263
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/core/RingBuffer.ts","../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts"],"sourcesContent":["import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import type { LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: RingBuffer): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) return;\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { SeriesConfig, SeriesStyle, LODView, Viewport } from \"./types.js\";\nimport { RingBuffer } from \"./RingBuffer.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly buffer: RingBuffer;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(config: SeriesConfig, style: SeriesStyle) {\n this.config = config;\n this.buffer = new RingBuffer(config.capacity);\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.buffer.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.buffer.push(x[i]!, y[i]!);\n }\n this._dirty = true;\n }\n\n clear(): void {\n this.buffer.clear();\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.build(this.buffer);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.buffer.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.buffer.getX(i);\n target[count * 2 + 1] = this.buffer.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.buffer.lowerBoundX(viewport.xMin);\n const end = this.buffer.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.buffer.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.buffer.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const s = new SeriesStore(config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/core/MinMaxPyramid.ts","../src/core/SeriesStore.ts","../src/core/RingBuffer.ts","../src/render/ShaderPrograms.ts","../src/render/Renderer.ts","../src/render/ReglBackend.ts","../src/interaction/InputController.ts","../src/interaction/Camera2D.ts","../src/interaction/AxisController.ts","../src/ui/Chart.ts","../src/core/StaticDataset.ts"],"sourcesContent":["import type { Dataset, LODView, Viewport } from \"./types.js\";\n\nconst MAX_LEVELS = 16;\n\nexport class MinMaxPyramid {\n private levels: Float32Array[] = [];\n private levelLengths: Uint32Array;\n private levelSampleWidths: Uint32Array;\n private _builtLen: number = 0;\n private _lastRangeStart: number = NaN;\n\n constructor(readonly bucketSize: number = 2) {\n if (!Number.isInteger(bucketSize) || bucketSize < 2) {\n throw new RangeError(\"MinMaxPyramid bucketSize must be an integer >= 2.\");\n }\n\n this.levelLengths = new Uint32Array(MAX_LEVELS);\n this.levelSampleWidths = new Uint32Array(MAX_LEVELS);\n }\n\n build(source: Dataset): void {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n\n let srcLen = source.length;\n if (srcLen === 0) {\n this._builtLen = 0;\n this._lastRangeStart = NaN;\n return;\n }\n\n let prevLevel: Float32Array | null = null;\n let level = 0;\n\n while (srcLen > 0 && level < MAX_LEVELS) {\n const nextLen = Math.ceil(srcLen / this.bucketSize);\n const levelData = new Float32Array(nextLen * 2);\n\n for (let i = 0; i < srcLen; i += this.bucketSize) {\n let minY = Infinity;\n let maxY = -Infinity;\n const end = Math.min(i + this.bucketSize, srcLen);\n for (let j = i; j < end; j++) {\n if (prevLevel) {\n const prevMin = prevLevel[j * 2]!;\n const prevMax = prevLevel[j * 2 + 1]!;\n if (prevMin < minY) minY = prevMin;\n if (prevMax > maxY) maxY = prevMax;\n } else {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n }\n const outIdx = Math.floor(i / this.bucketSize);\n levelData[outIdx * 2] = minY;\n levelData[outIdx * 2 + 1] = maxY;\n }\n\n this.levels[level] = levelData;\n this.levelLengths[level] = nextLen;\n this.levelSampleWidths[level] = this.bucketSize ** (level + 1);\n\n if (nextLen === 1) break;\n\n prevLevel = levelData;\n srcLen = nextLen;\n level++;\n }\n\n this._builtLen = source.length;\n this._lastRangeStart = source.range?.start ?? NaN;\n }\n\n incrementalBuild(source: Dataset): void {\n const newLen = source.length;\n const rangeStart = source.range?.start ?? NaN;\n\n if (newLen === 0) {\n this.levels = [];\n this.levelLengths.fill(0);\n this.levelSampleWidths.fill(0);\n this._builtLen = 0;\n this._lastRangeStart = NaN;\n return;\n }\n\n if (newLen < this._builtLen || rangeStart !== this._lastRangeStart) {\n this.build(source);\n return;\n }\n\n if (newLen === this._builtLen) return;\n\n this.appendTail(source, newLen - this._builtLen);\n this._builtLen = newLen;\n }\n\n private appendTail(source: Dataset, appendedCount: number): void {\n const newLen = source.length;\n const W = this.bucketSize;\n let changedIdx = newLen - appendedCount;\n\n for (let L = 0; L < MAX_LEVELS; L++) {\n const items: number = L === 0 ? newLen : this.levelLengths[L - 1]!;\n const first = Math.floor(changedIdx / W);\n const last = Math.ceil(items / W) - 1;\n\n if (first > last) break;\n\n this.levelSampleWidths[L] = W ** (L + 1);\n this.ensureLevelData(L, last + 1);\n\n for (let b = first; b <= last; b++) {\n const start = b * W;\n const end = Math.min((b + 1) * W, items);\n\n let minY = Infinity;\n let maxY = -Infinity;\n\n if (L === 0) {\n for (let j = start; j < end; j++) {\n const y = source.getY(j);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n } else {\n const prev = this.levels[L - 1]!;\n for (let j = start; j < end; j++) {\n const pMin = prev[j * 2]!;\n const pMax = prev[j * 2 + 1]!;\n if (pMin < minY) minY = pMin;\n if (pMax > maxY) maxY = pMax;\n }\n }\n\n const dst = this.levels[L]!;\n dst[b * 2] = minY;\n dst[b * 2 + 1] = maxY;\n }\n\n this.levelLengths[L] = last + 1;\n changedIdx = first;\n\n if (this.levelLengths[L]! <= 1) break;\n }\n }\n\n private ensureLevelData(level: number, minBuckets: number): void {\n const needed = minBuckets * 2;\n const current = this.levels[level];\n if (current && current.length >= needed) return;\n\n const next = new Float32Array(needed);\n if (current) {\n next.set(current.subarray(0, Math.min(current.length, needed)));\n }\n this.levels[level] = next;\n }\n\n query(_viewport: Viewport, pixelWidth: number, xRange: { start: number; length: number }): LODView {\n if (pixelWidth <= 0 || xRange.length <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const visibleSamples = xRange.length;\n const samplesPerPixel = Math.max(1, visibleSamples / pixelWidth);\n const level = Math.min(\n Math.max(0, Math.ceil(Math.log2(samplesPerPixel)) - 1),\n this.levels.length - 1,\n );\n\n const levelData = this.levels[level];\n const levelLen = this.levelLengths[level];\n const sampleWidth = this.levelSampleWidths[level];\n if (!levelData || levelLen === undefined || sampleWidth === undefined || levelLen === 0 || sampleWidth === 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel };\n }\n\n const queryStart = Math.max(0, xRange.start);\n const queryEnd = queryStart + xRange.length;\n const bucketStart = Math.max(0, Math.floor(queryStart / sampleWidth));\n const bucketEnd = Math.min(levelLen, Math.ceil(queryEnd / sampleWidth));\n const count = bucketEnd - bucketStart;\n\n if (count <= 0) {\n return { buckets: new Float32Array(0), bucketCount: 0, level, samplesPerPixel };\n }\n\n const result = new Float32Array(count * 2);\n for (let i = 0; i < count; i++) {\n const j = (bucketStart + i) * 2;\n result[i * 2] = levelData[j]!;\n result[i * 2 + 1] = levelData[j + 1]!;\n }\n\n return { buckets: result, bucketCount: count, level, samplesPerPixel };\n }\n}\n","import type { Dataset, AppendableDataset, LODView, Viewport, SeriesConfig, SeriesStyle } from \"./types.js\";\nimport { MinMaxPyramid } from \"./MinMaxPyramid.js\";\n\nexport class SeriesStore {\n readonly config: SeriesConfig;\n readonly style: SeriesStyle;\n private readonly dataset: Dataset;\n private readonly pyramid: MinMaxPyramid;\n\n private _dirty: boolean = false;\n private _visible: boolean = true;\n\n constructor(dataset: Dataset, config: SeriesConfig, style: SeriesStyle) {\n this.dataset = dataset;\n this.config = config;\n this.pyramid = new MinMaxPyramid();\n this.style = style;\n\n if (dataset.length > 0) {\n this.pyramid.build(dataset);\n }\n }\n\n get dirty(): boolean {\n return this._dirty;\n }\n\n get length(): number {\n return this.dataset.length;\n }\n\n get visible(): boolean {\n return this._visible;\n }\n\n setVisible(visible: boolean): void {\n this._visible = visible;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n if (!(\"push\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not appendable.\");\n }\n\n const appendable = this.dataset as AppendableDataset;\n appendable.append(x, y);\n this._dirty = true;\n }\n\n clear(): void {\n if (!(\"clear\" in this.dataset)) {\n throw new TypeError(\"SeriesStore dataset is not clearable.\");\n }\n\n (this.dataset as AppendableDataset).clear();\n this.pyramid.build(this.dataset);\n this._dirty = false;\n }\n\n rebuildPyramid(): void {\n if (!this._dirty) return;\n this.pyramid.incrementalBuild(this.dataset);\n this._dirty = false;\n }\n\n query(viewport: Viewport, pixelWidth: number): LODView {\n const range = this.dataset.range;\n if (!range) {\n return { buckets: new Float32Array(0), bucketCount: 0, level: 0, samplesPerPixel: 0 };\n }\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n\n return this.pyramid.query(viewport, pixelWidth, {\n start,\n length: Math.max(0, end - start),\n });\n }\n\n visibleSampleCount(viewport: Viewport): number {\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n return Math.max(0, end - start);\n }\n\n copyRawVisible(viewport: Viewport, target: Float32Array, maxPoints: number): number {\n if (maxPoints <= 0 || target.length < maxPoints * 2) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const stride = Math.max(1, Math.ceil(visible / maxPoints));\n let count = 0;\n for (let i = start; i < end && count < maxPoints; i += stride) {\n target[count * 2] = this.dataset.getX(i);\n target[count * 2 + 1] = this.dataset.getY(i);\n count++;\n }\n\n return count;\n }\n\n copyMinMaxVisible(viewport: Viewport, target: Float32Array, maxSegments: number): number {\n if (maxSegments <= 0 || target.length < maxSegments * 4) return 0;\n\n const start = this.dataset.lowerBoundX(viewport.xMin);\n const end = this.dataset.upperBoundX(viewport.xMax);\n const visible = end - start;\n if (visible <= 0) return 0;\n\n const segmentCount = Math.min(maxSegments, visible);\n let vertexCount = 0;\n for (let segment = 0; segment < segmentCount; segment++) {\n const segmentStart = start + Math.floor((segment * visible) / segmentCount);\n const segmentEnd = start + Math.max(\n Math.floor(((segment + 1) * visible) / segmentCount),\n Math.floor((segment * visible) / segmentCount) + 1,\n );\n const clampedEnd = Math.min(end, segmentEnd);\n\n let minY = Infinity;\n let maxY = -Infinity;\n for (let i = segmentStart; i < clampedEnd; i++) {\n const y = this.dataset.getY(i);\n if (y < minY) minY = y;\n if (y > maxY) maxY = y;\n }\n\n const x = this.dataset.getX(segmentStart + ((clampedEnd - segmentStart) >> 1));\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = minY;\n vertexCount++;\n target[vertexCount * 2] = x;\n target[vertexCount * 2 + 1] = maxY;\n vertexCount++;\n }\n\n return vertexCount;\n }\n}\n","import type { TimeRange } from \"./types.js\";\n\nexport class RingBuffer {\n readonly capacity: number;\n private _length: number = 0;\n private _head: number = 0;\n\n private readonly xData: Float64Array;\n private readonly yData: Float32Array;\n\n constructor(capacity: number) {\n if (!Number.isInteger(capacity) || capacity <= 0) {\n throw new RangeError(\"RingBuffer capacity must be a positive integer.\");\n }\n\n this.capacity = capacity;\n this.xData = new Float64Array(capacity);\n this.yData = new Float32Array(capacity);\n }\n\n get length(): number {\n return this._length;\n }\n\n get range(): TimeRange | null {\n if (this._length === 0) return null;\n return { start: this.getX(0), end: this.getX(this._length - 1) };\n }\n\n push(x: number, y: number): void {\n this.xData[this._head] = x;\n this.yData[this._head] = y;\n this._head = (this._head + 1) % this.capacity;\n if (this._length < this.capacity) this._length++;\n }\n\n append(x: ArrayLike<number>, y: ArrayLike<number>): void {\n const n = Math.min(x.length, y.length);\n for (let i = 0; i < n; i++) {\n this.push(x[i]!, y[i]!);\n }\n }\n\n get(index: number): { x: number; y: number } | null {\n if (index < 0 || index >= this._length) return null;\n return { x: this.getX(index), y: this.getY(index) };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[this.logicalToPhysical(index)]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[this.logicalToPhysical(index)]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this._length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.getX(mid) <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n clear(): void {\n this._length = 0;\n this._head = 0;\n }\n\n private logicalToPhysical(index: number): number {\n return (this._head - this._length + index + this.capacity) % this.capacity;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this._length) {\n throw new RangeError(`RingBuffer index out of range: ${index}`);\n }\n }\n}\n","import lineVert from \"./shaders/line.vert?raw\";\nimport lineFrag from \"./shaders/line.frag?raw\";\nimport segmentVert from \"./shaders/segment.vert?raw\";\nimport segmentFrag from \"./shaders/segment.frag?raw\";\n\nexport const ShaderPrograms = {\n line: { vert: lineVert, frag: lineFrag },\n segment: { vert: segmentVert, frag: segmentFrag },\n} as const;\n","import { ShaderPrograms } from \"./ShaderPrograms.js\";\nimport type { Camera2D } from \"../interaction/Camera2D.js\";\nimport type { GpuBackend, GpuBuffer, GpuProgram } from \"./types.js\";\nimport type { SeriesStyle } from \"../core/types.js\";\n\nexport class Renderer {\n private readonly lineProgram: GpuProgram;\n private readonly scaleUniform: Float32Array = new Float32Array(2);\n private readonly offsetUniform: Float32Array = new Float32Array(2);\n\n constructor(private backend: GpuBackend) {\n this.lineProgram = this.backend.createProgram(ShaderPrograms.line.vert, ShaderPrograms.line.frag);\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.backend.clear(r, g, b, a);\n }\n\n createFloatBuffer(floatCount: number): GpuBuffer {\n return this.backend.createBuffer({ usage: \"stream\", type: \"float\", length: floatCount });\n }\n\n updateFloatBuffer(buffer: GpuBuffer, data: Float32Array): void {\n this.backend.updateBuffer(buffer, data);\n }\n\n viewport(x: number, y: number, width: number, height: number): void {\n this.backend.viewport(x, y, width, height);\n }\n\n drawLines(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"lines\", positions, count, style, camera);\n }\n\n drawLineStrip(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLinePrimitive(\"line_strip\", positions, count, style, camera);\n }\n\n private drawLinePrimitive(primitive: \"lines\" | \"line_strip\", positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.scaleUniform[0] = camera.xScale;\n this.scaleUniform[1] = camera.yScale;\n this.offsetUniform[0] = camera.xOffset;\n this.offsetUniform[1] = camera.yOffset;\n\n this.backend.draw({\n program: this.lineProgram,\n primitive,\n count,\n attributes: { position: positions },\n uniforms: {\n uScale: this.scaleUniform,\n uOffset: this.offsetUniform,\n uColor: style.color,\n },\n });\n }\n\n drawMinMaxSegments(positions: GpuBuffer, count: number, style: SeriesStyle, camera: Camera2D): void {\n this.drawLines(positions, count, style, camera);\n }\n\n dispose(): void {\n this.backend.destroy();\n }\n}\n","import createRegl from \"regl\";\nimport type { AttributeState, Buffer as ReglBuffer, DrawCommand, PrimitiveType, Regl, Uniform } from \"regl\";\nimport type { GpuBackend, GpuBuffer, GpuProgram, GpuResource, BufferSpec, DrawSpec, UniformValue } from \"./types.js\";\n\ntype ReglGpuBuffer = GpuBuffer & {\n readonly buffer: ReglBuffer;\n};\n\ntype ReglGpuProgram = GpuProgram & {\n readonly id: number;\n readonly vert: string;\n readonly frag: string;\n};\n\ninterface DrawProps {\n readonly count: number;\n readonly instances: number;\n readonly attributes: Readonly<Record<string, ReglBuffer>>;\n readonly uniforms: Readonly<Record<string, UniformValue>>;\n}\n\nfunction toReglContext(gl: WebGL2RenderingContext): WebGLRenderingContext {\n // regl's public types accept WebGLRenderingContext even though regl can run on WebGL2 contexts.\n return gl as unknown as WebGLRenderingContext;\n}\n\nexport class ReglBackend implements GpuBackend {\n private gl: WebGL2RenderingContext;\n private regl: Regl;\n private nextProgramId: number = 1;\n private commandCache: Map<string, DrawCommand> = new Map();\n\n constructor(canvas: HTMLCanvasElement) {\n const gl = canvas.getContext(\"webgl2\", {\n alpha: true,\n antialias: false,\n depth: false,\n stencil: false,\n premultipliedAlpha: false,\n preserveDrawingBuffer: false,\n powerPreference: \"high-performance\",\n });\n\n if (!gl) {\n throw new Error(\"BlazePlot requires WebGL2, but this browser/context does not support it.\");\n }\n\n this.gl = gl;\n this.regl = createRegl({\n gl: toReglContext(this.gl),\n extensions: [],\n optionalExtensions: [\n \"ext_disjoint_timer_query_webgl2\",\n ],\n });\n }\n\n createBuffer(spec: BufferSpec): GpuBuffer {\n const bytesPerElement = spec.type === \"float\" ? 4 : 2;\n return {\n length: spec.length,\n type: spec.type,\n buffer: this.regl.buffer({\n length: spec.length * bytesPerElement,\n usage: spec.usage,\n type: spec.type === \"float\" ? \"float\" : \"uint16\",\n }),\n } as ReglGpuBuffer;\n }\n\n updateBuffer(buffer: GpuBuffer, data: Float32Array | Uint16Array, offset: number = 0): void {\n if (data.length + offset > buffer.length) {\n throw new RangeError(\"GPU buffer update exceeds allocated buffer length.\");\n }\n\n const bytesPerElement = buffer.type === \"float\" ? 4 : 2;\n this.asReglBuffer(buffer).buffer.subdata(data, offset * bytesPerElement);\n }\n\n createProgram(vert: string, frag: string): GpuProgram {\n return {\n id: this.nextProgramId++,\n vert,\n frag,\n } as ReglGpuProgram;\n }\n\n draw(spec: DrawSpec): void {\n if (spec.count <= 0) return;\n\n const program = this.asReglProgram(spec.program);\n const attributeNames = Object.keys(spec.attributes).sort();\n const uniformNames = Object.keys(spec.uniforms).sort();\n const key = [program.id, spec.primitive, attributeNames.join(\",\"), uniformNames.join(\",\"), spec.instances === undefined ? 0 : 1].join(\"|\");\n let command = this.commandCache.get(key);\n\n if (!command) {\n command = this.createDrawCommand(program, spec.primitive, attributeNames, uniformNames, spec.instances !== undefined);\n this.commandCache.set(key, command);\n }\n\n const attributes: Record<string, ReglBuffer> = {};\n for (const name of attributeNames) {\n attributes[name] = this.asReglBuffer(spec.attributes[name]!).buffer;\n }\n\n command({\n count: spec.count,\n instances: spec.instances ?? 0,\n attributes,\n uniforms: spec.uniforms,\n });\n }\n\n dispose(resource: GpuResource): void {\n if (this.isReglBuffer(resource)) resource.buffer.destroy();\n }\n\n clear(r: number, g: number, b: number, a: number): void {\n this.regl.clear({ color: [r, g, b, a] });\n }\n\n viewport(_x: number, _y: number, _w: number, _h: number): void {\n // Handled by regl internally via canvas size\n }\n\n destroy(): void {\n this.regl.destroy();\n }\n\n private createDrawCommand(\n program: ReglGpuProgram,\n primitive: DrawSpec[\"primitive\"],\n attributeNames: readonly string[],\n uniformNames: readonly string[],\n instanced: boolean,\n ): DrawCommand {\n const attributes: Record<string, (context: object, props: DrawProps) => AttributeState> = {};\n for (const name of attributeNames) {\n attributes[name] = (_context, props) => props.attributes[name]!;\n }\n\n const uniforms: Record<string, (context: object, props: DrawProps) => Uniform> = {};\n for (const name of uniformNames) {\n uniforms[name] = (_context, props) => props.uniforms[name] as Uniform;\n }\n\n return this.regl({\n vert: program.vert,\n frag: program.frag,\n attributes,\n uniforms,\n primitive: this.toReglPrimitive(primitive),\n count: (_context: object, props: DrawProps) => props.count,\n instances: instanced ? (_context: object, props: DrawProps) => props.instances : undefined,\n depth: { enable: false },\n });\n }\n\n private asReglBuffer(buffer: GpuBuffer): ReglGpuBuffer {\n return buffer as ReglGpuBuffer;\n }\n\n private asReglProgram(program: GpuProgram): ReglGpuProgram {\n return program as ReglGpuProgram;\n }\n\n private isReglBuffer(resource: GpuResource): resource is ReglGpuBuffer {\n return \"length\" in resource && \"type\" in resource && \"buffer\" in resource;\n }\n\n private toReglPrimitive(primitive: DrawSpec[\"primitive\"]): PrimitiveType {\n switch (primitive) {\n case \"line_strip\":\n return \"line strip\";\n case \"triangle_strip\":\n return \"triangle strip\";\n default:\n return primitive;\n }\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\nimport type { PanIntent, ViewportPolicy, ZoomIntent } from \"./types.js\";\n\nexport class InputController {\n private _enabled: boolean = true;\n private activePointerId: number | null = null;\n private lastX: number = 0;\n private lastY: number = 0;\n\n constructor(\n private readonly canvas: HTMLCanvasElement,\n private readonly camera: Camera2D,\n private readonly policy?: ViewportPolicy,\n ) {\n this.bindEvents();\n }\n\n get enabled(): boolean {\n return this._enabled;\n }\n\n set enabled(value: boolean) {\n this._enabled = value;\n }\n\n private bindEvents(): void {\n this.canvas.addEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.addEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.addEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.addEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.addEventListener(\"wheel\", this.onWheel, { passive: false });\n }\n\n private onPointerDown = (e: PointerEvent): void => {\n if (!this._enabled || this.activePointerId !== null) return;\n this.activePointerId = e.pointerId;\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n this.canvas.setPointerCapture(e.pointerId);\n };\n\n private onPointerMove = (e: PointerEvent): void => {\n if (!this._enabled || e.pointerId !== this.activePointerId) return;\n const rect = this.canvas.getBoundingClientRect();\n const dx = rect.width > 0 ? (this.lastX - e.clientX) / rect.width : 0;\n const dy = rect.height > 0 ? (e.clientY - this.lastY) / rect.height : 0;\n const intent = this.applyPanPolicy({ dx, dy });\n if (intent) this.camera.pan(intent);\n this.lastX = e.clientX;\n this.lastY = e.clientY;\n };\n\n private onPointerUp = (e: PointerEvent): void => {\n if (e.pointerId !== this.activePointerId) return;\n this.activePointerId = null;\n if (this.canvas.hasPointerCapture(e.pointerId)) {\n this.canvas.releasePointerCapture(e.pointerId);\n }\n };\n\n private onWheel = (e: WheelEvent): void => {\n if (!this._enabled) return;\n e.preventDefault();\n const factor = e.deltaY < 0 ? 1.1 : 0.9;\n const rect = this.canvas.getBoundingClientRect();\n const cx = rect.width > 0 ? (e.clientX - rect.left) / rect.width : 0.5;\n const cy = rect.height > 0 ? 1 - (e.clientY - rect.top) / rect.height : 0.5;\n const intent = this.applyZoomPolicy({ factor, cx, cy, axis: \"xy\" });\n if (intent) this.camera.zoom(intent);\n };\n\n private applyPanPolicy(intent: PanIntent): PanIntent | null {\n if (!this.policy?.beforePan) return intent;\n return this.policy.beforePan(this.camera, intent);\n }\n\n private applyZoomPolicy(intent: ZoomIntent): ZoomIntent | null {\n if (!this.policy?.beforeZoom) return intent;\n return this.policy.beforeZoom(this.camera, intent);\n }\n\n dispose(): void {\n this.canvas.removeEventListener(\"pointerdown\", this.onPointerDown);\n this.canvas.removeEventListener(\"pointermove\", this.onPointerMove);\n this.canvas.removeEventListener(\"pointerup\", this.onPointerUp);\n this.canvas.removeEventListener(\"pointercancel\", this.onPointerUp);\n this.canvas.removeEventListener(\"wheel\", this.onWheel);\n }\n}\n","import type { Viewport } from \"../core/types.js\";\nimport type { PanIntent, ZoomIntent } from \"./types.js\";\n\nexport class Camera2D {\n private _xMin: number = 0;\n private _xMax: number = 1;\n private _yMin: number = 0;\n private _yMax: number = 1;\n\n get xMin(): number {\n return this._xMin;\n }\n\n get xMax(): number {\n return this._xMax;\n }\n\n get yMin(): number {\n return this._yMin;\n }\n\n get yMax(): number {\n return this._yMax;\n }\n\n get viewport(): Viewport {\n return { xMin: this._xMin, xMax: this._xMax, yMin: this._yMin, yMax: this._yMax };\n }\n\n get xScale(): number {\n return 2 / (this._xMax - this._xMin);\n }\n\n get xOffset(): number {\n return -(this._xMin + this._xMax) / (this._xMax - this._xMin);\n }\n\n get yScale(): number {\n return 2 / (this._yMax - this._yMin);\n }\n\n get yOffset(): number {\n return -(this._yMin + this._yMax) / (this._yMax - this._yMin);\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n const next = {\n xMin: v.xMin ?? this._xMin,\n xMax: v.xMax ?? this._xMax,\n yMin: v.yMin ?? this._yMin,\n yMax: v.yMax ?? this._yMax,\n };\n Camera2D.assertValidViewport(next);\n this._xMin = next.xMin;\n this._xMax = next.xMax;\n this._yMin = next.yMin;\n this._yMax = next.yMax;\n }\n\n pan(intent: PanIntent): void {\n const { dx, dy } = intent;\n Camera2D.assertFinite(\"dx\", dx);\n Camera2D.assertFinite(\"dy\", dy);\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n this.setViewport({\n xMin: this._xMin + dx * rangeX,\n xMax: this._xMax + dx * rangeX,\n yMin: this._yMin + dy * rangeY,\n yMax: this._yMax + dy * rangeY,\n });\n }\n\n zoom(intent: ZoomIntent): void {\n const { factor, cx, cy, axis } = intent;\n Camera2D.assertFinite(\"factor\", factor);\n Camera2D.assertFinite(\"cx\", cx);\n Camera2D.assertFinite(\"cy\", cy);\n if (factor <= 0) throw new RangeError(\"Camera2D zoom factor must be > 0.\");\n\n const rangeX = this._xMax - this._xMin;\n const rangeY = this._yMax - this._yMin;\n const dataCx = this._xMin + rangeX * cx;\n const dataCy = this._yMin + rangeY * cy;\n const newRangeX = axis === \"y\" ? rangeX : rangeX / factor;\n const newRangeY = axis === \"x\" ? rangeY : rangeY / factor;\n this.setViewport({\n xMin: dataCx - newRangeX * cx,\n xMax: dataCx + newRangeX * (1 - cx),\n yMin: dataCy - newRangeY * cy,\n yMax: dataCy + newRangeY * (1 - cy),\n });\n }\n\n toClip(x: number, y: number): [number, number] {\n return [\n x * this.xScale + this.xOffset,\n y * this.yScale + this.yOffset,\n ];\n }\n\n toScreen(clipX: number, clipY: number, canvasWidth: number, canvasHeight: number): [number, number] {\n return [\n (clipX + 1) * 0.5 * canvasWidth,\n (1 - clipY) * 0.5 * canvasHeight,\n ];\n }\n\n clone(): Camera2D {\n const c = new Camera2D();\n c.setViewport(this.viewport);\n return c;\n }\n\n private static assertValidViewport(v: Viewport): void {\n Camera2D.assertFinite(\"xMin\", v.xMin);\n Camera2D.assertFinite(\"xMax\", v.xMax);\n Camera2D.assertFinite(\"yMin\", v.yMin);\n Camera2D.assertFinite(\"yMax\", v.yMax);\n if (v.xMax <= v.xMin) throw new RangeError(\"Camera2D requires xMax > xMin.\");\n if (v.yMax <= v.yMin) throw new RangeError(\"Camera2D requires yMax > yMin.\");\n }\n\n private static assertFinite(name: string, value: number): void {\n if (!Number.isFinite(value)) throw new RangeError(`Camera2D ${name} must be finite.`);\n }\n}\n","import type { Camera2D } from \"./Camera2D.js\";\n\nexport class AxisController {\n constructor(private readonly camera: Camera2D) {}\n\n getXTickValues(canvasWidth: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.xMin, this.camera.xMax, canvasWidth, maxTicks, 80, target);\n }\n\n getYTickValues(canvasHeight: number, maxTicks: number = 10, target: number[] = []): number[] {\n return this.getTickValues(this.camera.yMin, this.camera.yMax, canvasHeight, maxTicks, 48, target);\n }\n\n formatValue(value: number): string {\n if (Math.abs(value) < 1e-12) return \"0\";\n const abs = Math.abs(value);\n if (abs >= 1e6 || abs < 1e-3) return value.toExponential(2);\n if (abs >= 100) return value.toFixed(0);\n if (abs >= 10) return value.toFixed(1);\n return value.toFixed(2);\n }\n\n private getTickValues(min: number, max: number, pixelSize: number, maxTicks: number, minPixelSpacing: number, target: number[]): number[] {\n target.length = 0;\n if (pixelSize <= 0 || maxTicks <= 0) return target;\n\n const range = max - min;\n if (!Number.isFinite(range) || range <= 0) return target;\n\n const targetTicks = Math.max(2, Math.min(maxTicks, Math.floor(pixelSize / minPixelSpacing)));\n const step = this.niceStep(range / (targetTicks - 1));\n const firstIndex = Math.floor(min / step);\n const lastIndex = Math.ceil(max / step);\n\n for (let index = firstIndex; index <= lastIndex && target.length < maxTicks + 2; index++) {\n target.push(this.normalizeTick(index * step, step));\n }\n\n return target;\n }\n\n private niceStep(rawStep: number): number {\n const magnitude = 10 ** Math.floor(Math.log10(rawStep));\n const normalized = rawStep / magnitude;\n\n if (normalized <= 1.5) return magnitude;\n if (normalized <= 3) return 2 * magnitude;\n if (normalized <= 7) return 5 * magnitude;\n return 10 * magnitude;\n }\n\n private normalizeTick(value: number, step: number): number {\n const decimals = Math.max(0, -Math.floor(Math.log10(step)) + 2);\n const normalized = Number(value.toFixed(decimals));\n return Object.is(normalized, -0) ? 0 : normalized;\n }\n}\n","import type { SeriesConfig, SeriesStyle, Dataset } from \"../core/types.js\";\nimport { SeriesStore } from \"../core/SeriesStore.js\";\nimport { RingBuffer } from \"../core/RingBuffer.js\";\nimport { Renderer } from \"../render/Renderer.js\";\nimport { ReglBackend } from \"../render/ReglBackend.js\";\nimport type { GpuBuffer } from \"../render/types.js\";\nimport { InputController } from \"../interaction/InputController.js\";\nimport { Camera2D } from \"../interaction/Camera2D.js\";\nimport { AxisController } from \"../interaction/AxisController.js\";\nimport type { ViewportPolicy } from \"../interaction/types.js\";\n\nconst RAW_LINE_VERTEX_CAPACITY = 16_384;\nconst GRID_LINE_VERTEX_CAPACITY = 64;\n\nexport interface ChartOptions {\n readonly viewportPolicy?: ViewportPolicy;\n readonly grid?: boolean;\n readonly gridStyle?: Partial<SeriesStyle>;\n}\n\nexport interface ChartFrameStats {\n fps: number;\n frameMs: number;\n pointsRendered: number;\n drawCalls: number;\n uploadBytes: number;\n renderMode: \"none\" | \"raw\" | \"minmax\" | \"mixed\";\n}\n\nexport class Chart {\n private series: SeriesStore[] = [];\n private camera: Camera2D;\n private axis: AxisController;\n private renderer: Renderer;\n private input: InputController;\n private rawLineBuffer: GpuBuffer;\n private rawLineData: Float32Array;\n private gridBuffer: GpuBuffer;\n private gridData: Float32Array;\n private gridStyle: SeriesStyle;\n private readonly xTicks: number[] = [];\n private readonly yTicks: number[] = [];\n private stats: ChartFrameStats = {\n fps: 0,\n frameMs: 0,\n pointsRendered: 0,\n drawCalls: 0,\n uploadBytes: 0,\n renderMode: \"none\",\n };\n private resizeObserver: ResizeObserver | null = null;\n private lastFrameAt: number = 0;\n private _rafId: number = 0;\n\n constructor(private readonly canvas: HTMLCanvasElement, private readonly options: ChartOptions = {}) {\n this.applyCanvasSize();\n this.camera = new Camera2D();\n this.axis = new AxisController(this.camera);\n this.renderer = new Renderer(new ReglBackend(canvas));\n this.input = new InputController(canvas, this.camera, options.viewportPolicy);\n this.rawLineData = new Float32Array(RAW_LINE_VERTEX_CAPACITY * 2);\n this.rawLineBuffer = this.renderer.createFloatBuffer(this.rawLineData.length);\n this.gridData = new Float32Array(GRID_LINE_VERTEX_CAPACITY * 2);\n this.gridBuffer = this.renderer.createFloatBuffer(this.gridData.length);\n this.gridStyle = {\n color: options.gridStyle?.color ?? [0.22, 0.30, 0.44, 0.45],\n lineWidth: options.gridStyle?.lineWidth ?? 1,\n };\n if (typeof ResizeObserver !== \"undefined\") {\n this.resizeObserver = new ResizeObserver(() => this.resize());\n this.resizeObserver.observe(this.canvas);\n }\n }\n\n addSeries(config: SeriesConfig, style?: Partial<SeriesStyle>): SeriesStore {\n const dataset: Dataset = config.dataset ?? new RingBuffer(config.capacity);\n const s = new SeriesStore(dataset, config, {\n color: style?.color ?? [0.3, 0.6, 1.0, 1.0],\n lineWidth: style?.lineWidth ?? 1,\n });\n this.series.push(s);\n return s;\n }\n\n removeSeries(series: SeriesStore): boolean {\n const index = this.series.indexOf(series);\n if (index === -1) return false;\n\n this.series.splice(index, 1);\n return true;\n }\n\n setViewport(v: { xMin?: number; xMax?: number; yMin?: number; yMax?: number }): void {\n this.camera.setViewport(v);\n }\n\n resize(dpr: number = globalThis.devicePixelRatio): boolean {\n const resized = this.applyCanvasSize(dpr);\n if (resized) {\n this.renderer.viewport(0, 0, this.canvas.width, this.canvas.height);\n }\n return resized;\n }\n\n getFrameStats(target: ChartFrameStats = { fps: 0, frameMs: 0, pointsRendered: 0, drawCalls: 0, uploadBytes: 0, renderMode: \"none\" }): ChartFrameStats {\n target.fps = this.stats.fps;\n target.frameMs = this.stats.frameMs;\n target.pointsRendered = this.stats.pointsRendered;\n target.drawCalls = this.stats.drawCalls;\n target.uploadBytes = this.stats.uploadBytes;\n target.renderMode = this.stats.renderMode;\n return target;\n }\n\n start(): void {\n const frame = (): void => {\n this._rafId = requestAnimationFrame(frame);\n this.render();\n };\n this._rafId = requestAnimationFrame(frame);\n }\n\n stop(): void {\n cancelAnimationFrame(this._rafId);\n }\n\n private render(): void {\n const frameStartedAt = performance.now();\n if (this.lastFrameAt > 0) {\n this.stats.fps = 1000 / (frameStartedAt - this.lastFrameAt);\n }\n this.lastFrameAt = frameStartedAt;\n this.stats.pointsRendered = 0;\n this.stats.drawCalls = 0;\n this.stats.uploadBytes = 0;\n this.stats.renderMode = \"none\";\n\n this.options.viewportPolicy?.beforeRender?.(this.camera);\n this.renderer.clear(0.08, 0.10, 0.16, 1);\n\n const viewport = this.camera.viewport;\n if (this.options.grid !== false) {\n const gridVertexCount = this.writeGridVertices(viewport);\n if (gridVertexCount > 0) {\n this.renderer.updateFloatBuffer(this.gridBuffer, this.gridData);\n this.renderer.drawLines(this.gridBuffer, gridVertexCount, this.gridStyle, this.camera);\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.gridData.byteLength;\n }\n }\n\n for (const s of this.series) {\n if (!s.visible) continue;\n const visibleSamples = s.visibleSampleCount(viewport);\n const dense = visibleSamples > RAW_LINE_VERTEX_CAPACITY;\n const count = dense\n ? s.copyMinMaxVisible(viewport, this.rawLineData, Math.min(this.canvas.width, RAW_LINE_VERTEX_CAPACITY >> 1))\n : s.copyRawVisible(viewport, this.rawLineData, RAW_LINE_VERTEX_CAPACITY);\n if (count < 2) continue;\n this.renderer.updateFloatBuffer(this.rawLineBuffer, this.rawLineData);\n if (dense) {\n this.renderer.drawMinMaxSegments(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"minmax\");\n } else {\n this.renderer.drawLineStrip(this.rawLineBuffer, count, s.style, this.camera);\n this.recordRenderMode(\"raw\");\n }\n this.stats.pointsRendered += count;\n this.stats.drawCalls++;\n this.stats.uploadBytes += this.rawLineData.byteLength;\n }\n\n this.stats.frameMs = performance.now() - frameStartedAt;\n }\n\n dispose(): void {\n this.stop();\n this.resizeObserver?.disconnect();\n this.input.dispose();\n this.renderer.dispose();\n }\n\n private applyCanvasSize(dpr: number = globalThis.devicePixelRatio): boolean {\n const scale = Number.isFinite(dpr) ? Math.max(1, dpr) : 1;\n const width = Math.max(1, Math.floor(this.canvas.clientWidth * scale));\n const height = Math.max(1, Math.floor(this.canvas.clientHeight * scale));\n if (this.canvas.width === width && this.canvas.height === height) return false;\n\n this.canvas.width = width;\n this.canvas.height = height;\n return true;\n }\n\n private writeGridVertices(viewport: { xMin: number; xMax: number; yMin: number; yMax: number }): number {\n this.axis.getXTickValues(this.canvas.width, 12, this.xTicks);\n this.axis.getYTickValues(this.canvas.height, 8, this.yTicks);\n\n let vertexCount = 0;\n for (const x of this.xTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMin;\n vertexCount++;\n this.gridData[vertexCount * 2] = x;\n this.gridData[vertexCount * 2 + 1] = viewport.yMax;\n vertexCount++;\n }\n\n for (const y of this.yTicks) {\n if (vertexCount + 2 > GRID_LINE_VERTEX_CAPACITY) return vertexCount;\n this.gridData[vertexCount * 2] = viewport.xMin;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n this.gridData[vertexCount * 2] = viewport.xMax;\n this.gridData[vertexCount * 2 + 1] = y;\n vertexCount++;\n }\n\n return vertexCount;\n }\n\n private recordRenderMode(mode: \"raw\" | \"minmax\"): void {\n if (this.stats.renderMode === \"none\") {\n this.stats.renderMode = mode;\n } else if (this.stats.renderMode !== mode) {\n this.stats.renderMode = \"mixed\";\n }\n }\n}\n","import type { Dataset, TimeRange } from \"./types.js\";\n\nexport class StaticDataset implements Dataset {\n constructor(\n private readonly xData: ArrayLike<number>,\n private readonly yData: ArrayLike<number>,\n ) {}\n\n get length(): number {\n return Math.min(this.xData.length, this.yData.length);\n }\n\n get range(): TimeRange | null {\n if (this.length === 0) return null;\n return { start: this.xData[0]!, end: this.xData[this.length - 1]! };\n }\n\n getX(index: number): number {\n this.assertValidIndex(index);\n return this.xData[index]!;\n }\n\n getY(index: number): number {\n this.assertValidIndex(index);\n return this.yData[index]!;\n }\n\n lowerBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! < x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n upperBoundX(x: number): number {\n let lo = 0;\n let hi = this.length;\n while (lo < hi) {\n const mid = lo + ((hi - lo) >> 1);\n if (this.xData[mid]! <= x) lo = mid + 1;\n else hi = mid;\n }\n return lo;\n }\n\n private assertValidIndex(index: number): void {\n if (!Number.isInteger(index) || index < 0 || index >= this.length) {\n throw new RangeError(`StaticDataset index out of range: ${index}`);\n }\n }\n}\n"],"mappings":"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"}
|
package/dist/ui/Chart.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,
|
|
1
|
+
{"version":3,"file":"Chart.d.ts","sourceRoot":"","sources":["../../src/ui/Chart.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAW,MAAM,kBAAkB,CAAC;AAC3E,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAQrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,yBAAyB,CAAC;AAK9D,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,cAAc,CAAC,EAAE,cAAc,CAAC;IACzC,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,CAAC;CAC3C;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;CACjD;AAED,qBAAa,KAAK;IAyBJ,OAAO,CAAC,QAAQ,CAAC,MAAM;IAAqB,OAAO,CAAC,QAAQ,CAAC,OAAO;IAxBhF,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAW;IACzB,OAAO,CAAC,IAAI,CAAiB;IAC7B,OAAO,CAAC,QAAQ,CAAW;IAC3B,OAAO,CAAC,KAAK,CAAkB;IAC/B,OAAO,CAAC,aAAa,CAAY;IACjC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,UAAU,CAAY;IAC9B,OAAO,CAAC,QAAQ,CAAe;IAC/B,OAAO,CAAC,SAAS,CAAc;IAC/B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAgB;IACvC,OAAO,CAAC,KAAK,CAOX;IACF,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,WAAW,CAAa;IAChC,OAAO,CAAC,MAAM,CAAa;gBAEE,MAAM,EAAE,iBAAiB,EAAmB,OAAO,GAAE,YAAiB;IAoBnG,SAAS,CAAC,MAAM,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO,CAAC,WAAW,CAAC,GAAG,WAAW;IAU1E,YAAY,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO;IAQ1C,WAAW,CAAC,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI;IAIpF,MAAM,CAAC,GAAG,GAAE,MAAoC,GAAG,OAAO;IAQ1D,aAAa,CAAC,MAAM,GAAE,eAA6G,GAAG,eAAe;IAUrJ,KAAK,IAAI,IAAI;IAQb,IAAI,IAAI,IAAI;IAIZ,OAAO,CAAC,MAAM;IAiDd,OAAO,IAAI,IAAI;IAOf,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,iBAAiB;IA4BzB,OAAO,CAAC,gBAAgB;CAOzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "blazeplot",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "BlazePlot contributors"
|
|
6
6
|
},
|
|
@@ -25,8 +25,7 @@
|
|
|
25
25
|
"files": [
|
|
26
26
|
"dist",
|
|
27
27
|
"README.md",
|
|
28
|
-
"LICENSE"
|
|
29
|
-
"ROADMAP.md"
|
|
28
|
+
"LICENSE"
|
|
30
29
|
],
|
|
31
30
|
"scripts": {
|
|
32
31
|
"dev": "vite",
|
package/ROADMAP.md
DELETED
|
@@ -1,263 +0,0 @@
|
|
|
1
|
-
# BlazePlot — Roadmap
|
|
2
|
-
|
|
3
|
-
**BlazePlot is a real-time LOD time series rendering engine, not a plotting library.**
|
|
4
|
-
|
|
5
|
-
Target: 10M points resident, 60 Hz append/update, pan/zoom fluid, render O(pixel) not O(samples), zero allocations in frame loop, multi-series, line/envelope/scatter.
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Architecture
|
|
10
|
-
|
|
11
|
-
```
|
|
12
|
-
src/
|
|
13
|
-
core/ # Data engine — no UI, no GPU
|
|
14
|
-
render/ # GPU abstraction + regl V1 backend
|
|
15
|
-
interaction/ # Camera, input, axis ticks
|
|
16
|
-
ui/ # Orchestrator (Chart)
|
|
17
|
-
tests/ # bun test — RingBuffer, MinMaxPyramid, Camera2D
|
|
18
|
-
preview/ # Dev preview harness, detached from package build
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
The core split: **data engine** and **renderer** are separate. A `SeriesStore` owns a `RingBuffer` + `MinMaxPyramid`. The renderer reads LOD views, never raw data.
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
interface GpuBackend { … } # abstract GPU
|
|
25
|
-
class ReglBackend { … } # V1 implementation
|
|
26
|
-
class FutureWebGPUBackend { …} # V3
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
**Camera2D** is the canonical viewport model (data-space xMin/xMax/yMin/yMax). Scale/offset for shader uniforms are derived getters. `ViewportPlanner` was removed — its pan/zoom live on `Camera2D` directly.
|
|
30
|
-
|
|
31
|
-
Package output is detached from the preview app:
|
|
32
|
-
- `bun run dev` serves `preview/`.
|
|
33
|
-
- `bun run build` emits `dist/index.js` and `dist/index.d.ts` from `src/index.ts`.
|
|
34
|
-
- `preview/` is excluded from npm package contents.
|
|
35
|
-
|
|
36
|
-
---
|
|
37
|
-
|
|
38
|
-
## Phase 1 — Vertical slice: line on screen
|
|
39
|
-
|
|
40
|
-
**Status: in progress**
|
|
41
|
-
|
|
42
|
-
Get one end-to-end path working: append → visible raw extraction → GPU upload → draw.
|
|
43
|
-
|
|
44
|
-
- [x] WebGL2 context + regl init
|
|
45
|
-
- [x] Canvas resize + DPR handling
|
|
46
|
-
- [x] Streaming append with debug overlay
|
|
47
|
-
- [x] `ReglBackend` — createBuffer, updateBuffer, createProgram, cached draw commands
|
|
48
|
-
- [x] Raw line strip draw via regl
|
|
49
|
-
- [x] Wire `Chart.render()`: clear → copy visible raw range → upload → draw
|
|
50
|
-
- [x] **Benchmark overlay**: fps, ms/frame, points rendered, draw calls, upload bytes
|
|
51
|
-
|
|
52
|
-
This is the shortest path to seeing data on screen. Benchmarking the full pipeline comes after.
|
|
53
|
-
|
|
54
|
-
---
|
|
55
|
-
|
|
56
|
-
## Phase 2 — Core data engine
|
|
57
|
-
|
|
58
|
-
**Status: basic scaffold implemented, correctness tests passing**
|
|
59
|
-
|
|
60
|
-
- [x] `RingBuffer` — append-only, Float64Array x / Float32Array y, logical index access, ring-wrap aware search
|
|
61
|
-
- [x] `MinMaxPyramid` — min/max per level (bucket size 2), correct higher-level aggregation, ring-wrap aware builds, `query()` returns `LODView`
|
|
62
|
-
- [x] `SeriesStore` — buffer + pyramid + style, dirty tracking
|
|
63
|
-
- [x] `Camera2D` — viewport model with pan, zoom, setViewport, clip/screen transforms
|
|
64
|
-
- [x] `DataCursor` — binary search by timestamp
|
|
65
|
-
- [x] Tests for `RingBuffer`, `MinMaxPyramid`, and `Camera2D` (bun test runner)
|
|
66
|
-
- [ ] **Incremental pyramid update** — current: full rebuild on every `build()`. Target: O(log N) per append, updating only closed buckets in the chain. This is the core competitive advantage — must be designed before release.
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Phase 2.5 — Worker pipeline
|
|
71
|
-
|
|
72
|
-
**Status: not started**
|
|
73
|
-
|
|
74
|
-
```
|
|
75
|
-
producer thread / worker ──► SharedArrayBuffer ──► downsampling worker ──► main thread
|
|
76
|
-
```
|
|
77
|
-
|
|
78
|
-
- [ ] Ingest worker — receives data, writes to ring buffer via SharedArrayBuffer
|
|
79
|
-
- [ ] Downsample worker — incremental pyramid update off main thread
|
|
80
|
-
- [ ] Main thread — reads coherent snapshot, uploads visible range to GPU
|
|
81
|
-
- [ ] `OffscreenCanvas` optional path
|
|
82
|
-
|
|
83
|
-
Data structures have correctness coverage, but the incremental pyramid API must be finalized before moving them off main thread.
|
|
84
|
-
|
|
85
|
-
---
|
|
86
|
-
|
|
87
|
-
## Phase 3 — regl renderer (full)
|
|
88
|
-
|
|
89
|
-
**Status: not started**
|
|
90
|
-
|
|
91
|
-
- [x] `ReglBackend` — createBuffer, updateBuffer (subdata), createProgram, draw command cache
|
|
92
|
-
- [ ] Persistent buffer pool (no Float32Array allocs per frame)
|
|
93
|
-
- [x] Raw line strip for few visible points
|
|
94
|
-
- [x] `MinMaxSegmentRenderer` — vertical min/max segments for dense viewports
|
|
95
|
-
- [ ] Instanced draw for segment mode
|
|
96
|
-
- [x] Camera transform as uniforms (scale/offset getters on Camera2D)
|
|
97
|
-
- [ ] Two shader modes: `line.vert/frag` and `segment.vert/frag`
|
|
98
|
-
- [x] `Renderer.drawMinMaxSegments`
|
|
99
|
-
- [ ] Draw call batching per shader mode
|
|
100
|
-
|
|
101
|
-
---
|
|
102
|
-
|
|
103
|
-
## Phase 4 — Interaction
|
|
104
|
-
|
|
105
|
-
**Status: implemented (camera + input)**
|
|
106
|
-
|
|
107
|
-
- [x] `Camera2D` — viewport model with pan, zoom, setViewport
|
|
108
|
-
- [x] `InputController` — pointer pan, wheel zoom, touch via Pointer Events
|
|
109
|
-
- [x] `ViewportPolicy` — transforms pan/zoom intents and can update camera before render
|
|
110
|
-
- [x] Preview synced-X policy — X stays live-followed while wheel zoom/pan affect Y only
|
|
111
|
-
- [x] Camera uniforms propagated to shaders per frame
|
|
112
|
-
- [ ] LOD re-query on pan/zoom (viewport change → new LODView)
|
|
113
|
-
- [x] `AxisController` — smart tick generation and label formatting
|
|
114
|
-
- [ ] Axis tick rendering (smart tick count, label formatting)
|
|
115
|
-
- [x] Grid line rendering
|
|
116
|
-
|
|
117
|
-
Camera modifies `Camera2D`, renderer reads it. No direct data access from interaction layer.
|
|
118
|
-
|
|
119
|
-
---
|
|
120
|
-
|
|
121
|
-
## Phase 5 — Multi-series
|
|
122
|
-
|
|
123
|
-
**Status: data model ready**
|
|
124
|
-
|
|
125
|
-
- [x] `Chart.addSeries()` supports multiple stores
|
|
126
|
-
- [x] Each `SeriesStore` has independent buffer + pyramid + style
|
|
127
|
-
- [ ] Batched draw calls (same shader → one draw per series group)
|
|
128
|
-
- [ ] Shared X axis optional, independent Y per series
|
|
129
|
-
- [x] Color/style per-series
|
|
130
|
-
- [x] Series visibility toggle
|
|
131
|
-
|
|
132
|
-
Limit: solid lines only, no markers, no antialias, no spline, no fill.
|
|
133
|
-
|
|
134
|
-
---
|
|
135
|
-
|
|
136
|
-
## Phase 6 — Public API
|
|
137
|
-
|
|
138
|
-
**Status: basic shape exists**
|
|
139
|
-
|
|
140
|
-
- [x] `new Chart(canvas)`
|
|
141
|
-
- [x] `new Chart(canvas, { viewportPolicy })`
|
|
142
|
-
- [x] `chart.addSeries(config, style)`
|
|
143
|
-
- [x] `chart.setViewport({ xMin, xMax, yMin, yMax })`
|
|
144
|
-
- [x] `chart.start()` / `chart.stop()`
|
|
145
|
-
- [x] `chart.resize()` — handle container resize with DPR
|
|
146
|
-
- [x] `series.append(x, y)` — accepts typed arrays
|
|
147
|
-
- [x] `series.clear()`
|
|
148
|
-
- [x] `chart.removeSeries(series)`
|
|
149
|
-
- [ ] Axis labels / tick rendering
|
|
150
|
-
- [x] Grid
|
|
151
|
-
- [ ] Legend
|
|
152
|
-
- [ ] Tooltip / hit testing
|
|
153
|
-
- [ ] Export image
|
|
154
|
-
- [ ] Theme system
|
|
155
|
-
- [x] ResizeObserver integration
|
|
156
|
-
|
|
157
|
-
Package status:
|
|
158
|
-
- [x] `exports`, `main`, `module`, and `types` point at `dist/`
|
|
159
|
-
- [x] Vite library build from `src/index.ts`
|
|
160
|
-
- [x] Declaration emit from `src/` only via Vite d.ts plugin
|
|
161
|
-
- [x] `bun pm pack --dry-run` includes package files only
|
|
162
|
-
|
|
163
|
-
---
|
|
164
|
-
|
|
165
|
-
## Downsampler — LOD engine
|
|
166
|
-
|
|
167
|
-
**Status: basic pyramid built, not incremental**
|
|
168
|
-
|
|
169
|
-
Current: `MinMaxPyramid.build()` does a full bottom-up rebuild. Target:
|
|
170
|
-
|
|
171
|
-
```
|
|
172
|
-
raw level: x: Float64Array, y: Float32Array
|
|
173
|
-
level 1: minY/maxY per bucket of 2
|
|
174
|
-
level 2: minY/maxY per bucket of 4
|
|
175
|
-
level 3: minY/maxY per bucket of 8
|
|
176
|
-
…
|
|
177
|
-
```
|
|
178
|
-
|
|
179
|
-
**Incremental append**: each append updates only the chain of closed buckets. Query is O(buckets in viewport).
|
|
180
|
-
|
|
181
|
-
Planned incremental design:
|
|
182
|
-
- Raw samples are addressed by monotonically increasing logical sample index, not physical ring position.
|
|
183
|
-
- Level `n` bucket width is `bucketSize ** (n + 1)` raw samples.
|
|
184
|
-
- Appending a sample updates only level 0 while its bucket is open.
|
|
185
|
-
- When a bucket closes, its min/max pair is propagated upward as one input sample for the next level.
|
|
186
|
-
- Higher levels never read raw Y values; they combine child min/max pairs.
|
|
187
|
-
- Ring wrap invalidates buckets whose covered logical index range was overwritten.
|
|
188
|
-
- Query receives a visible logical index range from x-search and maps that range to bucket indices using the selected level width.
|
|
189
|
-
|
|
190
|
-
**Query**: `samples_per_pixel = visible_samples / plotWidthPx`, pick `level = max(0, ceil(log2(samples_per_pixel)) - 1)`, return min/max pairs.
|
|
191
|
-
|
|
192
|
-
**Render decision**:
|
|
193
|
-
- few points → raw line strip
|
|
194
|
-
- many points → vertical min/max segments
|
|
195
|
-
- very many → envelope mesh
|
|
196
|
-
|
|
197
|
-
---
|
|
198
|
-
|
|
199
|
-
## Backend strategy
|
|
200
|
-
|
|
201
|
-
```
|
|
202
|
-
V1: WebGL2 + regl ← CURRENT
|
|
203
|
-
V2: Backend abstraction ← In place (GpuBackend interface)
|
|
204
|
-
V3: WebGPU backend ← Future
|
|
205
|
-
```
|
|
206
|
-
|
|
207
|
-
regl is the V1 backend, not the architecture. The `GpuBackend` interface decouples core from GPU.
|
|
208
|
-
|
|
209
|
-
regl rules for V1:
|
|
210
|
-
- Persistent buffers (no re-create per frame)
|
|
211
|
-
- Precompiled regl commands
|
|
212
|
-
- `subdata` on small ranges
|
|
213
|
-
- Batched draw calls
|
|
214
|
-
- Simple shaders, camera in uniforms
|
|
215
|
-
- WebGL2 required (no fallback)
|
|
216
|
-
|
|
217
|
-
---
|
|
218
|
-
|
|
219
|
-
## Overflow semantics
|
|
220
|
-
|
|
221
|
-
**Status: undecided**
|
|
222
|
-
|
|
223
|
-
`RingBuffer` wraps silently at capacity. For streaming this is usually correct, but it should be explicit. Options:
|
|
224
|
-
- Ring-buffer with wrap notification
|
|
225
|
-
- Fixed capacity with error on overflow
|
|
226
|
-
- Auto-growing buffer (breaks streaming contract)
|
|
227
|
-
|
|
228
|
-
Deferred until we have a concrete use case.
|
|
229
|
-
|
|
230
|
-
---
|
|
231
|
-
|
|
232
|
-
## What we're NOT doing (V1)
|
|
233
|
-
|
|
234
|
-
- SVG / Canvas2D fallback
|
|
235
|
-
- Spline interpolation
|
|
236
|
-
- Complex fill (gradient, area below)
|
|
237
|
-
- Markers / point symbols
|
|
238
|
-
- Antialias perfection
|
|
239
|
-
- Recalculating axes in render loop
|
|
240
|
-
- Per-series draw call without batching
|
|
241
|
-
|
|
242
|
-
---
|
|
243
|
-
|
|
244
|
-
## Competitive advantage
|
|
245
|
-
|
|
246
|
-
Not WebGL. The core differentiator:
|
|
247
|
-
|
|
248
|
-
> Incremental min/max pyramid + zero-allocation render loop + Camera2D viewport model
|
|
249
|
-
|
|
250
|
-
Never render 10M points. Render `plotWidthPx * 2` (2k–8k vertices).
|
|
251
|
-
|
|
252
|
-
---
|
|
253
|
-
|
|
254
|
-
## Future / difficult
|
|
255
|
-
|
|
256
|
-
- Multi-chart sync
|
|
257
|
-
- Multiple Y axes
|
|
258
|
-
- Spectrogram / heatmap
|
|
259
|
-
- Large scatter ( > 1M points )
|
|
260
|
-
- OHLC / candlestick
|
|
261
|
-
- FFT / waterfall
|
|
262
|
-
- Out-of-core data ( > RAM)
|
|
263
|
-
- WebGPU backend
|