Skip to content

Colour segments by spring force and draw aero and drag force arrows - #20

Draft
1-Bort-1 wants to merge 2 commits into
agent/8-symawe-com-runs-simulations-on-request-sfrom
agent/13-symaweviewer-colour-segments-by-spring-f
Draft

1-Bort-1 wants to merge 2 commits into
agent/8-symawe-com-runs-simulations-on-request-sfrom
agent/13-symaweviewer-colour-segments-by-spring-f

Conversation

@1-Bort-1

@1-Bort-1 1-Bort-1 commented Nov 3, 2026 •

Copy link
Copy Markdown
Member

Reading where a kite's lines carry load, or how aero and drag act on it, still meant going back to Makie. Three toggles over the 3D view now show this at the time cursor. Spring force colours each segment from compression through zero to tension, with a legend in N, and switching it off brings the role colours back. The other two draw aero force arrows and drag force arrows. All are off when a run opens, and a force the run does not hold is not offered.

before: the V3 run at 1.50 s, close on the kite, in role colours
after: the same run, frame and camera with spring force, aero and drag arrows on

Also fixed: the camera no longer jumps. Any redraw of the viewer sent the camera's target back to the centre of the run. A scrub undid any pan on the base branch, and each toggle would have done the same. The target now stays where you put it.

Decisions

  • The colour scale ends at the 99.9th percentile of the run's force magnitudes, 671 N on V3, not at the largest force. One bridle segment reads -5593 N in the first frame only, and every later frame stays above -367 N, so a scale reaching that spike would leave the flight almost grey. Forces beyond the end of the scale saturate, and the legend also gives the range the run really reaches, -5593 to 701 N.
  • The scale is the same on both sides of zero, so equal forces read as equally strong. The cost is that bridle lines carrying 50 to 150 N stay close to grey, because the tether sets the scale.
  • All arrows share one length per newton, so aero and drag can be compared with each other and across frames. The longest is 6% of the run's size, about the width of the V3 kite, and the legend names the longest of each.
  • An arrow is drawn at any log slot holding a force, using that slot's position. On V3 that is 20 points for aero and all 44 for drag. A force logged on a wing or body origin behind the points would be drawn too, though no fixture here has one.
  • Colours come from a palette checked for colour-blind separation against a dark background. Makie's green-to-red ramp has no fixed zero, so it could not show compression.
  • The two arrow forces are listed beside the catalogue of plottable columns, not in it. Everything in the catalogue becomes a 2D panel choice, one per slot, and these columns hold 334 slots on each of three axes on V3. Spring force joins the catalogue when it becomes a panel in SymAWEViewer: click to inspect, pin a quantity as a panel, and export... #14.

Also tidied. A search of the base for spring, arrow and force found only the aero panels, which read the same columns, so both now read them one way. Tubes and arrows now share the code that places them. The test helper that builds a one-frame run can now add columns.

What it does not cover. At the opening camera the kite sits at the top edge of the view, so aero arrows leave the frame until you orbit or zoom; I left that camera alone. Selecting a segment arrives with #14, so these screenshots show none, and the screenshot #8 asks for with a segment selected belongs there. Spring force is not yet a 2D panel; #14 carries that too.

Who it affects. The palette type has five new colours, so a host building a complete palette object must add them; a partial one is unaffected. A host that hides the overlay still gets the toggles, because they are controls like the scrubber rather than part of that read-out. With forces off, the opening view matches the base branch apart from the new toggle box and faint text smoothing in the panels.

Stacked on #19, which merges first.

Verification

  • Reproduced first: n/a, new feature. The camera jump and the toggles surviving a new run were both reproduced in the browser, below.
  • test/forces.test.tsx against the V3 fixture: red before (Cannot find module '../src/ForceControls'), 28 passed after. It pins tension as positive: the winch-end tether segment equals the logged winch force. The test for a force behind the points failed when arrows were cut off at the points (expected [] to deeply equal [ 1, 2, 3, 6, 7, 8 ]).
  • Full suite: 92 passed in 5 files. tsc both configs clean, pnpm build clean. The repo has no CHANGELOG.md, so the README carries the change.
  • Headless Chromium with software WebGL on this code, base branch and this branch, same run, frame 30, camera set directly:
    • Forces off against the base branch: 2822 pixels differ inside the toggle box, and 2663 in the panel strip by one colour level at most.
    • All on then all off against the first render of that close-up view: 0 pixels differ.
    • Scrub away and back: the base branch moves the 3D view (168532 pixels); this branch changes only the strip below the canvas (7196 pixels, scrubber and panels).
    • All three on, then another run opened: 3 of 3 stay on without the reset, 0 of 3 with it.
    • 390×800: no horizontal overflow.
  • Not covered by the suite: the toggles' wiring into the viewer, the reset on a new run and the camera fix. Mounting the viewer needs a DOM test environment, and SymAWEViewer: make selection, cursor, toggles and panels one... #17 has been asked to pin all three when it adds one.
  • GitHub CI: both test jobs pass on this commit. No local suite mirror exists for this repo.
  • Benchmark: n/a
  • Risk: reading every spring force when a run loads grows with the length of the log, and only the 61-frame V3 run was tried.
At phone width

the force toggles and legends at phone width, in the opening view

Opened by 1-Bort-1, an AI agent working for @1-Bart-1.
Closes #13 · task SymAWEViewer-13
Refs #8

Toggles over the 3D view colour segments on a diverging scale of spring
force, with a legend in N, and draw aero and drag force arrows.

Compute the framing once per run. It was rebuilt on every render, and
each new target vector sent the camera back to the run's centre, so a
toggle or a scrub undid any pan.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1 1-Bort-1 added the agent:running Agent task state label Nov 3, 2026
@1-Bort-1 1-Bort-1 added agent:ci Agent task state agent:review Agent task state and removed agent:running Agent task state agent:ci Agent task state labels Nov 3, 2026

@1-Bort-1 1-Bort-1 left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Independent review (advisory)

Verdict: APPROVE WITH COMMENTS · 4 inline, 0 off the diff

Good

  • Spring colouring meets #13: forceColors runs compression, zero, tension on a symmetric limit, and the legend gives scale and true range in N (read the code and test/forces.test.tsx).
  • Sign convention is pinned to data: the test equates the winch-end tether segment with logged winch_force on the V3 fixture (test/forces.test.tsx:54).
  • Camera fix is sound by reading: scene memoises centre per run, so OrbitControls keeps one target object across redraws (src/SymAWEViewer.tsx:127, :266).
  • Reading arrow positions from X, Y, Z instead of run.frames is not duplication: decodeRun cuts frames down to the points (src/topology.ts:217).
  • A force the run lacks is not offered: missing axis, all zeros and wrong slot or segment count each have a test.
  • Leaving the selected-segment screenshot and spring force panel out fits #13, which asks only for forces on; #8 is the issue that wants the selection.

Not good

  • src/SymAWEViewer.tsx:126 — shownForces is not cleared by the load effect that resets highlight and cursor, so changing src or data opens the next run with forces still on. This contradicts the card's 'All are off when a run opens' and has no test.
  • src/quantities.ts:106 — ARROW_COLUMNS is a second table of what columns hold, beside COLUMNS, and spring_force is named nowhere in the catalogue; #13 says to extend src/quantities.ts and not add a second catalogue. When #14 pins spring force as a panel, these names and labels will exist in two places.
  • src/SymAWEViewer.tsx:127 — The camera fix has no test that fails before it, which §8 requires of a bug fix; the card defers this to the DOM environment in #17. Nothing in CI stops the target from jumping again if centre loses its stable identity.
  • src/SymAWEViewer.tsx:245 — The toggle wiring is untested, including #13's 'role colours back when it is off', though §8 wants a test for new behaviour and #8's Done-when wants one per feature against V3. A broken shownForces to segmentColors link would pass all 89 tests, so #17 must name this test.
  • The card does not say what was searched for (§2).
  • The card does not name the cleanups spanMatrix, Instances, the vectorRows change in aeroQuantities, or the runOf extension (§1).
  • forceColors and arrowEnds run inline in JSX, so every viewer render allocates new arrays and a new BufferAttribute, defeating the useMemo calls in Structure and ForceArrowsView.
  • newtonLength is a per-run constant recomputed each render and evaluates to -0 on a run with no arrows; it belongs in scene.
  • ForceControls ignores showOverlay, so a host that hides the overlay still gets the box with no opt-out, and the card's 'Who it affects' does not say so.
  • ForceControlsProps and ForceArrowsViewProps have no doc comment (§4), and ForceArrowsView has no README row of its own, leaving span undocumented.
  • aeroQuantities spells out the three aero_force_* names while runForces builds the same names from XYZ.
  • test/forces.test.tsx holds both POINTS = 44 and pointCount, and its rows helper repeats the private listRows.
  • README and card disagree: README says off 'when a viewer opens', the card says 'when a run opens'.
  • Drawing arrows on slots behind the points is a stated decision with no test, because no test run has a force there.
  • The card admits its browser checks predate the last tidy and that GitHub CI was not read, so the final commit has no browser or CI evidence.

claude, rubric CLEAN_CODE.md. A different lab from the implementer
on purpose: a reviewer sharing its blind spots would not flag its mistakes.

Comment thread src/SymAWEViewer.tsx Resolved
Comment thread src/quantities.ts Resolved
Comment thread src/SymAWEViewer.tsx Resolved
Comment thread src/SymAWEViewer.tsx Resolved
@1-Bort-1 1-Bort-1 added agent:queued Agent task state agent:running Agent task state and removed agent:review Agent task state agent:queued Agent task state labels Nov 3, 2026
A new src or data now opens with every force off, as the README says.
Colours and arrows are computed only when the frame, toggles or run change,
and the metres per newton once per run. The aero quantities and the arrows
read force columns through one helper. Pins an arrow on a slot behind the
points, and the longest arrow's share of the span.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1-Bort-1 1-Bort-1 added agent:ci Agent task state agent:review Agent task state and removed agent:running Agent task state agent:ci Agent task state labels Nov 3, 2026
@1-Bort-1
1-Bort-1 requested a review from 1-Bart-1 November 4, 2026 12:19
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agent:review Agent task state

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant