Track operations¶
How an analyst moves a track, or a period of it, rotates it about a point, shears or stretches it from one end, splits it at a time and merges tracks into one; and how they clean it: removing jumps, smoothing it, and giving single fixes a colour, a label or a comment of their own. Part A: moving, rotating, splitting and merging (decision, product owner, 13 Oct 2026). Part B1: shearing and stretching, shear first as the operation analysts use most with TMA legs (decision, product owner, 13 Oct 2026; see Shearing and stretching). Cleaning tracks (part B2, 14 Oct 2026): jump removal, smoothing and marked fixes. Still to come: dragging single fixes, and the legacy OTG and DR import modes.
Requirements cited¶
| SRD | Requirement |
|---|---|
| CAP-01 | Dragging, splitting, merging, jump removal and smoothing of tracks. |
| CAP-02 | Track edits are destructive in the working plot, each recorded as a delta. |
| CAP-21 | The TMA module's manual dragging of a solution: translate, rotate, stretch, shear. |
| SUB-19, SUB-21 | Every change is a recorded step; undo is replay to a point, never an inverse operation. |
| SUB-24 | Provenance records who made each change, and what they asked for. |
| SUB-03, SUB-04 | Measured along geodesics; read and shown in the analyst's units and notation. |
| SUB-26, SUB-28 | Moving a track changes neither current time, the window nor the selection; a change made elsewhere is never overwritten. |
| NFR-13 | Dragging a track has a keyboard and a form-based equivalent. |
| PRN-08 | The analyst owns the data: a track is moved where the analyst says, without second-guessing; nothing is removed or moved without the analyst seeing it first. |
| EXT-14, EXT-15 | A legacy plot's per-fix colours, labels and comments are imported, not listed as left out. |
Model¶
-
What moves: the whole track, or a period of it. Legacy Debrief dragged a whole track, or a selected time period of it, to line it up with a reference: that is kept (decision, 13 Oct 2026). On the map, a small control below the drawing toolbar, What changes, says which (for moving, rotating, shearing and stretching alike): Whole track (the default) or Time window, the fixes in the time window shown. The forms offer the same choice. An agent may give any period. Fixes whose times fall in the period, ends included, move; the rest stay where they are.
-
The joins jump. Moving a period moves only its fixes, so the track jumps where they meet the rest: the track is not stretched or smoothed to keep it continuous. The map shows the jump while the analyst drags, and says so: only the fixes in the time window move, so the track jumps where they meet the rest. Jump removal (part B) will tidy a join an analyst does not want.
-
Moving is geodesic. A move takes every fix the same range along the same true bearing, each along its own geodesic, as legacy Debrief offset each fix: not a change of latitude and longitude, as an annotation's whole-shape move is. Courses and speeds over ground are kept as they were. On a curved earth no move of every fix by the same range and bearing keeps a track's shape exactly: as meridians converge, a track far north moved north is squeezed east-west a little, and one moved east turns a little. For the moves an analyst makes the difference is small (a track at 60°N moved 5 nmi north is 0.25% shorter; at 70°N moved 20 nmi, 1.6% shorter; a track steering 000 at 70°N moved 20 nmi east then steers 000.9), so the recorded speeds and courses are kept rather than worked out again from the moved positions.
-
Rotating is geodesic. A rotation keeps each fix's range from the pivot and turns its bearing from the pivot by the angle; clockwise is positive. Courses over ground of the fixes turned turn with the track: by the angle, near the pivot; far from it, or far north, by a little more or less, as the meridians converge, so that each course is still the track's direction as drawn (turned about the North Pole, a ship steering 090 still steers 090). The pivot is, unless the analyst chooses, the fix nearest current time, when current time is within what moves; otherwise the first fix of what moves. On the map the pivot is a handle of its own: drag it (or move it with the arrow keys) to turn about somewhere else. Moving the pivot records nothing; it says where the next rotation turns about.
-
Handles. A track selected on its own, and drawn on the map, shows three handles in the theme's focus colour, each named for a screen reader:
Handle Looks like Does Move a filled square on a fix in the middle of what moves drag it, and the track follows it Rotate a ring beyond the fix farthest from the pivot, on a dashed arm from it drag it round the pivot, and the track turns with it Pivot a dotted ring, by default on the fix nearest current time drag it to choose where the track turns about Ends a diamond beside the first fix and one beside the last fix of what moves (a double edge when Stretch is chosen) drag one to shear the track, or stretch it, holding the other end (below) Dragging the move or rotate handle draws the track moved or turned as the pointer goes, the track as it was dashed beneath it, and the note at the top of the map says by how much: BLUE ONE: moving 1.20 nmi 045.0°T, BLUE ONE: rotating 12.0° clockwise about 50°20.120'N 004°07.210'W. Letting go saves it as one step.
Escapebefore letting go puts it back, and nothing is recorded. What is saved is what the note said: the distance in the analyst's length unit and the bearing or angle, each to the decimals shown. -
Steps, named for what was done. Each operation is one step in the History view, its first note naming it and later notes saying the rest:
Operation Named Further notes Move the whole track BLUE ONE moved 1.20 nmi 045.0°T Move a period BLUE ONE part moved 1.20 nmi 045.0°T Only the fixes from 09:30:00Z to 10:15:00Z Rotate BLUE ONE rotated 12.0° clockwise (or part rotated) About 50°20.120'N 004°07.210'W, and the period Split BLUE ONE split at 09:30:00Z Into BLUE ONE (1) and BLUE ONE (2) Merge BLUE ONE and BLUE TWO merged (or 3 tracks merged) Into BLUE ONE, and any series not kept Shear BLUE ONE sheared: 087.2°T 12.4 kn (or part sheared) Held at the start, 09:30:00Z, Was 090.0°T 10.0 kn, and the period Stretch BLUE ONE stretched: 12.4 kn (or part stretched) Held at the end, 10:15:00Z, Was 10.0 kn, and the period Each step's provenance record holds who made it, the track or tracks it chose (
selected), and what was asked (parameters): the distance and bearing, or the angle and the pivot's latitude and longitude, the period's start and end, the time of a split and the names of its parts, or the merged track's name (SUB-24). Undo is replay to the step before, as for any step (SUB-21). -
Splitting at a time. Split track at current time… splits the selected track at current time into two: the fixes before it, and the fixes from it on (a fix exactly at the time starts the second part). The parts are offered as BLUE ONE (1) and BLUE ONE (2), which the analyst may change. Each keeps the track's colour, platform class, hiding and provenance. The first keeps the track's identity, so a named set or a tool result that refers to the track still does; the second is a new track, listed straight after it, and named sets that held the track hold both. Sensor observations that start at or after the time go with the second part. Observations that run across the time are not cut in two: they stay with the first part, and the step's notes say so (2087 bearings runs past the split and stays with BLUE ONE (1)), since those after the time now have a host track that has ended. Each part needs at least two fixes, or nothing is split and the message says how many each side has. Both parts are selected afterwards.
-
Merging. Merge selected tracks joins two or more selected tracks into one, in time order, whatever order they were selected in. The merged track keeps the earliest's identity, colour and platform class, and is named as the analyst says: offered the earliest's name, or, for the parts of one split track (BLUE ONE (1) and BLUE ONE (2)), the track's own (BLUE ONE); the others go, and sensor observations and named sets that referred to them refer to it. Tracks that overlap in time are not merged, and the message says where: The tracks were not merged: they overlap in time (BLUE ONE and RED ONE from 09:00:00Z to 09:40:00Z). Split or move one so they no longer overlap, then merge them. (Choosing which track wins where they overlap was considered and left out, to keep merging predictable.) Tracks that only meet, one ending as the next starts, merge. Speeds, courses or depths are kept only if every track has them. Before merging tracks where some have none, Debrief asks (Merging BLUE ONE, BLUE TWO keeps only what every track has. Courses not kept: BLUE TWO had none. Undo puts them back., with Merge anyway); the step's notes say which were not kept, and why, and the tool service returns the same in
notes. The merged track is selected afterwards. -
What is a step, and what isn't.
Step in the history Undone by Ctrl+ZLetting go of the move or rotate handle Yes, one Yes A run of arrow keys on the move or rotate handle Yes, one for the run Yes Letting go of an end, to shear or stretch Yes, one Yes A run of arrow keys on an end Yes, one for the run Yes Move…, Rotate…, Shear…, Stretch…, Split…, Merge Yes, one each Yes Dragging or nudging the pivot No No Choosing Whole track or Time window, or Shear or Stretch No No Escapeduring a drag; a move of nothingNo No -
The keyboard.
Tabto a handle. On the move handle the arrow keys move it 5 pixels, 25 withShift; on the rotate handleRightandUpturn it 1° clockwise,LeftandDown1° anticlockwise, 10° withShift; on the pivot the arrow keys move it 5 pixels (25 withShift). A run of presses on the move or rotate handle is saved as one step once they stop (under a second), onEnter, or when the keyboard moves on;Escapefirst puts it back. Presses made while that step is being saved are not lost: they are made as the next step. Whole track and Time window are buttons on the map, reached withTab, as are Shear and Stretch. The ends are described below. -
The forms. For an exact change, or without the map:
- Move track… (the outline's context menu on a track; Move… under Track, below the outline, in the playground): what moves (Whole track or Current time window, with how many fixes it holds), the distance (
1.2 nmi,2000 yd,3 km, or a number in the analyst's unit) and the bearing in degrees true (045). Each field says what it understood (Means 1.20 nmi) or what is wrong. - Rotate track…: what turns; the pivot (Fix nearest current time, First fix, Last fix, or in VS Code a position typed in any notation Debrief reads); and the angle (
12,12 clockwise,-12or12 anticlockwise). - Split track at current time…: the names of the two parts, offered as X (1) and X (2).
- Merge selected tracks: the merged track's name, offered as above; first, if speeds, courses or depths would not be kept, whether to merge anyway.
- Shear track… and Stretch track…: below.
- Move track… (the outline's context menu on a track; Move… under Track, below the outline, in the playground): what moves (Whole track or Current time window, with how many fixes it holds), the distance (
-
Shared state and conflicts. Moving, rotating, splitting and merging change neither current time nor the time window. The selection is kept, except that a split selects both parts and a merge the merged track. If the plot changes elsewhere during a drag (a colleague, an agent), the map shows the latest at once, drops the drag and says The plot was changed elsewhere, so your change was not made. Debrief is showing the latest; try again if you still want to. A change sent from a plot that has since moved on is refused the same way (SUB-28): track operations are never merged with a change made meanwhile. Context tracks follow the track: the whole moved track is drawn as context outside the window. A hidden track is not drawn, so it has no handles, but it can still be moved, rotated, split and merged from the outline.
-
For agents. The same steps through the tool service:
debrief/edit_track(feature,edit: aTrackEdit,{"action": "move", "distance": {"value": 1.2, "unit": "[nmi_i]"}, "bearing": {"value": 45, "unit": "deg"}}or{"action": "rotate", "angle": {"value": -10, "unit": "deg"}, "pivot": [-4.12, 50.33]}, with aperiodto move or turn only that; for a rotation with no pivot,current_timechooses the default),debrief/split_track(feature,at, andnamesif wanted) anddebrief/merge_tracks(features, andnameif wanted), each withbaseas for any change. Shears and stretches go throughdebrief/edit_tracktoo (below). In VS Code the commandsdebrief.moveTrack,debrief.rotateTrack,debrief.shearTrackanddebrief.stretchTracktake the track and the edit,debrief.splitTrackthe track and{at, names}, anddebrief.mergeTracksthe tracks' ids and{name}, instead of asking.
sequenceDiagram
actor Analyst
participant Map
participant Host as Extension host
participant Service as Tool service
participant Plot as Plot file
Analyst->>Map: select BLUE ONE
Map->>Map: move, rotate and pivot handles
Analyst->>Map: drag the move handle
Map->>Map: draw the track moved (geodesic), the old one dashed; "moving 1.20 nmi 045.0°T"
Analyst->>Map: let go
Map->>Host: edit_track (feature_id, track_edit: move, distance, bearing, period?)
Host->>Service: debrief/edit_track (edit, base)
alt changed elsewhere since base
Service-->>Host: CONFLICT
Host->>Map: show_plot (the latest); nothing was changed
else
Service->>Plot: one step: "BLUE ONE moved 1.20 nmi 045.0°T", with its parameters
Service-->>Host: new base
Host->>Map: show_plot (handles where the track now is)
end
sequenceDiagram
actor Analyst
participant Host as Extension host
participant Service as Tool service
Analyst->>Host: Split track at current time… (names offered)
Host->>Service: debrief/split_track (feature, at, names, base)
Service-->>Host: one step: "BLUE ONE split at 09:30:00Z"; the two parts
Host->>Host: reload; select both parts
Analyst->>Host: Merge selected tracks (name offered: BLUE ONE)
Host->>Service: debrief/merge_tracks (features, name, base)
alt the tracks overlap in time
Service-->>Host: refused, saying where they overlap; nothing changed
else
Service-->>Host: one step: "BLUE ONE (1) and BLUE ONE (2) merged"
end
Shearing and stretching¶
Part B1 (decision, product owner, 13 Oct 2026): shear is the operation analysts use most when working with TMA legs, so it comes first, with stretch beside it. A target's leg is a straight line run at a steady speed; the analyst keeps one end where the bearings put it and changes the course and speed of the rest. Both are legacy Debrief's TMA drags (CAP-21), here on any track.
-
One end is held. What changes is the whole track or only its fixes in the time window, chosen with the same Whole track and Time window control. One end of it, its first fix or its last, is held (the anchor) and does not move; the analyst drags the other end. Dragging the end at the start holds the end, and the other way round.
-
Shear: every fix moves in proportion to its time from the held end. Say the held fix is A, at time tA, and the dragged end E, at time tE, is dragged to E′. A fix at time t moves by the fraction f = (t − tA) / (tE − tA) of the end's move: not at all at the held end, the whole of it at the dragged end, half of it halfway in time. A straight leg at a steady speed stays a straight leg at a steady speed, with a new course and a new speed: they change together, as in legacy Debrief's TMA shear.
Dashed: the leg as it was. Solid: sheared. Each fix moves the part of E's move that its time is of the leg's.
-
Measured on the earth, from the held end. The move is taken in the frame centred on the held fix in which each position is placed by its range and true bearing from it (an azimuthal equidistant projection): there, a geodesic through the held fix is a straight line, and ranges from it are exact. So a straight leg through the held end (a geodesic, run at a steady speed) stays exactly straight after a shear, at any latitude and across the antimeridian. We considered moving each fix the fraction f of the end's range along the end's bearing, as a move does; but over a leg the meridians close in, the same bearing points slightly differently at each fix, and the sheared leg would bend (by tens of metres over a 10 nmi leg at 50° north). The tests check legs at 50°N, at 84°N and across the antimeridian.
-
Stretch: only the speed changes. With Stretch chosen, only how far the end is dragged along the line from the held end counts: the drag is taken onto that line. Every fix keeps its bearing from the held end and its range from it is multiplied by one factor, the new range of the dragged end over its old one. A straight leg stays on its line, at the new speed, on the same course; a track that turns keeps its shape, larger or smaller about the held end, and every speed changes by the same factor. A stretch never goes to nothing or past the held end: the slowest it offers is one step of speed (0.1 kn).
-
Recorded courses and speeds go with the fixes. Each fix's recorded course and speed are carried through the same change rather than worked out again from the new positions: Debrief follows the fix's recorded course and speed for ten seconds, changes that point as a fix at that time would be changed, and takes the new course and speed from the changed fix to it. So a shear adds the leg's change of velocity to each fix's own (a fix logged at 000 at 10 kn on a leg that gains 10 kn east is now 045 at 14.1 kn), and a stretch multiplies each speed by the factor and keeps each course. On a straight steady leg every fix's course and speed become exactly the leg's new ones; on a real track the detail recorded at each fix survives instead of being replaced by the jitter of the positions. A track that records courses but not speeds, or speeds but not courses, has the missing one taken from its positions for the purpose; what it does not record stays unrecorded.
-
Course and speed made good. What the map and the step say: the true bearing, at the first fix of what changes, of the geodesic from it to the last fix, and the range between them over the time between. For a straight steady leg these are its course and speed.
-
The ends on the map. A track selected on its own shows a diamond beside its first and last fixes of what changes, in the theme's focus colour, drawn to the left of the way the track goes so they are clear of the pivot (often on an end) and the rotate handle (beyond the far end, on the line of a straight leg). Beside What changes, so the control stays short on a short map, its Drag the ends says what dragging one does: Shear (the default) or Stretch, which gives the diamonds a double edge. Each is named for a screen reader: BLUE ONE: shear from the end, holding the start; drag it, or use the arrow keys; BLUE ONE: stretch from the start, holding the end; drag it along the track, or use Up and Down to change speed. We chose a switch on the map over a modifier key (
Shift-drag), which nobody can see and which is awkward from the keyboard, and over separate stretch handles, which would put four diamonds on a short leg; legacy Debrief, too, chose the drag first and then dragged. -
What the map says. Dragging an end draws the track changed as the pointer goes, the track as it was dashed beneath, and says BLUE ONE: shearing to 087.2°T 12.4 kn; end moved 1.20 nmi 045.0°T, or BLUE ONE: stretching to 12.4 kn (was 10.0 kn); with Time window, it adds that the track jumps where the window's fixes meet the rest. Letting go is one step;
Escapefirst puts it back. What is saved is what the map said: the end's move in the analyst's length unit and its bearing, or the speed, each to the decimals shown. -
The step. BLUE ONE sheared: 087.2°T 12.4 kn or BLUE ONE stretched: 12.4 kn (part sheared for the fixes in a period), then Held at the start, 09:30:00Z, Was 090.0°T 10.0 kn (or Was 10.0 kn) and the period. Its provenance record holds the end held (
anchor), the times of the held and dragged ends (anchor_time,dragged_time), how far and which way the dragged end went (distance,bearing), and the course and speed made good (course,speed): as asked where they were asked, worked out where they were not. Undo is replay to the step before, as for any step. -
The keyboard.
Tabto an end. Shearing, the arrow keys move it 5 pixels (25 withShift), as the move handle. Stretching,UpandRightmake it one step of speed faster (0.1 kn, or one step of the analyst's speed decimals),DownandLeftone step slower, ten withShift. A run of presses is one step, saved once they stop, onEnteror when the keyboard moves on;Escapeputs it back; presses made while the last step is saved are kept for the next. Shear and Stretch are buttons on the map, reached withTab. -
The forms. Shear track… (the outline's context menu on a track; Shear… under Track, below the outline, in the playground) asks what changes, which end is held (Hold the start or Hold the end), and the course and speed it then makes good, offering what it makes good now; a speed may be typed
12.4,12.4 kn,6 m/sor20 km/h, and each field says what it understood. Held at the start, the dragged end goes the speed times the period's length along the course; held at the end, Debrief finds the start from which the geodesic to the held end sets off on the course asked. Stretch track… asks what changes, which end is held, and the speed, which must be more than nothing. -
What is refused, and why. A shear or a stretch of fixes all at one time: BLUE ONE has fixes at only one time there, so it cannot be sheared or stretched: that needs fixes at two times. A stretch of fixes that end where they start: … so it cannot be stretched: shear it instead. A stretch to no speed. A shear, holding the end, to a course and speed that no leg ending at the held fix makes good, as can happen near a pole: … cannot make good 180.0°T at 25.0 kn and end where it does: no leg that long sets off on that course to its last fix. Hold the start instead. A change sent from a plot that has since changed is refused, as for any change (SUB-28), and a drag under way when the plot changes elsewhere is dropped and the map says so.
-
For agents.
debrief/edit_trackwith{"action": "shear", "anchor": "start", "distance": {"value": 1.2, "unit": "[nmi_i]"}, "bearing": {"value": 45, "unit": "deg"}}(the dragged end's move),{"action": "shear", "anchor": "end", "course": {"value": 87.2, "unit": "deg"}, "speed": {"value": 12.4, "unit": "[kn_i]"}}(the course and speed made good), or{"action": "stretch", "anchor": "start", "speed": {"value": 12.4, "unit": "[kn_i]"}}, each with aperiodto change only that. In VS Code,debrief.shearTrackanddebrief.stretchTracktake the track and the edit, withoutaction, instead of asking.
Not in this part: live bearing residuals while dragging, and solutions rooted in a period of bearings (the TMA module, CAP-21); shearing one leg of a multi-leg solution apart from the others.
Cleaning tracks¶
Part B2 (14 Oct 2026). Three ways to tidy a track an analyst has imported, each one recorded step, and none done without the analyst seeing what it would do first.
-
Jumps: found, shown, then removed. A jump is a fix the platform could not have reached in time: a GPS glitch, a mistyped position. Find and remove jumps… (the outline's menu on a track; Jumps… under Track, below the outline, in the playground) asks for a speed, offered as three times the track's median speed between fixes, and never less than 10 kn, which the analyst can change (
30,30 kn,15 m/s). Three times the median fits the platform: a helicopter at 120 kn and a submarine at 5 kn each get a threshold far above the changes of speed they really make between fixes; the 10 kn floor stops position noise on a slow or stopped platform being called a jump. A fixed speed (60 kn, say) would miss every jump of a slow platform and flag a fast one's ordinary fixes.A fix is a jump when reaching it from the last good fix before it needs more than that speed (range along the geodesic over elapsed time; two fixes at one time in different places need infinite speed). Comparing with the last good fix, not simply the fix before, finds a burst of bad fixes in a row; and after a jump a fix is only back on the track when the track goes on from it, so the second of two bad fixes is found even though it is reachable over the longer time since the last good one. A jump is off the track and back: a fix the track goes on from smoothly is not one, so a real burst of speed (a sprint between drifts, far above three times the median) is not offered. Up to 5 fixes in a row can be one jump. A track that goes off and stays off longer than that, or until it ends (a ship at anchor getting under way), is not a jump, since the platform may really be there; nothing is offered. The first fix is a jump when it is far from the next two and they agree; the last likewise.
What is found is shown first, never removed silently: each jump is ringed on the map in the theme's warning colour, the note at the top of the map says RED ONE: 3 jumps found, each faster than 30.0 kn to reach, and a list gives each one's time, position and how fast it would have been reached (09:20:00Z 37°08.456'N 075°26.932'W · 176.5 kn to reach from 09:19:00Z), all ticked. The analyst unticks any that are real (its ring goes), and Remove takes out the rest as one step: RED ONE: 3 jumps removed, with notes saying when they were (At 09:20:00Z, 09:21:00Z and 10:40:00Z), the speed (Each faster than 30.0 kn to reach) and any marked fixes that went with them. Where the track has two fixes at a jump's time (two tracks merged where they meet, say), only the one found to be the jump goes; when which it is cannot be told, nothing is removed and Debrief says so. Cancel, or closing the list, removes nothing. With none found, Debrief says so: RED ONE: no jumps found faster than 30.0 kn.
Removing fixes keeps every series in step: positions, times, speeds, courses, depths and marked fixes lose the same fixes. A track keeps at least two fixes.
-
Smoothing: previewed, then applied. Smooth track… (Smooth… in the playground) asks what to smooth (the whole track, or its fixes in the time window, as for a move) and over how many fixes: an odd number, 5 unless the analyst says, each fix averaged with the 2 either side of it. One method, a moving average, chosen because an analyst can say exactly what it did: each fix moves to the average position of itself and the same number of fixes either side, worked out in a flat frame centred on that fix (ranges and bearings from it, along geodesics), so it is right far north and across the antimeridian. Near the ends of what is smoothed the window narrows evenly, so the first and last fixes never move and nothing is pulled sideways. A gap in the data (more than ten times the track's median time between fixes) is treated as an end: fixes either side of it are never averaged together, so a platform that went somewhere while nothing was recorded is not pulled across the gap. Fixes outside the period stay where they are. Times never change, so the fixes stay in time order. Recorded courses and speeds are averaged over the same fixes (courses as directions, so 350° and 010° average to 000°), so they stay in step with the positions; depths are kept. Simplifying a track (dropping fixes, as Douglas-Peucker does) is a different operation, not offered: it loses fixes rather than moving them.
Before anything changes, the track as smoothing would leave it is drawn dashed in the theme's focus colour over the track as it is, and the note says what it would do: RED ONE smoothed over 5 fixes, if applied: 236 fixes moved; the most a fix moved: 0.06 nmi, at 09:22:00Z. Apply makes it one step, RED ONE smoothed over 5 fixes (or RED ONE part smoothed…), its notes saying how many fixes moved and the most any moved, and the period. Cancel changes nothing. A track smoothing would not move (a straight, steady one) says so and records nothing.
-
Marked fixes: a colour, a label or a comment of their own. Legacy plots let an analyst colour single fixes, label them and comment on them, and the .dpf import used to list those as not imported. Now a fix can carry any of the three:
On the map Elsewhere Colour a dot at the fix in that colour, and the line from it to the next fix drawn in it the fix list Label the text beside the fix, as a track's name is the fix list Comment shown when pointing at the fix, with its time, position, course and speed the fix list, and the Timeline, at the fix's time, as RED ONE fix A fix with only a label or a comment is a ring in the track's colour, so it can be pointed at. To mark a fix: right-click it on the map (on a touch screen, press and hold it: about half a second with the finger still), or open the fix list (Fixes: colour, label or comment… on the outline's menu; Fixes… in the playground), which lists every fix of the track in time order with its time, position, course, speed and any mark, and choose one; then Colour… (the track colours, amber and yellow), Label… or Comment…. An empty label or comment, or Track's colour, takes it away. Each change is one step: RED ONE fix at 09:31:00Z coloured yellow, … labelled 'Turn 1', …: comment added (or changed, removed); a long label is shortened in the step's name and kept whole.
A mark is kept with the track, found by its fix's time, not its place in the track (see the schema's
FixMark). So it stays with its fix whatever happens to the rest: jumps removed before it, the track moved, rotated, sheared, stretched, smoothed, split (each part keeps its own marks) or merged. Where two fixes share a time, the mark is the first's; merging two tracks that meet at a time where both have a marked fix keeps the earlier track's, and the step's notes say so. Only marked fixes are listed, so a track of 10,000 fixes with three marked carries three marks, and the plot is still plain GeoJSON to other tools.From legacy plots. The .dpf import keeps each fix's own colour (where it differs from the track's), its label and its comment as marks. Legacy Debrief labels every fix with its time unless told otherwise; a label that only gives the fix's time (
0504,120500) is not imported, and the import says how many, since Debrief shows fixes' times itself. A label hidden in the legacy plot is imported and shown, and the import says how many. Where on the fix a legacy label went, and fix symbols and arrows, are still listed as not imported (EXT-15). -
What is a step, and what isn't.
Step in the history Undone by Ctrl+ZRemove the jumps ticked Yes, one for all of them Yes Apply smoothing Yes, one Yes A fix coloured, labelled or commented on Yes, one each Yes Finding jumps; unticking one; a smoothing preview; Cancel No No Choosing a fix in the fix list No No -
The keyboard. Everything here has a keyboard path: the commands and their input boxes and lists in VS Code; in the playground, the buttons under Track, below the outline, the form, the list of jumps (checkboxes) and the fix list (
UpandDownmove along it,EnterorSpacechooses a fix). Right-clicking a fix on the map, or pressing and holding it on a touch screen, is a shortcut, never the only way.Touch. On a tablet there is no right button, so pressing and holding a track or a marked fix does what a right-click does: after about half a second (0.55 s), the fix's menu opens where the finger is, the finger still down. It is a hold only while the finger stays within about 10 pixels of where it touched, no second finger lands, and the map does not move: a tap still selects, a finger that moves pans the map or drags a handle, and two fingers zoom. Holding a fix does not show the browser's own callout or select text on the map. Leaflet's built-in press and hold is not used: it works only where the browser says it is mobile Safari, which iPadOS often does not.
-
Shared state and conflicts. None of these changes current time, the time window or the selection (choosing a fix in the playground's fix list selects its track). A change sent from a plot that has since moved on is refused, as any change is (SUB-28), and Debrief shows the latest; jumps found or smoothing previewed on a plot that has changed must be found or previewed again.
-
For agents. The same through the tool service:
debrief/find_jumps(feature;threshold, a speed such as{"value": 30, "unit": "[kn_i]"}, andperiod, if wanted) returns the threshold used, the track's median speed and the jumps (time, position, speed to reach, the fix it was reached from) and changes nothing;debrief/remove_jumps(feature,times, and thethresholdfor the record) removes them as one step.debrief/preview_smoothing(feature,window,period) returns the track as it would be and how far fixes would move, and changes nothing;debrief/smooth_trackapplies it.debrief/mark_fix(feature,time,changes: any ofcolour,label,comment, null or empty taking one away;colour_namefor the step's name). Each change takesbaseas for any change. In VS Code,debrief.removeJumpstakes the track and{threshold, times}(times: "all"removes every jump found; notimesonly finds them and rings them on the map),debrief.smoothTrackthe track and{window, period, apply}(apply: falseleaves the preview on the map), anddebrief.markFixthe track, the fix's time and the changes, instead of asking.
sequenceDiagram
actor Analyst
participant Host as Extension host
participant Map
participant Service as Tool service
Analyst->>Host: Find and remove jumps… (threshold offered: 3 × median, at least 10 kn)
Host->>Service: debrief/find_jumps (feature, threshold, base)
Service-->>Host: the jumps; nothing changed
Host->>Map: show_fixes (feature_id, fix_times, message)
Map->>Map: ring each jump; "RED ONE: 3 jumps found…"
Host->>Analyst: the list, all ticked
Analyst->>Host: untick one; Remove
Host->>Service: debrief/remove_jumps (feature, times, threshold, base)
alt changed elsewhere since base
Service-->>Host: CONFLICT; nothing changed
else
Service-->>Host: one step: "RED ONE: 2 jumps removed"
end
Host->>Map: show_fixes (nothing): the rings go
Reference implementation¶
- Schema (0.0.14; 0.0.15 adds shear and stretch):
TrackEdit,TrackEditActionEnumandTrackEditAnchorEnuminschemas/linkml/features.yaml; the messageedit_track(feature_id,track_edit) inschemas/linkml/messages.yaml; the rules indebrief_schemas.documents.track_edit_problemsandvscode/src/messages.ts; fixtureswebview_message/valid/edit-track-*.jsonand theedit-track-*invalid ones. - Making and naming changes:
debrief_stac.tracks(moved,rotated,default_pivot,AnchorFrame,sheared,stretched,shear_target,leg_of,split,merge,overlaps, the step names);Catalogue.edit_track,split_trackandmerge_tracks; the service methods indebrief_tools.service. - The map: what a drag or an arrow key makes, the readouts, the handles' places and a run of presses in
vscode/webview/trackedit.ts(free of Leaflet, unit-tested); the handles, preview and keyboard invscode/webview/trackmap.ts; the host side invscode/src/panels/map.ts(receive) and the commanddebrief.editTrack. - VS Code: the commands
debrief.moveTrack,debrief.rotateTrack,debrief.shearTrack,debrief.stretchTrack,debrief.splitTrackanddebrief.mergeTracksinvscode/src/extension.ts, on the outline's context menu for a track. - The playground:
vscode/play/host.ts(the buttons and the small forms) andtrackinvscode/play/play.py. - Tests:
python/debrief-stac/tests/test_tracks.py(geodesic moves and rotations, far north and across the antimeridian; periods; split and merge invariants; undo; conflicts), the service test,vscode/test/unit/trackedit.test.ts, the playground test'svscode/test/play/tracks.mjs(drag, Escape, undo, rotate, keyboard runs, a period, a colleague's change during a drag, split, merge, an overlap refused, the forms), the playground test'svscode/test/play/shear.mjs(a straight leg sheared and stretched by its ends, Escape, undo, the keyboard, the forms), and the integration test's track steps. - Cleaning tracks (part B2): schema 0.0.16's
FixMarkandfix_marksinschemas/linkml/features.yaml, the messagesshow_fixesandfix_chosen, the rules indebrief_schemas.documents;debrief_stac.fixes(finding jumps, the default threshold, removing fixes with every series in step, smoothing, marks and the step names), marks carried throughsplitandmergeindebrief_stac.tracks;Catalogue.find_jumps,remove_jumps,smoothing_preview,smooth_trackandmark_fix; the service'sdebrief/find_jumps,debrief/remove_jumps,debrief/preview_smoothing,debrief/smooth_trackanddebrief/mark_fix; the .dpf mapping indebrief_io.dpf_import(_fix_marks);vscode/webview/fixes.ts(free of Leaflet: the fix list's rows, reading a threshold and a window, the words); the map's marks, rings and preview invscode/webview/map.ts; the commandsdebrief.removeJumps,debrief.smoothTrackanddebrief.markFixinvscode/src/extension.ts; the Timeline's fix comments invscode/src/timeline.ts; the playground's Jumps…, Smooth… and Fixes… (vscode/play/host.ts,cleanandglitchesinplay.py). Tests:python/debrief-stac/tests/test_fixes.py, the service test,python/debrief-io/tests/test_dpf_import.py,vscode/test/unit/fixes.test.ts, the playground test'svscode/test/play/cleaning.mjs, and the integration test's cleaning steps.
Not yet (part B and later): dragging single fixes; OTG and DR modes; simplifying a track (dropping fixes); where on a fix a label goes, and fix symbols and arrows; live bearing residuals while shearing or stretching (the TMA module, CAP-21); choosing which track wins where merged tracks overlap; renaming a track on its own.