--- name: Gebogen lijnen overview: Lijnen en pijlen krijgen buigpunten waardoor een vloeiende kromme door alle punten loopt. Bij een geselecteerde lijn staat tussen elk paar punten een spook-greep; slepen daarvan maakt een nieuw buigpunt, dubbelklikken op een buigpunt verwijdert het. todos: - id: model content: "LineAnnotation: Bends-lijst, Catmull-Rom-naar-Bezier helper, Render/Bounds/HitTest/Move/Clone aanpassen, pijlpunt langs raaklijn" status: completed - id: handles content: "Grepen: buigpunten + spook-grepen, BeginHandleDrag voegt buigpunt in, RemoveHandle; IsGhostHandle/RemoveHandle in Annotation" status: completed - id: surface content: "AnnotationSurface: spook-grepen anders tekenen, echte grepen voorrang bij HitHandle" status: completed - id: editor content: "EditorWindow: dubbelklik op buigpunt verwijdert het (met undo), hint-tekst bijwerken" status: completed isProject: false --- # Gebogen lijnen en pijlen ## Gedrag - Selecteer een lijn of pijl: je ziet de begin- en eindgreep, de buigpunten en, halverwege elk stuk van de kromme, een kleine halfdoorzichtige spook-greep. - Sleep je een spook-greep, dan wordt die een echt buigpunt en volgt de lijn de muis (zoals in je screenshot). - Dubbelklik op een buigpunt verwijdert het. Beide acties kun je ongedaan maken. - De kromme loopt precies door alle punten (Catmull-Rom, omgezet naar kubische Beziers). De pijlpunt volgt de richting van het laatste stuk. ## Wijzigingen **[src/Kniip/Editor/Annotations/LineAnnotation.cs](src/Kniip/Editor/Annotations/LineAnnotation.cs)** - Nieuw: `List Bends`, met `Start + Bends + End` als doorlooppunten. - Een helper bouwt de Bezier-segmenten. Voor `Bounds`, `HitTest` en de posities van de spook-grepen gebruikt hij bemonsterde punten (ongeveer 16 per segment). Zonder buigpunten blijft alles gelijk aan nu. - `Render`: een `StreamGeometry` met `BezierTo`. Bij een pijl wordt de richting bepaald door `End` min het laatste controlepunt. Het laatste segment eindigt op het basispunt van de pijlpunt. - Grepen: index 0 is `Start` en 1 is `End`, zodat bestaande code blijft werken. Daarna volgen de buigpunten en dan de spook-grepen (het Bezier-punt bij t=0,5 van elk segment). - `BeginHandleDrag`: bij een spook-greep wordt een buigpunt op de juiste plek in `Bends` ingevoegd en het actieve buigpunt onthouden. `MoveHandle` verplaatst daarna dat punt. - Met Shift blijft `SnapAngle` werken voor begin en eind, maar dan ten opzichte van het naastliggende punt. - `Move` verschuift ook alle buigpunten. `Clone` maakt een diepe kopie van `Bends`, nodig voor ongedaan maken (zelfde patroon als in `HighlightAnnotation`). **[src/Kniip/Editor/Annotations/Annotation.cs](src/Kniip/Editor/Annotations/Annotation.cs)** - `public virtual bool IsGhostHandle(int index) => false;` - `public virtual bool RemoveHandle(int index) => false;` (LineAnnotation verwijdert hiermee een buigpunt) **[src/Kniip/Editor/AnnotationSurface.cs](src/Kniip/Editor/AnnotationSurface.cs)** - `DrawSelection` tekent spook-grepen als kleinere, halfdoorzichtige cirkels. `HitHandle` controleert eerst de echte grepen en daarna pas de spook-grepen, zodat een echte greep voorrang krijgt als ze overlappen. **[src/Kniip/Editor/EditorWindow.xaml.cs](src/Kniip/Editor/EditorWindow.xaml.cs)** (rond regel 452) - In `Surface_MouseLeftButtonDown`: als op een greep geklikt wordt met `e.ClickCount == 2` en `_selected.RemoveHandle(handle)` slaagt, dan volgen `Commit(_pending)` en `InvalidateVisual`, en stopt de verwerking daar. Anders start het bestaande sleepgedrag. - Optioneel: in `UpdateHint` een korte tip toevoegen voor lijnen ("Sleep het middenpunt om te buigen, dubbelklik om een punt te verwijderen"). ## Niet nodig Exporteren gaat via `Render` in [src/Kniip/Editor/DocumentRenderer.cs](src/Kniip/Editor/DocumentRenderer.cs) en werkt dus automatisch. Ook het aanmaken van lijnen (`UpdateCreating`) blijft ongewijzigd: nieuwe lijnen zijn recht.