- Extracted drag/resize logic from Data Explorer into reusable `ui.js` utility.
- Migrated Zoom Sketch from GridStack into a free-floating, draggable, and resizable `z-30` overlay (default size 900x455).
- Restored and optimized auto-hide timing lifecycle for Close-Up mode:
- 0-5s: Clean freeze for data inspection without hovering.
- 5-8s: Fading visual countdown warning prior to panel closure.
- Implemented state flag `zoomPanelExplicitlyClosed` guaranteeing the "X" button correctly masks rapid re-triggers.
- Bound 'g' toggle shortcut to aggressively wipe/close panels when exiting God Mode entirely.
- Added visual "Mouse pointer Out of Bounds" overlay when cursor exits main radar canvas.
- Implemented GridStack.js as the core dashboard manager, enabling responsive dragging and resizing of the Radar, Video, and SpeedGraph panels.
- Replaced global windowResized events with debounced ResizeObserver instances attached to the specific panel containers.
- Fixed a massive memory leak in p5.js sketches by explicitly calling .remove() on old Graphics buffers before recreation.
- Optimized zoomSketch.js by removing destructive canvas teardown calls from radarSketch and using smoothed camera coordinates for tooltip bounding logic.
- Patched tooltip overflow bugs in drawUtils.js and speedGraphSketch.js to intelligently clamp within panel edges, even in narrow columns.
- Disabled native p5 windowResized triggers to prevent double-firing when moving the web app across multiple monitors.
Refactors the rendering logic for both main radar and zoom views to support
high-refresh-rate monitors and 4K displays without performance loss.
Key Changes:
1. Performance & Display:
- Uncapped Frame Rate: Set `p.frameRate(144)` in both sketches. This removes
artificial throttling on high-refresh monitors (75Hz+), eliminating
beat-frequency judder.
- 4K Quality: Removed `p.pixelDensity(1)` restrictions. High-end PCs will
now render at full device resolution (Retina/4K) instead of being downscaled.
2. Zoom Sketch Optimization:
- Viewport Culling: Implemented background slicing logic to only render the
visible portion of the static background image, significantly reducing GPU
bandwidth usage during zoom.
3. UX & Animation:
- Camera Smoothing: Applied a frame-rate independent Lerp (factor 0.5) to the
zoom camera. This mimics the weight and feel of the main radar cursor.
- Visual "Lead": Added a `leadFactor` (0.2) to the dashed hover circle. It
now interpolates between the camera and mouse, making controls feel
instant/elastic even while the view smooths out.
- Coordinate Fixes: Updated tooltip and connector logic to map correctly
from the smoothed camera space to screen space.
Addresses performance bottlenecks on high-end PCs and refines the
zoom interaction model to eliminate jitter while maintaining responsiveness.
Performance Optimizations:
1. High-DPI Scaling Fix:
- Forced `p.pixelDensity(1)` in zoomSketch.
- Issue: Retinal/4K screens were defaulting to pixelDensity 2.0+, causing
the GPU to render 4x the necessary pixels (e.g., 1000x1000 for a 500x500 canvas).
This bandwidth saturation caused FPS drops on powerful GPUs.
2. Refresh Rate Uncap:
- Set `p.frameRate(144)` explicitly.
- Issue: p5.js often throttles to 60fps. On 75Hz+ monitors, this caused a
"beat frequency" judder where update cycles missed display refresh cycles.
UX & Animation Logic:
1. Camera Smoothing (The "Cinematic" Feel):
- Decoupled the Zoom Camera position from the Raw Mouse position.
- Applied a Lerp smoothing factor of 0.5 (aligned with main radarSketch
cursor logic) to create fluid motion without feeling sluggish.
2. Visual "Lead" / Elasticity:
- Introduced `zoomLeadFactor` (0.2) for the dashed hover circle.
- The circle position is interpolated between the Smoothed Camera and
the Raw Mouse.
- Benefit: This creates a visual cue that "leads" the camera, making the
controls feel responsive/instant even while the view smoothly catches up.
3. Coordinate System Fixes:
- Reverted manual world-to-screen reprojection for tooltips.
- Adopted a relative screen-space transform:
(ItemScreenPos - CameraPos) * ZoomFactor.
- This ensures connector lines lock perfectly to visual elements regardless
of camera lag.
- Clamp delta time to minimum of 0 to prevent negative interpolation.
- Add protection against division by zero in SNR color mapping.
- Ensure trajectory points exist before fading alpha calculation.
- Standardize p.deltaTime usage for cross-browser stability.
Refactors animation and interpolation logic to ensure consistent behavior
across different monitor refresh rates (e.g., 60Hz vs 144Hz).
Changes:
- Implement time-delta adjusted smoothing for FPS counter and mouse tracking.
- Update IFT graph scaling in 'dom.js' to use performance-based delta time.
- Remove hardcoded 60FPS limit in zoom sketch to allow native refresh rates.
- Fix vertical tooltip jitter in 'drawUtils.js' by using smoothed mouse coordinates.
- Add 'lastOverlayUpdateTime' to global state for cross-module time tracking.
Adds linear interpolation (lerp) to mouse coordinates in the zoom view
to prevent jitter and provide a smoother user experience when inspecting
radar points.
Changes:
- Add `smoothedMouseX` and `smoothedMouseY` state to `radarSketch.js`.
- Apply smoothing factor (0.5) to mouse movement in the main draw loop.
- Update `handleCloseUpDisplay` and zoom sketch drawing to use smoothed coordinates.
- Ensure coordinates snap to mouse position on the first frame to prevent visual jumping.
radar view (src/drawUtils.js):
- Refactored drawTrackMarkers with a smart collision-resolution algorithm for floating labels.
- Added leader lines and themed tooltips for track IDs and speed data to prevent overlapping.
- Optimized velocity vectors with arrowheads and reduced thickness for better clarity.
- Updated drawRegionsOfInterest to use ROI_CLOSE_Y_MAX constant.
speed graph (src/p5/speedGraphSketch.js):
- Implemented a MATLAB-style spectral color scheme (Blue-Cyan-Green-Yellow-Red) to visualize track density on the CAN speed
line.
- Added a vertical smooth gradient legend bar for track density.
- Switched to robust 95th percentile normalization for density mapping to mitigate outlier noise.
- Synchronized density calculations with the "Confirmed Only" toggle.
- Updated the horizontal legend to reflect density-based coloring.
zoom view (src/p5/zoomSketch.js):
- Adjusted tooltip vertical offset for improved diagonal positioning.
- Disabled internal track detail boxes to prioritize the specialized zoom tooltip system.
This commit introduces a suite of major enhancements to the "Zoom Mode" functionality, focusing on user experience, interaction smoothness, and bug fixes. It refines the data display logic, adds interactive visual feedback, and implements a more intelligent auto-hide behavior.
#### 1. Mouse Smoothing for Zoom Navigation
To address jittery mouse movements at high magnification, a linear interpolation (lerp) filter has been implemented.
- **`radarSketch.js`**: A "smoothed" mouse coordinate is now calculated on each frame when zoom mode is active. This smoothed position is used for all zoom-related logic, including positioning the zoom window's view and detecting hovered items.
- **`drawUtils.js`**: The `handleCloseUpDisplay` function has been updated to accept the smoothed coordinates, ensuring that hover detection is perfectly synchronized with the smoothed visual feedback. This results in a much more fluid and controllable navigation experience in the zoom window.
#### 2. Dynamic and Visual Zoom Feedback
The zoom interaction has been made more intuitive with several visual aids.
- **Variable Hover Radius**: The hover detection radius is now inversely proportional to the zoom factor. This provides a larger, more forgiving selection area when zoomed out and a smaller, more precise area when zoomed in. The formula `constrain(80 / zoomFactor, 5, 25)` is used to keep the radius within a usable range.
- **Zoom Area Rectangle**: A semi-transparent, dashed red rectangle is now drawn on the main radar canvas, centered on the smoothed mouse position. This rectangle visually represents the exact area being magnified in the zoom window.
- **Debug Circle**: For tuning and visualization, a temporary purple circle is drawn on both the main radar canvas and within the zoom sketch. This circle's size dynamically matches the current hover radius, making it easy to see the selection area at any zoom level.
#### 3. Intelligent Auto-Hide with Countdown
The behavior of the zoom window when the user stops hovering over points has been significantly improved.
- **Grace Period**: A 2-second grace period has been added. When the user stops hovering, the zoom window remains active and continues to follow the mouse for 2 seconds before any closing action begins.
- **Visual Countdown**: After the grace period, a 3-second countdown is initiated. The zoom window displays a "Closing in 3... 2... 1..." message, clearly communicating its state to the user.
- **State Management**: The logic in `radarSketch.js` and `state.js` was refactored to correctly manage the delay timer (`zoomHideDelayTimeout`) and the countdown interval (`zoomCountdownInterval`), ensuring the grace period works as intended and the UI updates smoothly.
#### 4. Bug Fixes and Data Consistency
- **Data Synchronization**: Corrected a critical bug where tooltips and rendered markers were using data from different frames. All drawing and tooltip logic in `radarSketch.js`, `zoomSketch.js`, and `drawUtils.js` has been unified to use data exclusively from the `appState.currentFrame`.
- **Console Warning Fix**: Resolved a persistent `CanvasTextAlign` error in the console caused by an incorrect `textAlign(p.LEFT - 2)` call in `zoomSketch.js`.
These changes culminate in a more robust, intuitive, and polished zoom feature that is both more powerful for analysis and more pleasant to use.
This commit introduces significant improvements to the "Zoom Mode" (Close-Up Display) functionality and resolves critical data synchronization bugs related to tooltips and marker rendering.
#### 1. Interactive Zoom Enhancements
To improve user experience and provide better visual feedback during zoom operations, the following features have been added:
- **Dynamic Hover Radius:** The hover detection radius is now inversely proportional to the zoom factor (`appState.zoomFactor`). This provides a larger, more forgiving selection area when zoomed out and a smaller, more precise area when zoomed in. The formula `constrain(80 / zoomFactor, 5, 25)` is used to keep the radius within a usable range.
- **Visual Zoom Area Rectangle:** A semi-transparent, dashed red rectangle is now drawn on the main radar canvas around the mouse cursor. This rectangle visually represents the exact area being displayed in the zoom window, making it clear what is being magnified.
- **Debug Hover Circle:** For tuning and visualization purposes, a temporary purple circle is drawn around the cursor, matching the dynamic hover radius. This makes it easy to see the current size of the selection area as the user zooms in and out with the scroll wheel.
#### 2. Tooltip and Data Display Fixes
A core issue was identified where tooltips and rendered markers were using data from different frames, causing a disconnect between the visualization and the information displayed.
- **Corrected Data Source:** The logic has been unified across `radarSketch.js`, `zoomSketch.js`, and `drawUtils.js` to ensure that both the track markers (`correctedPosition`) and the predicted position markers (`predictedPosition`) are drawn using data exclusively from the `appState.currentFrame`.
- **Aligned Tooltip Information:** The `handleCloseUpDisplay` function was corrected to fetch tooltip data for all markers from the current frame's log. This ensures the connecting lines from the tooltip point to the correct markers on the screen and that the displayed coordinate data matches what is being rendered.
#### 3. Bug Fix: Console Warning
- **Resolved `CanvasTextAlign` Error:** Fixed a persistent console warning (`The provided value 'NaN' is not a valid enum value of type CanvasTextAlign`). The error was caused by an incorrect `textAlign(p.LEFT - 2)` call in `zoomSketch.js`. This has been corrected to the valid `textAlign(p.LEFT, p.TOP)`, eliminating the console spam.
These changes result in a more intuitive, accurate, and bug-free user experience when using the close-up display and inspecting track data.
**Modified Files:**
- `src/p5/radarSketch.js`
- `src/p5/zoomSketch.js`
- `src/drawUtils.js`
This commit introduces several major improvements to the "God Mode" zoom sketch, making it more intuitive and robust. It also resolves two critical race-condition bugs related to canvas resizing and initial data loading.
**Features:**
- **Automatic Zoom on Hover:** The zoom sketch now appears automatically when the user hovers over any data point (track, point cloud, etc.) and disappears after a configurable cooling-off period. This provides a more dynamic and professional user experience, allowing for quick inspection without manual toggling. The zoom window now smoothly follows the cursor during this cooling-off period.
- **Point Index in Tooltip:** The zoom sketch tooltip has been enhanced to display the index of the hovered point within its `pointCloud` array (e.g., "Point 123"). This adds valuable context for debugging and detailed data analysis.
**Bug Fixes:**
- **fix(p5):** Resolves a critical bug where the zoom sketch would go blank after the browser window was resized. This was caused by a race condition where the sketch's canvas was being resized to 0x0 before its container had updated. The fix defers the resize call and correctly destroys the old canvas, allowing it to be recreated with the proper dimensions.
- **fix(loading):** Corrects a race condition in the drag-and-drop file loading pipeline (`processFilePipeline`). The speed graph sketch will now reliably initialize on the first load, as the code now uses `Promise.all` to ensure both the JSON data is parsed and the video's metadata (duration) is available before attempting to render the visualization.
This commit introduces a major improvement to the file loading pipeline, resolving a critical race condition that occurred during fresh loads and drag-and-drop actions. Previously, the application would attempt to initialize data-dependent components (like the speed graph) and manage the loading modal simultaneously, leading to timing issues.
The core of this fix is a new, robust processFilePipeline function in main.js that implements a two-stage video loading process. This decouples data initialization from UI updates, ensuring each occurs at the correct point in the browser's file loading lifecycle.
Key Changes & Bug Fixes:
main.js: Refactored processFilePipeline
Two-Stage Video Loading: The video loading process now uses two distinct event listeners:
loadedmetadata: Fires as soon as the video's duration is known. This event now immediately triggers finalizeSetup(), ensuring that the speedGraphSketch is created with the correct time axis, fixing the blank graph bug.
canplaythrough: Fires only after the video has buffered enough for smooth playback. The resolution of the main videoReadyPromise is tied to this event, guaranteeing the loading modal is hidden at the appropriate time and resolving the "stuck modal" bug.
Explicit Data Synchronization: A final, crucial fix was added to finalizeSetup() to re-synchronize all radar frame timestamps against the video's confirmed start time. This eliminates data mismatches that previously caused NaN errors on fresh loads.
speedGraphSketch.js: Enhanced Robustness
The sketch's draw() and drawTimeIndicator() functions have been made more defensive. They now check that both videoDuration and appState.currentFrame are valid before attempting to render, preventing crashes and NaN errors if the sketch is asked to draw before all data is ready.
modal.js: Improved Loading Modal
The modal logic was updated to support a dedicated loading state with a progress bar, providing better user feedback during the file parsing and video buffering stages.
The zoom sketch canvas would turn blank after the browser window was resized.
The root cause was a race condition between the JavaScript `windowResized` event and the browser's layout rendering. The resize event was triggering the `zoomSketch` to resize its own canvas before its parent container (`#zoom-panel`) had been assigned its new, non-zero dimensions by the layout engine. This resulted in the zoom canvas being recreated with a size of 0x0 pixels.
This commit resolves the issue by:
1. In `radarSketch.js`, deferring the resize call for the zoom sketch using `setTimeout`. This pushes the execution to the end of the event loop, giving the browser time to update the container's dimensions first.
2. In `zoomSketch.js`, modifying the `handleResize` function to destroy the old, invalid canvas. The canvas is now correctly recreated with the proper dimensions on the next `updateAndDraw` call (triggered by mouse movement), making the solution robust and independent of specific timings.
Adds a new zoom panel that provides a magnified, real-time view of the area under the cursor when "Close-Up Mode" is active. This feature enhances the tool's precision for detailed data analysis.
Key features and fixes include:
- Renders a high-fidelity, vector-based redraw of the scene, not a pixelated image.
- Implemented dynamic zoom control via the mouse wheel when hovering over the main radar canvas.
- The zoom sketch is fully decoupled from the main radar sketch to ensure stability and prevent UI freezes.
- Includes a self-contained tooltip within the zoom window that correctly scales its size and text to match the zoom level.
- The tooltip's position is now smart, dynamically moving to the least cluttered quadrant to avoid obstructing data points.
- Connector lines and item highlighting are now fully functional and styled to match the main view's tooltip.
Motion state added in the persistent overlays