From 71d72c53f37d3d0d8fdf0708d244f5945307f9ed Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 24 Feb 2026 11:18:01 +0000 Subject: [PATCH] Unify single-track and multi-track paths in ConfigurableGraph The single-track path (primary linePlot + addDataPoints()) was dead code: KinematicsGraphNode exclusively uses setTrackData() / clearAllTracks(), so the primary linePlot was always empty and addDataPoints() was never called from outside ConfigurableGraph. - Remove the primary LinePlot and its creation from ConfigurableGraph; the clippedDataContainer now only holds per-track plots from setTrackData() - Pass null for linePlot to the primary GraphDataManager, which now serves solely as a coordinator for tick spacing, axis reset, and the manuallyZoomed flag shared by gesture handlers - Make GraphDataManager.linePlot: LinePlot | null and guard the three setDataSet() call sites with optional chaining - Delete the dead public addDataPoints() and private getValueForAxis() methods No behaviour change: the primary linePlot rendered nothing (0 points), and the ZoomGestureHandler's getDataPointCount() > 1 branch was already unreachable because the primary manager was never populated. https://claude.ai/code/session_01JZLVYHZUundEnN8z2tM4mV --- src/screen-name/graph/ConfigurableGraph.ts | 51 ++-------------------- src/screen-name/graph/GraphDataManager.ts | 10 ++--- 2 files changed, 9 insertions(+), 52 deletions(-) diff --git a/src/screen-name/graph/ConfigurableGraph.ts b/src/screen-name/graph/ConfigurableGraph.ts index 08f6b24..d5ecd4f 100644 --- a/src/screen-name/graph/ConfigurableGraph.ts +++ b/src/screen-name/graph/ConfigurableGraph.ts @@ -267,15 +267,8 @@ export default class ConfigurableGraph extends Node { }); this.graphContentNode.addChild(this.xAxisInteractionRegion); - // Create line plot - const linePlot = new LinePlot(this.chartTransform, [], { - stroke: TrackLabColors.plot1Property, - lineWidth: PLOT_LINE_WIDTH, - }); - - // Wrap line plot in a clipped container to prevent overflow beyond the grid + // Clipped container for all track line plots; prevents overflow beyond the grid. this.clippedDataContainer = new Node({ - children: [linePlot], clipArea: Shape.rect(0, 0, width, height), }); this.graphContentNode.addChild(this.clippedDataContainer); @@ -308,8 +301,9 @@ export default class ConfigurableGraph extends Node { yTickLabelSet, }; - // Initialize data manager - this.dataManager = new GraphDataManager(this.chartTransform, linePlot, maxDataPoints, this.gridConfig); + // Coordinator for tick spacing, axis reset, and zoom-flag state shared by + // gesture handlers. No LinePlot: track plots are managed via setTrackData(). + this.dataManager = new GraphDataManager(this.chartTransform, null, maxDataPoints, this.gridConfig); // Create controls panel helper this.controlsPanel = new GraphControlsPanel( @@ -586,43 +580,6 @@ export default class ConfigurableGraph extends Node { this.dataManager.clearData(); } - /** - * Add data points from a record array, mapping each record to the selected axes. - */ - public addDataPoints(dataPoints: Array>): void { - if (dataPoints.length === 0) { - return; - } - - const xProperty = this.xPropertyProperty.value; - const yProperty = this.yPropertyProperty.value; - - const mappedPoints: Array<{ x: number; y: number }> = []; - for (const point of dataPoints) { - const x = this.getValueForAxis(xProperty, point); - const y = this.getValueForAxis(yProperty, point); - if (x !== null && y !== null && Number.isFinite(x) && Number.isFinite(y)) { - mappedPoints.push({ x, y }); - } - } - - if (mappedPoints.length > 0) { - this.dataManager.addDataPoints(mappedPoints); - } - } - - /** - * Get the value for a specific axis from a data point record. - * Dispatches on the PlottableProperty variant: RecordPlottable uses an - * accessor function; LivePlottable reads from a reactive property. - */ - private getValueForAxis(axisProperty: PlottableProperty, point: Record): number | null { - if ("accessor" in axisProperty) { - return axisProperty.accessor(point); - } - return axisProperty.property.value; - } - /** * Update the axis labels (call when units change) */ diff --git a/src/screen-name/graph/GraphDataManager.ts b/src/screen-name/graph/GraphDataManager.ts index b67a33e..4d4bd72 100644 --- a/src/screen-name/graph/GraphDataManager.ts +++ b/src/screen-name/graph/GraphDataManager.ts @@ -39,7 +39,7 @@ export default class GraphDataManager { private readonly maxDataPoints: number; private readonly chartTransform: ChartTransform; - private readonly linePlot: LinePlot; + private readonly linePlot: LinePlot | null; private isManuallyZoomed = false; // Grid and tick components @@ -52,7 +52,7 @@ export default class GraphDataManager { public constructor( chartTransform: ChartTransform, - linePlot: LinePlot, + linePlot: LinePlot | null, maxDataPoints: number, gridConfig: GridVisualizationConfig, ) { @@ -186,7 +186,7 @@ export default class GraphDataManager { const evicted = this.writePoint(xValue, yValue); this.updateMinMaxIncremental(xValue, yValue, evicted); - this.linePlot.setDataSet(this.getOrderedPoints()); + this.linePlot?.setDataSet(this.getOrderedPoints()); if (this.dataSize > 1 && !this.isManuallyZoomed) { this.applyAxisRangesFromExtremes(); @@ -233,7 +233,7 @@ export default class GraphDataManager { this.recomputeMinMax(); } - this.linePlot.setDataSet(this.getOrderedPoints()); + this.linePlot?.setDataSet(this.getOrderedPoints()); if (this.dataSize > 1 && !this.isManuallyZoomed) { this.applyAxisRangesFromExtremes(); @@ -250,7 +250,7 @@ export default class GraphDataManager { this.xMax = -Infinity; this.yMin = Infinity; this.yMax = -Infinity; - this.linePlot.setDataSet([]); + this.linePlot?.setDataSet([]); const defaultRange = new Range(-10, 10); this.chartTransform.setModelXRange(defaultRange);