feat: add debug bounding boxes to magnifier view

Add the same debug bounding box visualization (color-coded rectangles and
importance score labels) to the magnifier view that was previously added to
the main map.

Key features:
- SVG rectangles show bounding boxes for all detected regions
- HTML overlay labels show region IDs and importance scores
- Color-coded by importance (green=accepted, orange=high, yellow=medium, gray=low)
- Only shows labels for regions within magnified viewport
- Properly converts SVG coordinates to magnifier pixel coordinates
- Behind SHOW_DEBUG_BOUNDING_BOXES dev flag

This helps debug the adaptive zoom search algorithm by showing which regions
are being considered and their importance rankings inside the magnifier.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Thomas Hallock 2025-11-24 19:05:58 -06:00
parent a5cbceaeb1
commit 9c7d2fab5f
1 changed files with 121 additions and 0 deletions

View File

@ -1942,8 +1942,129 @@ export function MapRenderer({
</g>
)
})()}
{/* Debug: Bounding boxes for detected regions in magnifier */}
{SHOW_DEBUG_BOUNDING_BOXES &&
debugBoundingBoxes.map((bbox) => {
const importance = bbox.importance ?? 0
// Color-code by importance
let strokeColor = '#888888' // Gray for low importance
if (bbox.wasAccepted) {
strokeColor = '#00ff00' // Green for accepted region
} else if (importance > 1.5) {
strokeColor = '#ff6600' // Orange for high importance
} else if (importance > 0.5) {
strokeColor = '#ffcc00' // Yellow for medium importance
}
return (
<rect
key={`mag-bbox-${bbox.regionId}`}
x={bbox.x}
y={bbox.y}
width={bbox.width}
height={bbox.height}
fill="none"
stroke={strokeColor}
strokeWidth={1}
vectorEffect="non-scaling-stroke"
pointerEvents="none"
/>
)
})}
</animated.svg>
{/* Debug: Bounding box labels in magnifier as HTML overlays */}
{SHOW_DEBUG_BOUNDING_BOXES &&
containerRef.current &&
svgRef.current &&
debugBoundingBoxes.map((bbox) => {
const importance = bbox.importance ?? 0
let strokeColor = '#888888'
if (bbox.wasAccepted) {
strokeColor = '#00ff00'
} else if (importance > 1.5) {
strokeColor = '#ff6600'
} else if (importance > 0.5) {
strokeColor = '#ffcc00'
}
// Get magnifier dimensions
const containerRect = containerRef.current!.getBoundingClientRect()
const magnifierWidth = containerRect.width * 0.5
const magnifierHeight = magnifierWidth / 2
// Parse viewBox
const viewBoxParts = mapData.viewBox.split(' ').map(Number)
const viewBoxX = viewBoxParts[0] || 0
const viewBoxY = viewBoxParts[1] || 0
const viewBoxWidth = viewBoxParts[2] || 1000
const viewBoxHeight = viewBoxParts[3] || 1000
// Get current zoom (use animated value)
const currentZoom = getCurrentZoom()
// Calculate magnified viewBox (same logic as the magnifier's viewBox calculation)
const svgRect = svgRef.current!.getBoundingClientRect()
const scaleX = viewBoxWidth / svgRect.width
const scaleY = viewBoxHeight / svgRect.height
const svgOffsetX = svgRect.left - containerRect.left
const svgOffsetY = svgRect.top - containerRect.top
if (!cursorPosition) return null
const cursorSvgX = (cursorPosition.x - svgOffsetX) * scaleX + viewBoxX
const cursorSvgY = (cursorPosition.y - svgOffsetY) * scaleY + viewBoxY
const magnifiedWidth = viewBoxWidth / currentZoom
const magnifiedHeight = viewBoxHeight / currentZoom
const magnifiedViewBoxX = cursorSvgX - magnifiedWidth / 2
const magnifiedViewBoxY = cursorSvgY - magnifiedHeight / 2
// Convert bbox center from SVG coords to magnifier pixel coords
const bboxCenterSvgX = bbox.x + bbox.width / 2
const bboxCenterSvgY = bbox.y + bbox.height / 2
// Calculate position within magnified viewBox
const relativeX = (bboxCenterSvgX - magnifiedViewBoxX) / magnifiedWidth
const relativeY = (bboxCenterSvgY - magnifiedViewBoxY) / magnifiedHeight
// Check if bbox is within magnified viewport
if (relativeX < 0 || relativeX > 1 || relativeY < 0 || relativeY > 1) {
return null // Don't show labels for regions outside magnifier viewport
}
// Convert to pixel position within magnifier
const labelX = relativeX * magnifierWidth
const labelY = relativeY * magnifierHeight
return (
<div
key={`mag-bbox-label-${bbox.regionId}`}
style={{
position: 'absolute',
left: `${labelX}px`,
top: `${labelY}px`,
transform: 'translate(-50%, -50%)',
pointerEvents: 'none',
zIndex: 15,
fontSize: '10px',
fontWeight: 'bold',
color: strokeColor,
textAlign: 'center',
textShadow: '0 0 2px black, 0 0 2px black, 0 0 2px black',
whiteSpace: 'nowrap',
}}
>
<div>{bbox.regionId}</div>
<div style={{ fontSize: '8px', fontWeight: 'normal' }}>{importance.toFixed(2)}</div>
</div>
)
})}
{/* Magnifier label */}
<animated.div
style={{