From f468c3011236f4e147a5972af0864bc5c1a7a7e4 Mon Sep 17 00:00:00 2001 From: Benjamin Admin Date: Tue, 10 Mar 2026 22:52:08 +0100 Subject: [PATCH] fix: Zellen an Box-Zone clampen im Overlay-Modus (keine Ueberlappung) Zellen oberhalb der Box werden in der Hoehe begrenzt, Zellen unterhalb werden nach unten verschoben. Sub-Session-Zellen bleiben unveraendert. Co-Authored-By: Claude Opus 4.6 --- .../ocr-pipeline/StepReconstruction.tsx | 60 ++++++++++++++++--- 1 file changed, 51 insertions(+), 9 deletions(-) diff --git a/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx b/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx index b86286d..dd4f117 100644 --- a/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx +++ b/admin-lehrer/components/ocr-pipeline/StepReconstruction.tsx @@ -476,6 +476,47 @@ export function StepReconstruction({ sessionId, onNext }: StepReconstructionProp ) } + // Box zones in percent for clamping cell positions in overlay mode + const boxZonesPct = useMemo(() => + parentZones + .filter(z => z.zone_type === 'box' && z.box) + .map(z => { + const imgH = imageNaturalSize?.h || 1 + return { + topPct: (z.box!.y / imgH) * 100, + bottomPct: ((z.box!.y + z.box!.height) / imgH) * 100, + } + }), + [parentZones, imageNaturalSize] + ) + + // Clamp cell positions so they don't overlap with box zones + const adjustCellForBoxZones = ( + bboxPct: { x: number; y: number; w: number; h: number }, + cellId: string, + ): { x: number; y: number; w: number; h: number } => { + // Sub-session cells (inside box) → no adjustment + if (cellId.startsWith('sub_')) return bboxPct + if (boxZonesPct.length === 0) return bboxPct + + const cellTop = bboxPct.y + const cellBottom = bboxPct.y + bboxPct.h + const cellCenter = cellTop + bboxPct.h / 2 + + for (const { topPct, bottomPct } of boxZonesPct) { + // Cell ABOVE box: clamp height so bottom doesn't exceed box top + if (cellCenter < topPct && cellBottom > topPct) { + return { ...bboxPct, h: topPct - cellTop } + } + // Cell BELOW box: push top down to box bottom + if (cellCenter > bottomPct && cellTop < bottomPct) { + const newY = bottomPct + return { ...bboxPct, y: newY, h: cellBottom - newY } + } + } + return bboxPct + } + // Overlay rendering helper const renderOverlayMode = () => { const imgW = imageNaturalSize?.w || 1 @@ -562,7 +603,8 @@ export function StepReconstruction({ sessionId, onNext }: StepReconstructionProp const displayText = getDisplayText(cell) const edited = isEdited(cell) const wordPos = cellWordPositions.get(cell.cellId) - const cellHeightPx = containerH * (cell.bboxPct.h / 100) + const adjBbox = adjustCellForBoxZones(cell.bboxPct, cell.cellId) + const cellHeightPx = containerH * (adjBbox.h / 100) // Pixel-analysed: render word-groups at detected positions as inputs if (wordPos && wordPos.length > 0) { @@ -579,9 +621,9 @@ export function StepReconstruction({ sessionId, onNext }: StepReconstructionProp className="absolute leading-none pointer-events-none select-none" style={{ left: `${wp.xPct}%`, - top: `${cell.bboxPct.y}%`, + top: `${adjBbox.y}%`, width: `${wp.wPct}%`, - height: `${cell.bboxPct.h}%`, + height: `${adjBbox.h}%`, fontSize: `${fs}px`, fontWeight: globalBold ? 'bold' : (cell.colType === 'column_en' ? 'bold' : 'normal'), fontFamily: "'Liberation Sans', Arial, sans-serif", @@ -601,9 +643,9 @@ export function StepReconstruction({ sessionId, onNext }: StepReconstructionProp return (