Annotations¶
How an analyst adds a line, area, circle, ellipse, label, marker or note to a plot, changes how it looks and when it is shown, deletes it, and finds notes by time. Part A: everything through forms. Drawing on the map comes later.
Requirements cited¶
| SRD | Requirement |
|---|---|
| CAP-03 | Annotations (shapes, labels, chart furniture) are ordinary GeoJSON features, with provenance, export and tool support. |
| CAP-04 | An annotation with only a time has no geometry. |
| CAP-05 | A temporal view shows narrative entries and time-only annotations. |
| SUB-19, SUB-21 | Every change is a recorded step; undo is replay to a point. |
| SUB-22 | Content, how features are styled included, is recorded and undoable. |
| SUB-04 | Positions, ranges, bearings and times are read and shown in the analyst's notation and units. |
| CAP-28 | An annotation with a time or a period is drawn only while it falls in the time window. |
| EXT-14, EXT-15 | Legacy plots' annotations come in as far as the data model allows; what doesn't is listed. |
Model¶
-
Seven kinds, one form. Add annotation… (the + on the Outline view's title bar, or on the Timeline's; Add annotation… under the outline in the playground) opens the annotation form beside the map. Its Kind is one of:
Kind Is Positions Line a line through two or more positions, drawn along geodesics one per line Area a closed area with three or more corners one per line Circle every position at one range from a centre the centre, and a radius with its unit Ellipse an ellipse about a centre the centre; semi-major and semi-minor axes with their unit; the longer axis's orientation in degrees true Label text at a position one Marker a marked position one Note text at a time, with no position none: it needs a time A new annotation starts as a circle in the middle of the map, with nothing else filled in. The word shape is not used in the interface: shapes are kinds of annotation (style guide, language).
-
Positions in the analyst's notation. A position may be typed as Debrief writes it (
50°20.120'N 004°07.210'W), in degrees, minutes and seconds, in decimal degrees, without the symbols (50 20.12 N 4 7.21 W), with the hemisphere first (N50 20.12 W4 7.21), or as two signed decimals, latitude first (50.335, -4.120). Under each, the form says what it understood (Means 50°20.120'N 004°07.210'W) or what is wrong with it. The same reading runs in Python and TypeScript, held to shared test vectors (schemas/vectors/positions.json), and agents may send positions as text too. -
Sizes in their units. A radius or semi-axes is a number and a unit: nautical miles, yards, metres or kilometres. The unit is kept with the value (SUB-02), so a circle of 2 nmi stays 2 nmi when the analyst's display unit is yards. A radius or semi-axis is at most 10,000 km: beyond about half the world, a circle drawn along geodesics folds back on itself. Orientation is degrees true, clockwise from north; 405 is read as 045.
-
Time. No time (always shown), At a time or Over a period. Times are typed as for a tool's time fields (
09:30Z,15 Jun 2023 09:30:00Z,150930Z JUN 23), with what was understood said beneath; a new annotation's time starts at current time. With a time or a period, it is drawn only while that falls in the time window (CAP-28). A note always has a time. -
Style. Colour (the annotation amber, a track colour by name, or any colour as
#rrggbb, its swatch beside the list); line solid, dashed or dotted, and its width in pixels; for areas, circles and ellipses a fill colour and how opaque it is; the label's size in pixels and where it goes (above, below, left, right, centre, or not shown). An area's, a circle's or an ellipse's label is hidden while the shape is too small on screen to carry it: under 70 pixels across where Debrief placed the label, or under 24 where the analyst (or a legacy plot) chose its place. Anything left at its default is drawn as Debrief draws annotations: amber, dashed, an area faintly tinted, so nothing a tool draws is mistaken for a track. An annotation drawn solid still has no direction ticks or end dots, and is still labelled. Style is content: changing it is a step (decision, 12 Oct 2026). -
Checked as typed, saved as one step. Each field says what is wrong beside it once the analyst has tried to save; nothing is sent until every field is right. Add (or Save changes) sends the description to the tool service, which checks it again, makes the annotation and records it as one step, named in the History view: Circle 'Exclusion zone' added, Style of Circle 'Exclusion zone' changed, Time of …, … renamed …, Circle 'Exclusion zone' changed (anything else, or several at once). Saving changes that change nothing records nothing: a field left as it was shown keeps its exact value, even where the form shows it rounded (a position to a thousandth of a minute, a time to the second). A field emptied is cleared: text, time and style go back to none.
Ctrl+Zundoes it like any step. -
Changing one. Its properties form opens from the outline's context menu (Change annotation…), from Change… in the playground, or by double-clicking it on the map. It shows everything the annotation is, in the same fields; its kind stays as it is. A change made elsewhere since the plot was opened is never overwritten: Debrief shows the latest and says nothing was changed (SUB-28).
-
Deleting. Delete on its form, Delete annotation on the outline's context menu (several at once, as one step), or Delete in the playground. Named sets keep their other members; a set left empty goes too. Undo brings everything back.
-
Chart furniture. The scale bar is always drawn, in the analyst's distance unit. The north arrow is chart furniture the plot carries: North arrow on the Outline view's ... menu (checked when shown), or the North arrow button in the playground, adds or removes it as a step. The map is Web Mercator, north up everywhere, so the arrow points up. Grids, legends and other furniture are not done.
-
The Timeline (CAP-05). A view below the outline lists the plot's time-only annotations, such as narrative notes and periods of interest, in time order: each entry its time (or period), name and first line of text. The entry current time is at, the last to start at or before it, is marked; in VS Code the view keeps it in sight as current time moves, so a narrative can be read along with a replay. Choosing an entry (click, or Enter) moves current time to it, or to its start. If that is outside the window shown, the window widens or moves to take it in, shown but never saved, exactly as for a tool's time, with Keep and Revert on the time controller (CAP-28). It is a native tree in VS Code, read by screen readers and used from the keyboard like any view; in the playground, a list of buttons, the current one marked for screen readers as well as by sight.
-
What is a step, and what isn't.
Step in the history Undone by Ctrl+ZAdding, changing, restyling, deleting an annotation Yes, one each Yes Showing or removing the north arrow Yes Yes Hiding an annotation on the map Yes (as for any feature) Yes Choosing a Timeline entry (current time), opening a form No No -
For agents. The same steps through the tool service:
debrief/add_annotation(annotation: the description the form sends, positions as numbers or text),debrief/edit_annotation(feature, andannotationwith only what changes, so{"appearance": {...}}restyles; a member given asnullis cleared, and a time given replaces a period, or a period a time; the north arrow has nothing to change),debrief/delete_annotations(features) anddebrief/set_north_arrow(shown), each withbaseas for any change. In VS Code the commandsdebrief.addAnnotation,debrief.editAnnotation,debrief.deleteAnnotation,debrief.toggleNorthArrowanddebrief.goToTimetake the same arguments instead of opening the form.
sequenceDiagram
actor Analyst
participant Form as Annotation form
participant Host as Extension host
participant Service as Tool service
participant Plot as Plot file
Analyst->>Form: kind, name, centre, radius, style, time
Form->>Form: read positions and times; say what they mean or what is wrong
Analyst->>Form: Add
Form->>Host: save_annotation (the description)
Host->>Service: debrief/add_annotation (description, base)
alt changed elsewhere since base
Service-->>Host: CONFLICT
Host->>Analyst: nothing was changed; showing the latest
else
Service->>Service: check it; make the feature (a circle: its polygon along geodesics)
Service->>Plot: one step: "Circle 'Exclusion zone' added"
Service-->>Host: new base, the feature's id
Host->>Host: reload: map, outline, Timeline, History
end
How circles and ellipses are kept¶
GeoJSON has no curves. A circle or an ellipse is kept as a polygon of 72 sides approximating it, built along geodesics, as its geometry, so that any other GeoJSON tool draws the area it covers and a plot's extent includes it, plus its own properties: shape (circle or ellipse), centre, and radius, or semi_major, semi_minor and orientation, each with its unit. Debrief draws and edits it from those, along geodesics and smooth at any zoom, never from the polygon; every change makes the polygon again, and a rule checked on reading refuses a polygon that no longer matches its centre and size. A point with a radius would have been smaller, but other tools would see only a point, and a plot's extent would leave the circle out.
Reference implementation¶
- Schema (0.0.12):
AnnotationProperties(shape,centre,radius,semi_major,semi_minor,orientation,furniture,appearance),AnnotationAppearanceandAnnotationSpecinschemas/linkml/features.yaml; the rules indebrief_schemas.documents(_annotation_problems); fixturesplot/valid/annotations-every-shape.jsonand thecircle-*,ellipse-*,line-*,chart-furniture-*andannotation-*invalid ones. - Kernel:
debrief_kernel.geodesy.circle_ringandellipse_ring;debrief_kernel.formatting.parse_positionand its TypeScript twinparsePosition(ts/kernel/src/positions.ts). - Making and naming changes:
debrief_stac.annotations(build,spec_of,describe_change);Catalogue.add_annotation,edit_annotation,delete_annotations,set_north_arrow; the service methods indebrief_tools.service. - VS Code: the form
vscode/webview/annotationform.tsx, its reading of fieldsvscode/webview/annotationdraft.ts; the panelvscode/src/panels/annotation.ts; drawingvscode/webview/annotationlook.tsanddrawAnnotationinvscode/webview/map.ts; the Timelinevscode/src/timeline.tsandvscode/src/views/timeline.ts; commands invscode/src/extension.ts. - The playground:
vscode/play/host.ts(the annotation form frame, the Timeline, the buttons) andannotateinvscode/play/play.py. - Legacy plots:
debrief_io.dpf(_read_look) anddebrief_io.dpf_import(_curve,_appearance,_look_notes). - Tests:
python/debrief-stac/tests/test_annotations.py, the service test,vscode/test/unit/annotations.test.ts, the playground test'svscode/test/play/annotations.mjs, and the integration test's annotation steps.
Not yet: drawing and editing annotations on the map with the pointer (part B); arrowheads; label symbols; grids and other chart furniture; changing an annotation's kind.