Browse Source

feat: Enhance radar overlay responsiveness and robustness

This commit introduces several improvements to the radar visualization, focusing on responsiveness, error handling, and clearer data representation.

**Key Changes:**

*   **Responsive Radar Overlay:** The persistent radar information overlay (`ift-dot-matrix` canvas) in `dom.js` is no longer a fixed size. It now dynamically adjusts its width to match the radar plot's size, ensuring a consistent visual experience across different screen resolutions and resize events. The internal drawing logic has been updated to dynamically calculate column counts based on the canvas's current dimensions.
*   **Improved Error Handling in Drawing Utilities:** Comprehensive `try...catch` blocks have been added to all major drawing functions within `drawUtils.js`. This significantly enhances the application's robustness by gracefully handling potential errors during rendering, preventing crashes and providing better debugging insights.
*   **TTC Category Fallback:** In `drawUtils.js`, the trajectory drawing logic for Time-to-Collision (TTC) now includes a fallback mechanism. If a track's `ttcCategory` is undefined or invalid, it will default to a neutral gray color, ensuring that trajectories are always rendered with a clear visual state.
refactor/sync-centralize
RUSHIL AMBARISH KADU 4 months ago
parent
commit
073f30c482
  1. 28
      steps/src/dom.js
  2. 46
      steps/src/drawUtils.js

28
steps/src/dom.js

@ -325,14 +325,14 @@ export function updatePersistentOverlays(currentMediaTime) {
radarInfoOverlay.innerHTML = `
<div id="radar-text-content" style="line-height: 1.5;">
Frame: <span id="ov-frame"></span>
| Motion State: <span id="ov-motion"></span>
| EGO State: <span id="ov-motion"></span>
| FPS: <b id="ov-fps"></b>
| Color Mode: <b id="ov-mode"></b>
| Color mode: <b id="ov-mode"></b>
| Drift: <b id="ov-drift"></b>
| Δt: <b id="ov-ift"></b>
<!-- | Scale: <b id="ov-scale"></b> -->
</div>
<canvas id="ift-dot-matrix" width="700" height="40" style="display:block; margin-top:5px; background:rgba(0,0,0,0.5); border:1px solid #555;"></canvas>
<canvas id="ift-dot-matrix" height="40" style="display:block; margin-top:5px; background:rgba(0,0,0,0.5); border:1px solid #555; width: 100%;"></canvas>
`;
overlayCache = {
@ -389,9 +389,19 @@ export function updatePersistentOverlays(currentMediaTime) {
// --- Draw Optimized Square Block Matrix Graph ---
// CONDITIONAL RENDER: Only redraw if frame changed or scale changed significantly
if (appState.currentFrame !== lastDrawnFrame || Math.abs(msPerBlock - lastDrawnScale) > 0.01) {
const dotCanvas = overlayCache.dotCanvas;
let isResized = false;
if (dotCanvas) {
const clientWidth = dotCanvas.clientWidth;
if (dotCanvas.width !== clientWidth) {
dotCanvas.width = clientWidth;
isResized = true;
}
}
if (appState.currentFrame !== lastDrawnFrame || Math.abs(msPerBlock - lastDrawnScale) > 0.01 || isResized) {
const dotCanvas = overlayCache.dotCanvas; // Use cached reference
if (dotCanvas) {
const ctx = dotCanvas.getContext("2d");
const w = dotCanvas.width;
@ -403,9 +413,9 @@ export function updatePersistentOverlays(currentMediaTime) {
const stride = blockSize + hGap;
// msPerBlock is already set above
// Calculate columns: 600px / 5px = 120 columns.
const totalCols = 140;
const centerCol = 70;
// Calculate columns dynamically based on width
const totalCols = Math.floor(w / stride);
const centerCol = Math.floor(totalCols / 2);
ctx.clearRect(0, 0, w, h);
@ -444,7 +454,7 @@ export function updatePersistentOverlays(currentMediaTime) {
}
}
// Draw Center Indicator (Triangle at column 60)
// Draw Center Indicator (Triangle at center column)
const centerX = centerCol * stride + 2;
ctx.fillStyle = "#FFFFFF";
ctx.beginPath();

46
steps/src/drawUtils.js

@ -79,6 +79,7 @@ export const movingColor = (p) => p.color(255, 0, 255); // Magenta
* @param {object} plotScales - The calculated scales for plotting.
*/
export function drawStaticRegionsToBuffer(p, b, plotScales) {
try {
b.clear();
// 1. Draw Axes (Grid)
@ -129,10 +130,14 @@ export function drawStaticRegionsToBuffer(p, b, plotScales) {
b.drawingContext.setLineDash([]);
b.pop();
} catch (error) {
console.error("Error in drawStaticRegionsToBuffer:", error);
}
}
export function drawAxes(p, plotScales) {
try {
p.push();
// Determine axis and text colors based on the current theme (dark/light mode).
const axisColor = document.documentElement.classList.contains("dark")
@ -209,10 +214,14 @@ export function drawAxes(p, plotScales) {
p.pop();
}
p.pop();
} catch (error) {
console.error("Error in drawAxes:", error);
}
}
export function drawPointCloud(p, points, plotScales) {
try {
// Set stroke weight for points.
p.strokeWeight(4);
// Get state of various toggles from the DOM.
@ -300,9 +309,13 @@ export function drawPointCloud(p, points, plotScales) {
p.point(pt.x * plotScales.plotScaleX, pt.y * plotScales.plotScaleY);
}
}
} catch (error) {
console.error("Error in drawPointCloud:", error);
}
}
export function drawTrajectories(p, plotScales) {
try {
const localTtcColors = ttcColors(p);
for (const track of appState.vizData.tracks) {
@ -376,10 +389,13 @@ export function drawTrajectories(p, plotScales) {
// MODE 2: DEFAULT TTC SCHEME (Use pre-calculated category from JSON)
// FIND the TTC category from the new timeline
let ttcCategory = null;
if (track.ttcCategoryTimeline) {
const ttcEntry = track.ttcCategoryTimeline.find(
(entry) => entry.frameIdx === lastLog.frameIdx
);
const ttcCategory = ttcEntry ? ttcEntry.ttcCategory : null; // Get the category if found
ttcCategory = ttcEntry ? ttcEntry.ttcCategory : null; // Get the category if found
}
switch (ttcCategory) {
case 3:
@ -426,9 +442,13 @@ export function drawTrajectories(p, plotScales) {
p.pop(); // This was the missing pop call for each trajectory loop
}
} catch (error) {
console.error("Error in drawTrajectories:", error);
}
}
export function drawTrackMarkers(p, plotScales) {
try {
const showDetails = toggleVelocity.checked;
const useStationary = toggleStationaryColor.checked;
const textColor = document.documentElement.classList.contains("dark")
@ -533,10 +553,14 @@ export function drawTrackMarkers(p, plotScales) {
}
p.pop();
}
} catch (error) {
console.error("Error in drawTrackMarkers:", error);
}
}
export function handleCloseUpDisplay(p, plotScales, mouseX, mouseY) {
try {
// --- Step 1: Gather Hovered Items ---
const frameData = appState.vizData.radarFrames[appState.currentFrame];
if (!frameData) return []; // Return empty array if no data
@ -819,6 +843,10 @@ export function handleCloseUpDisplay(p, plotScales, mouseX, mouseY) {
// Return the list of hovered items for other functions (like the zoom window) to use.
return hoveredItems;
} catch (error) {
console.error("Error in handleCloseUpDisplay:", error);
return [];
}
}
export function drawCovarianceEllipse(
@ -829,6 +857,7 @@ export function drawCovarianceEllipse(
plotScales,
isStationary
) {
try {
// Only draw the ellipse for tracks that are not stationary.
if (isStationary) return;
const [radiusA, radiusB] = radii;
@ -849,10 +878,14 @@ export function drawCovarianceEllipse(
radiusB * 2 * plotScales.plotScaleY // in p5 library expect
);
p.pop();
} catch (error) {
console.error("Error in drawCovarianceEllipse:", error);
}
}
export function drawEgoVehicle(p, plotScales) {
try {
const isDark = document.documentElement.classList.contains("dark");
const carColor = isDark ? p.color(150, 150, 220) : p.color(151, 151, 220);
@ -869,9 +902,13 @@ export function drawEgoVehicle(p, plotScales) {
p.rect(0, -10, carWidthPixels, carLengthPixels, 5);
p.pop();
} catch (error) {
console.error("Error in drawEgoVehicle:", error);
}
}
export function drawRegionsOfInterest(p, frameData, plotScales) {
try {
// --- THIS CHECK IS ESSENTIAL AND MUST NOT BE REMOVED ---
// It gracefully handles frames that do not have the barrier data.
if (!frameData || !frameData.filtered_barrier_x) {
@ -918,9 +955,13 @@ export function drawRegionsOfInterest(p, frameData, plotScales) {
);
p.pop();
} catch (error) {
console.error("Error in drawRegionsOfInterest:", error);
}
}
export function drawClusterCentroids(p, clustersInput, plotScales) {
try {
if (!clustersInput) {
return; // Do nothing if there's no cluster data
}
@ -977,4 +1018,7 @@ export function drawClusterCentroids(p, clustersInput, plotScales) {
p.pop();
}
}
} catch (error) {
console.error("Error in drawClusterCentroids:", error);
}
}
Loading…
Cancel
Save