51 lines
3.9 KiB
Markdown
51 lines
3.9 KiB
Markdown
---
|
|
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<Point> 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. |