Files
Daniel 4d738cd210 Sketch: an ellipse is drawn with its axes, and D measures its half-axes (#9291) (#9292)
* Sketch: an ellipse comes with its axes, and D measures its half-axes

An ellipse could only be sized by its minor radius, drawn like a circle's
radius, and there was no way to give its full axes. sketch.ellipse now also
adds the major and minor axes as construction lines through the centre.
The major axis runs from the major end to the point opposite it; the minor
one is perpendicular to it, ends on the ellipse, and both are bisected by
the centre. That adds six coordinates and six equations, so the ellipse
keeps its five degrees of freedom, and it needs no new constraint kind and
no format change.

With the axes in place every ellipse size is an ordinary dimension. D on an
axis line gives its length, the whole axis. D on the outline gives a half-
axis, the distance from the centre to an axis end, chosen the way a line
chooses horizontal or vertical but in the ellipse's own frame: text pulled
across the major axis measures along it (the major half-axis), text pulled
out past an end of it measures across it (the minor one). The end on the
text's side is used. Near the boundary between the two, a dimension being
placed keeps the half-axis it had (sketch.dimension's previous_axis, which
the Dimension tool sends), so the preview does not flip. A half-axis and
its whole axis determine each other, so the second becomes a driven
dimension through the existing redundancy path.

Deleting the ellipse leaves its axes, as deleting a Center Rectangle's
edges leaves its construction diagonals. Ellipses without axes, from
existing designs, keep the minor radius as before, and type radius still
gives it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Guide: an ellipse's axes and half-axis dimensions

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: test that an ellipse's half-axis preview keeps its axis near the boundary

The Dimension tool sends the half-axis its last preview chose, so near the
boundary between the major and the minor half-axis the preview keeps it.
This covers that path from the tool, from both sides of the boundary.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's axes select and drag with it, as a rectangle's diagonals do

A double-click on a Center Rectangle's edge or diagonal selects its edges
and both diagonals, and dragging a diagonal moves the rectangle without
changing it, because its lines share corner points. An ellipse's axes are
held by constraints instead, so a double-click selected only the ellipse
(and Delete then left the axes behind), and dragging the major axis moved
the ellipse but stretched its minor half-axis.

Sketch::ellipse_axes now finds an ellipse's construction axes (the
detection sketch.dimension already used, moved into the sketch crate).
Sketch::chain treats an ellipse and its two axes as joined, so a
double-click on any of them selects all three. Dragging either axis moves
the ellipse and both axes as one, keeping both half-axes. Dragging the
outline still sets the minor half-axis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a corner test reads its line's id instead of assuming l1

sketch.ellipse now adds two axis lines, which take the first line ids, so
the extend test reads the id of the line it draws from the reply.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's axes cut a trim, as a Center Rectangle's diagonals do

Trim, extend and break take every other curve as a cutter, construction
lines included, so an ellipse's construction axes stop them as a Center
Rectangle's diagonals do. A test now states it for both shapes, and the
guide says it. The freeform cutter test keeps the axes it used to delete
and asserts the piece a trim removes: from where the major axis crosses
the circle to where the ellipse does.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: test dragging an ellipse's outline with its axes present

Dragging the outline sets the minor half-axis, and the minor axis line,
held on the ellipse at one end, follows it; the centre and the major
half-axis stay.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: other dimension types on an ellipse with axes keep the minor radius

Only auto, major and minor give a half-axis on an ellipse drawn with its
axes. Any other type (radius, diameter, horizontal and the rest) gives
what it gives on an ellipse without axes, as the parameter doc says,
instead of quietly becoming a half-axis chosen by the text. The arm for
a missing text_at is dropped: with no text the rule already picks the
minor half-axis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: test an ellipse's half-axis dead zone from the major side too

The tests only showed a previous minor half-axis being kept near the
boundary; the point they used on the major side is major by geometry
alone. A point inside the band where geometry says minor now shows a
previous major half-axis kept, in the engine and in the Dimension
tool's preview.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a placed ellipse half-axis is the one its preview showed

On an ellipse already sized, a half-axis is added as a driven dimension
on the click, and that command left out the half-axis the preview kept
near the boundary, so the click could place the other one. It now
passes it as the preview does.

The remembered half-axis also comes only from a draft whose text was
placed (one without text is the minor half-axis by default and biased
the first placement), is kept per sketch as well as per picks, and is
forgotten once a dimension is placed or the picks are cleared.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: say how an ellipse's axes are recognised and what that costs

The axes are read from the constraints, with no mark in the design, so
the doc comment says which lines count, that deleting the midpoint or
point-on-curve constraint leaves an ellipse without axes, and that each
lookup scans curves times constraints.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse with one axis deleted still picks its half-axis by the text

With one construction axis deleted, D on the ellipse fell back to the minor radius wherever the
text was pulled, because the half-axis choice needed both axes. It now reads what is left of
them and chooses as before: the major half-axis goes to the major end (also from the far side,
when the point opposite is gone with its line), the minor one to its axis end, or as the minor
radius when the minor axis is the one deleted. An ellipse with neither axis keeps the minor
radius.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the one-axis half-axis test checks what is measured to

The test for an ellipse with one axis deleted checked only the reply's axis and value, which
both ends of an axis give alike. It now checks the dimension's kind and end: the axis end on
the text's side, the major end from either side once the point opposite is gone, a radius once
the minor axis is. With the major axis deleted and no text the reply names the minor axis and
measures to its end, where it used to be a radius with no axis named.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's minor radius is drawn as its half-axis, without R

A radius on an ellipse is the minor half-axis, and it was drawn as a circle's radius: one
leader from the centre towards the text, marked R, which measures nothing a reader can see.
It is now drawn as the distance from the centre to the minor axis end on the text's side,
the way the half-axis is drawn while the ellipse has its axes, and labelled with the length
alone. This is what D gives once the minor axis line is deleted, and on an ellipse with no
axes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's half-axis keeps a radius's stored text

The half-axis frame read the stored text from the middle of the half-axis, so a radius placed
on an ellipse in an existing design would show its text somewhere else. The text is stored from
the centre again, as a radius's always was, and the side drawn to follows it. An unplaced one
sits where a linear dimension to the minor axis end puts its text, and stacked texts step out
from the centre as a radius's do. A view test reads the painted label, so the drawing cannot
go back to R unnoticed.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse moved, turned or scaled takes its axes along

Move, Sketch Transform and Scale moved only the curves picked, so an ellipse moved without its
axes left them where they were: its centre no longer halved them, the minor end left the
ellipse, and the sketch stayed unsolved. A Center Rectangle's diagonals share its corners and
always go along; an ellipse's axes share only the major end. The axes now go with the ellipse,
as they do when it is dragged. Copy is unchanged: it copies no constraints, for a rectangle
either.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a preference draws ellipses without their axes, as before

Drawing an ellipse with its construction axes changes what the Ellipse tool makes out of the
box, so the old ellipse stays one setting away: Preferences › Sketch › Draw ellipses with their
axes, on by default. Off, the tool draws the ellipse alone. sketch.ellipse takes axes: false
for the same, and keeps drawing the axes when it is not given.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: sketch.ellipse refuses an axes value that is not true or false

A string such as "false" was read as not given, so the axes were drawn; it is now refused as
the text commands refuse a non-boolean bold or italic. The move test also covers an ellipse
whose minor axis was deleted: the major axis left goes along.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: D picks a half-axis on an ellipse without axes too

An ellipse with no axis lines (both deleted, a mirrored copy, one from an older design) gave the
minor radius wherever the text was pulled, so its major half-axis could not be dimensioned on
it. The half-axis is now chosen by where the text is on every ellipse: the major one to the
ellipse's own major end, the minor one as its minor radius. With no text it is the minor
radius, as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: with one half-axis dimensioned, D on the ellipse gives the other

D on an ellipse chose the half-axis by where the text was pulled even when that half-axis was
already held by a dimension, so the second D usually guessed the one already there and was
refused as over-constrained. With a driving dimension already on one half-axis (to an axis
end, the minor radius, or the whole axis along its line or between its ends), D with no type
now gives the other, in either order and with or without the axis lines. With both held it
chooses as before; an explicit major or minor is kept.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the held half-axis rule is documented and its cases tested

The Dimension command's parameters and the guide now say that with one half-axis held, D on
the ellipse gives the other. Tests cover the whole axis held as a distance between its ends
and as its line's length with the other axis deleted, and check that a mirrored ellipse has
no axes. The placement test undoes its first dimension, so its second half still tests where
the text is rather than the held half-axis.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: Transform previews an ellipse with its axes

OK in Sketch Transform moves, turns and scales an ellipse's axes with it, but the window drew
where OK would leave only the picked curves, so the axes stayed put in the preview until OK. An
ellipse picked alone is now drawn with the axis lines it has.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the typed-radius ellipse test counts the ellipse's axes

Main's #10282 test drew an ellipse with typed radii and expected one curve; with the
ellipse_axes preference on by default the tool also draws the two axes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's remaining axis still drags and selects it

With one axis deleted, dragging the other axis did not hold the ellipse (with the minor axis
left, the drag squashed it), and a double-click on the ellipse or that axis selected only the
one curve. The drag and Sketch::chain now read whichever axes are left through
ellipse_axis_lines, as Transform and Move already do.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: drop the unreachable third arm of the held half-axis check

A distance from the centre to the major end or the point opposite it is already matched by the first arm, so the third arm and its major_end closure never ran.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: D on an ellipse's axis line is the whole axis wherever the value is pulled

An axis line took the free line's rule, so on a turned ellipse a value pulled beside or above the box the axis spans gave its horizontal or vertical distance. An ellipse's axis is a construction axis, so auto now always gives its length, which the held half-axis check already counts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's axis is never a side of a Fillet or Chamfer corner

A line drawn from an ellipse's major end shares that point with the major axis, so Fillet or Chamfer there took the two as a corner (two lines skip the construction filter) and rounded the line into the axis. The axes are left out of a corner, picked by its point or as a and b.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: test the move reply, extend and the one-axis Transform preview for ellipse axes

The reply of sketch.move, sketch.transform and sketch.scale lists the axis lines, Extend stops at an axis, and Sketch Transform previews an ellipse with the one axis left after the other was deleted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: with Draw ellipses with their axes off, D on an ellipse is its minor radius as before

The preference brought back the old drawing only; D on an ellipse had changed with no way back. sketch.dimension takes half_axes (default true, refused when not true or false); false makes auto on an ellipse the minor radius wherever the text is. The Dimension tool and the context menu's Sketch Dimension pass it from the preference, and with it off a radius on an ellipse is drawn and labelled R as before.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: read an ellipse's axes in one pass over the constraints

ellipse_axis_lines scanned every constraint for every curve, so 500 ellipses with their axes (1500 curves, 2000 constraints) took 1.6 s to read and Move on all of them 2.0 s. It now collects the lines the centre bisects first: 3 ms and 0.36 s.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the dimension and corner parameters say how an ellipse's axis lines take part

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Preferences: Draw ellipses with their axes says D gives the minor radius when off

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: ask only the ellipses centred on a line's midpoint whether it is their axis

is_ellipse_axis read every ellipse's axes to answer for one line. An axis is bisected by its ellipse's centre, so it now asks only the ellipses centred on a point that bisects the line. The answer is the same.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a horizontal or vertical dimension across a level major axis holds it for D on the ellipse

half_axes_held counted a distance, a length and a radius, but not a horizontal or vertical dimension across the major axis, which is its length when the axis lies that way. D on the outline could then take the held major half-axis and be refused as determined; it now gives the minor one. Across a slanted axis such a dimension is only a projection and does not count.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Dimension: a draft on an ellipse is drawn with the axes preference it was made with

The frame read the preference as it is now, while the dimension added is the draft's.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a horizontal or vertical dimension across an upright minor axis holds it too

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: drop the unused Sketch::ellipse_axes; ellipse_axis_lines says how the axes are read

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse's own axes do not cut it, so Trim takes a lone ellipse whole and stops at real crossings

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: Fillet and Chamfer offer no corner at an ellipse's axis end, as the engine takes none

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a deleted ellipse leaves its centre on its axes, as a Center Rectangle's centre stays

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: ellipse axis docs say what they do, and the corner picker tests a curve's ends before its axis role

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the trim-at-a-crossing test checks that part of the ellipse is left

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: an ellipse axis moved, turned or scaled on its own takes its ellipse along, as a drag does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: a selection dragged by an ellipse axis takes the ellipse along, as the axis alone does

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Docs: the Sketch preferences page lists Draw ellipses with their axes

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Sketch: the ellipse axes help text says D gives the minor radius, drawn and labelled R as before, wherever the value is pulled

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-11-04 16:54:46 +00:00
..

Preferences redesign: design reference

This folder holds everything the Preferences design boards know, so that nobody needs the design canvas to build a page. It belongs to tracker #9863 and was extracted from the 13 Prefs2_* boards (canvas version 202) plus four reference boards. Once merged it is authoritative: if a board and this folder disagree, fix this folder in a docs-only pull request.

Nothing in the redesign changes a default. It regroups settings, restyles their controls and adds the settings-profile switcher.

Files

File What it holds
pages/<page>.md One spec per page: sections in order, each control with its verbatim label, control type, the setting it edits, default, hover text, figure, and the mismatches with the code.
figures/*.light.svg, figures/*.dark.svg Every illustration on the boards as a standalone SVG, verbatim geometry. figures/README.md states the house style.
measurements.md Dialog frame, spacing, control sizes, radii, type sizes, as measured from the boards.
tokens.md Every board colour mapped to a theme::Tokens field, or flagged "no token".
boards/ Not included: the boards are rendered from the canvas, which is private. The figures and the measurements replace them.

Pages: General, Appearance, Layout, Graphics, Design, Sketch, Tools, Navigation, 3D mouse, Shortcuts, Assistant, Plugins.

Page structure: 9 pages become 12, in four headings

General sits on top, ungrouped. Every heading holds at least two pages. The page list also shows a profile switcher card at its foot on every page.

Heading Pages
(none) General
Look Appearance, Layout, Graphics
Work Design, Sketch, Tools
Input Navigation, 3D mouse, Shortcuts
Extend Assistant, Plugins

Today's pages (PAGES in crates/ui-egui/src/prefs.rs): General, Interface, Design, Navigation, Keyboard Shortcuts, Sketch, Graphics, AI, Plugins. The old board's map (Prefs2_Map) showed "Sketch & selection" under Input and Graphics under "Display"; the later boards and tracker supersede it.

Where settings move

Setting group From To
Layout, toolbar, status bar, notices, menus, History and browser placement, dialog placement, toolbar tabs, navigation bar Interface Layout
Theme, theme options, viewport background, logo, scale and text, colour vision Interface Appearance
3D mouse (all of it, including the navigation bridge) Navigation 3D mouse
Direct interaction, "Tool at the cursor" Navigation Tools
Hole, Extrude, Placement, Assembly Move (joint handles, near and far steps, ghost) Design Tools
"Axis distances in Measure" Graphics Tools
Sketch and selection Sketch Sketch
Largest file, network locations, slicer reuse, print-face highlight General / Design General > Files
Renderer, window system, graphics card Graphics Graphics ("This computer")
Ambient occlusion Graphics > Edges and shading Graphics > Current view (a fourth tile)
Origin plane names, hide-origin Interface / Design Design > Origin
Profiles General General > Profiles, plus the profile card in every page list

Settings profiles

crates/ui-egui/src/settings_profiles.rs holds the Interface, Navigation and Sketch preferences, language, shortcuts, toolbar and S-box favourites, and the imported theme in use. It excludes the 3D mouse, Graphics and the Assistant. Pages a profile stores (General for language, Appearance, Layout, Sketch, Navigation, Shortcuts) carry an In profile tag beside the page title, with the hover text "Saved in settings profiles". The profile card at the foot of the page list shows the active profile name, with a dot and the hover text "Changed since saved" when it was edited.

Five ways to show a setting

Way Use
Picture cards Options that look different.
Segmented Two to four short options.
Checkbox Explanation on hover (the (i) icon).
Stepper plus live sample Numbers with their result.
List or table Per-item data.

The checkbox, segmented, dropdown, slider, stepper and badge are existing ui_kit controls. New: the page-list group headings and profile card, the "In profile" tag, the picture card, toggle tile, preset card, hover-help icon and carousel (step 2 of #9863), the theme carousel and options panel, the layout preview, the navigation-bar editor and the colour vision sample row.

Design rules the boards follow

  1. Few words. No explanatory paragraphs. Help moves to an (i) icon with a hover tooltip (the title text on the board, quoted verbatim in the page files). Visible text is labels, values and short badges ("Restart needed", "Desktop only", "Not on this GPU").
  2. One illustration style: see figures/README.md.
  3. Generous spacing: 38 px between sections (measurements.md).
  4. Colours are the existing theme tokens, never literals; where a board colour has no token, tokens.md says so.
  5. Section titles are plain text on the board and upper-cased by the style (text-transform: uppercase, 11 px, weight 600, tracking 0.07 em). Write them in sentence case in catalogs.

Reading a page file

Each control row is Label | control | edits | default | hover | figure | notes:

  • Label and hover are verbatim from the board. Board spelling is UK English (Centre, Colour); the catalogs hold US text in en.json and the UK spelling in en-GB.json.
  • Edits is the Prefs field (in crates/ui-egui/src/prefs.rs, the preference_settings! table) or the app/session field or command that the control changes, as of main at the time of writing. app.ui.* and app.session.* fields are session values that Preferences edits through its Snapshot.
  • Default is the default of the field in Prefs::default().
  • Notes flag every mismatch: a control with no setting behind it, a setting with no control on the board, a label that differs from the current catalog, and anything uncertain.

Controls with no board

Settings present in the code with no control on any board (not to be added by this redesign): parameters_apply_live (Parameters apply live) and personal_sheet_rules. Settings that exist only for other features and sit on no Preferences page (render_*, save_mesh_*, view_dxf_*, send_slicer, custom_slicers, easyprint_consent, update and similar memos) are also not on the boards.

Placeholder content (not to be built as drawn)

The boards show sample content. Build the real data, not these examples:

Page Placeholder
General Profile names (Laptop, Large monitor, Presentation), the network host chips (\\files.studio, \\nas01), "3 saved", "2 saved" crash reports, the update time.
Appearance The "Studio glass" imported theme and its options; the sample "Extrude 112.5 mm" distance row.
Layout The navigation-bar slot icons and names (Faces and edges, Spin, Projection, Ground shadow, Ambient occlusion) stand in for the app's own slots and icons; "10 of 16 slots".
Navigation The mapping rows and the mouse figure show the Fusion-style mapping only as an example of the shape.
3D mouse The device ("SpaceMouse Compact"), the live bars, and the button jobs (Open Preferences, View · Fit, View · Top, Hold Shift, Not assigned).
Shortcuts The whole command list, groups and key assignments.
Assistant Agent names and states (Claude Code, Codex CLI, Local model), "Signed in", "Key in environment".
Plugins The three plugin cards (Gear generator, Bracket tools, Thread library), their versions, permissions and descriptions.

Known gaps

  • The boards were checked in a browser in the light theme after the last edits; the dark half is generated from the same layout.
  • Theme options follow the text of Theme_Options.dc.html; the Appearance board was not compared against its rendering.
  • The graphics presets are the three in the code (Performance, Quality, Custom). An earlier board showed a fourth, "Balanced", which does not exist.
  • Screenshots of the boards (boards/*.png) are not included. The canvas is private and the extracted figures, measurements and token map are the substitute.