feat: Slide-Modus als alternative Wort-Positionierung im Overlay
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 34s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 23s
CI / test-nodejs-website (push) Successful in 24s
Some checks failed
CI / go-lint (push) Has been skipped
CI / python-lint (push) Has been skipped
CI / nodejs-lint (push) Has been skipped
CI / test-go-school (push) Successful in 34s
CI / test-go-edu-search (push) Successful in 33s
CI / test-python-klausur (push) Failing after 2m9s
CI / test-python-agent-core (push) Successful in 23s
CI / test-nodejs-website (push) Successful in 24s
Neuer Hook useSlideWordPositions: Schiebt alle erkannten Woerter von links nach rechts ueber die Pixel-Projektion bis jedes Wort auf seiner Tinte einrastet. Kein Wort geht verloren, keine Cluster-Matching-Regeln noetig. Toggle-Button (Slide/Cluster) in der Overlay-Toolbar zum Umschalten. Bestehender Cluster-Algorithmus bleibt als Alternative erhalten. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -3,6 +3,7 @@
|
||||
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'
|
||||
import type { GridResult, GridCell, RowResult, RowItem } from '@/app/(admin)/ai/ocr-overlay/types'
|
||||
import { usePixelWordPositions } from './usePixelWordPositions'
|
||||
import { useSlideWordPositions } from './useSlideWordPositions'
|
||||
|
||||
const KLAUSUR_API = '/klausur-api'
|
||||
|
||||
@@ -42,19 +43,27 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
|
||||
const [imageRotation, setImageRotation] = useState<0 | 180>(0)
|
||||
const [textOpacity, setTextOpacity] = useState(100)
|
||||
const [textColor, setTextColor] = useState<'red' | 'blue' | 'black'>('red')
|
||||
const [positioningMode, setPositioningMode] = useState<'cluster' | 'slide'>('slide')
|
||||
const reconRef = useRef<HTMLDivElement>(null)
|
||||
const [reconWidth, setReconWidth] = useState(0)
|
||||
|
||||
// Pixel-based word positions
|
||||
// Pixel-based word positions (both algorithms run, toggle selects which to use)
|
||||
const overlayImageUrl = sessionId
|
||||
? `${KLAUSUR_API}/api/v1/ocr-pipeline/sessions/${sessionId}/image/cropped`
|
||||
: ''
|
||||
const cellWordPositions = usePixelWordPositions(
|
||||
const clusterPositions = usePixelWordPositions(
|
||||
overlayImageUrl,
|
||||
gridCells,
|
||||
status === 'ready',
|
||||
imageRotation,
|
||||
)
|
||||
const slidePositions = useSlideWordPositions(
|
||||
overlayImageUrl,
|
||||
gridCells,
|
||||
status === 'ready',
|
||||
imageRotation,
|
||||
)
|
||||
const cellWordPositions = positioningMode === 'slide' ? slidePositions : clusterPositions
|
||||
|
||||
// Track container width
|
||||
useEffect(() => {
|
||||
@@ -395,6 +404,23 @@ export function OverlayReconstruction({ sessionId, onNext }: OverlayReconstructi
|
||||
|
||||
<div className="w-px h-5 bg-gray-300 dark:bg-gray-600 mx-1" />
|
||||
|
||||
{/* Positioning mode toggle */}
|
||||
<button
|
||||
onClick={() => setPositioningMode(m => m === 'slide' ? 'cluster' : 'slide')}
|
||||
className={`px-2 py-1 text-xs rounded border transition-colors ${
|
||||
positioningMode === 'slide'
|
||||
? 'bg-orange-500 text-white border-orange-500'
|
||||
: 'bg-white dark:bg-gray-700 text-gray-600 dark:text-gray-400 border-gray-300 dark:border-gray-600'
|
||||
}`}
|
||||
title={positioningMode === 'slide'
|
||||
? 'Slide-Modus: Woerter von links nach rechts schieben (klick fuer Cluster-Modus)'
|
||||
: 'Cluster-Modus: Woerter an Pixel-Cluster zuordnen (klick fuer Slide-Modus)'}
|
||||
>
|
||||
{positioningMode === 'slide' ? 'Slide' : 'Cluster'}
|
||||
</button>
|
||||
|
||||
<div className="w-px h-5 bg-gray-300 dark:bg-gray-600 mx-1" />
|
||||
|
||||
{/* Text color */}
|
||||
{(['red', 'blue', 'black'] as const).map(c => (
|
||||
<button
|
||||
|
||||
Reference in New Issue
Block a user