What changed
Changes made to the port after design reviews with the original author of the Java program, most recent first.
Fourth round
- The camera never moves within an arrangement. The third-round fix pinned foreshortening to the selection's bounding sphere, but the camera still travelled as that sphere changed — so toggling an outer cell subtly changed the perspective of everything else, on both machines this time. Distance is now set once per build, from the radius of the whole buildable arrangement; selecting and deselecting cells changes it by exactly nothing, and only zoom — a flat projection scale — does the framing.
- Each view now works at its own scale. The solid adds or removes one cell: shift the cell sitting on the clicked face, ctrl the one behind it, green and red as before. The diagram toggles the cell on either side of its plane: shift the one beneath, ctrl the one on top — in gold and blue, because those are toggles and green/red would lie. The group operation — a box together with its whole supporting set — lives only in the Cells table, on either modifier, and it too is a toggle. The previous "same gestures everywhere" was this port's invention, not the design.
- The Cells table counts again. Every plain box drew the digit 0 — it was showing its sub-cell index, which is always zero for a box with one sub-cell, instead of its cell index. Visible the moment a low symmetry put several cells in one row.
- Du Val's letters, where they exist. For the icosahedron under Ih the boxes now read a, b, c, d, e₁, e₂, f₂, f₁, g₁, g₂, h rather than positions in a sorted list. The identification of which orbit is which letter is the derivation in the research notes, the same one the walkthrough's Ef₁ preset was verified against. Every other solid keeps indices — no other solid has an accepted lettering.
- Scrollbars in the Cells table, horizontal and vertical, drawn when the table overflows and draggable. And switching to a smaller table resets the scroll, so it no longer comes back cropped to where a bigger table left it.
- Symmetry elements in class colours, with a legend. Inequivalent elements — axes no operation of the group carries onto each other — get different colours; for Ih the legend reads C₅ ×6, C₃ ×10, C₂ ×15, m ×15, S₁₀ ×6, S₆ ×10, which is the textbook census. Mirror planes are rimmed with thin tori of the same thickness as the axis cylinders, so an edge-on plane reads as a bar instead of vanishing; the faint translucent fill stays, having been looked at and kept. Checkboxes grey out when the group has none of that kind.
- The elements are marked on the diagram too. A dot where each rotation axis pierces the drawing plane, a dashed line where each mirror plane crosses it, in the same class colours — what the Java applet's diagram checkboxes drew. One toggle: mark on the diagram.
- A real flick keeps the solid spinning. Release while moving fast enough and it spins on at that rate until you catch it — the Java behaviour. A gentle release still just coasts to a stop.
- Make planes, ported. The original program's plane editor: one plane per line —
nx ny nz dand optionally a symmetry group to multiply that plane by — seeded from the current solid's own planes, built into an arrangement like any catalog solid, saved into the JSON document. One line,0 0 1 1 Ih, builds the rhombic triacontahedron's thirty-plane arrangement. - Winding repair moved into the engine. The face-orientation repair the derivation tool needed lives in
core.jsnow (orientFaces), because it is a property of the catalog data, not of one tool: most solids in the file are not consistently wound, and anything that ever culls back faces or integrates a volume will need it. - Crowding relief for the zoomed-out diagram. Far below 1× the facet strokes thin and fade with the zoom, so the bundle of near-parallel traces shimmers less. This is mitigation, not elimination — at that scale there are more lines than pixels and no stroke width is honest.
- Documented, not changed: the ten hemi-dual solids whose faces are approximations of faces with vertices at infinity (clamped to ~100 in the data, hence genuinely non-planar) are now documented, along with a short how-to for serving this site from GitHub Pages.
Third round
- Resizing the 3-D pane no longer changes the perspective. The camera distance was derived from the narrower of the two field-of-view angles, so it depended on the shape of the canvas — drag the splitter and you could watch vertical lines bend. Distance now depends only on the solid's radius; a narrow canvas is framed by scaling the projection, which cannot bend a straight line. Measured: the ratio distance ÷ radius is now bit-identical from 1600×600 to 300×1200.
- Toggling a cell no longer changes the perspective either. Same root cause seen from the other side: the radius was floored at 1, so any selection smaller than the first one sat too far from the camera and flattened. The Windows-only symptom was the Cells panel gaining a scrollbar and resizing the canvas. Perspective is now invariant under every selection.
- Symmetry elements are solid geometry, so the solid hides what is behind them. Axes are drawn as cylinders into the same depth buffer as the stellation instead of being painted over the top. Three separate toggles: rotation axes, mirror planes, and rotoreflection (Sn) axes — the three-dimensional cousin of a glide reflection. Mirror planes are drawn as a solid rim with only the faintest wash inside, because fifteen translucent discs compound into an opaque ball that hides the very thing they explain.
- Turning the solid is smoothed, and a flick coasts. Pointer motion is banked and spent a fixed fraction per frame, which evens out the uneven steps a mouse reports; on release the recent speed is added to the buffer so the motion carries on and settles. A first-order filter rather than a spring, so it cannot overshoot and there is no ringing to tune out.
- Undo and redo, as buttons beside core / + layer / all / clear and on ctrl+Z and ctrl+shift+Z (cmd works too). Every change to the cell set is undoable, a hundred deep. Carving from a high cell takes its whole supporting set, which can reach the core, and there is no way to reconstruct what was there from what is left.
- Green adds, red removes, in all three views. Holding shift outlines the target green, the carve modifier outlines it red, and the same two colours are used in the 3-D view, the diagram and the Cells table. Releasing the modifier clears the outline immediately. When the gesture would do nothing — nothing further out to add, nothing behind the face to remove — the outline is dimmed rather than dropped, so you still see where you are pointing but know the click is spent.
- Diagram face is a dropdown of the faces that actually differ. It was a number with no upper limit, so most values did nothing. The list is now the orbits of the face planes under the chosen symmetry, each named by the polygon at the centre of its diagram. The cuboctahedron under Oh offers exactly two — triangle · 8 planes and square · 6 planes — and lowering the symmetry splits them, as it should.
- The collapse arrow points back the way it opened — ▸ to open a group of sub-cells, ◂ to close it, rather than a downward arrow that read as unrelated. The arrow and the count of hidden parts are larger, heavier and in a colour you can find.
- The view is kept in the URL and in saved documents. The hash now carries the orientation and zoom, so a reload comes back to the same angle and a link shows the recipient the same picture. Saved JSON carries them too.
- A stale build cannot be served silently any more. A good part of the session went on a bug that had been fixed an hour earlier — the browser had an old
app.jsand neither ctrl+shift+R nor ctrl+F5 shifted it. The site now sendsCache-Control: no-cachefor code and markup, so every visit revalidates, and the help panel prints which build you are looking at. - Crossed faces get the right plane. Newell's method sums a signed area, and a bow-tie face has two lobes that cancel — so its normal came out of rounding error. 413 faces across 15 solids were affected. Where the sum collapses, the plane is now fitted to the vertices instead. Seven solids whose faces are otherwise planar go from wrong to correct to machine precision; the rest are the hemi-duals, whose face data is genuinely non-planar.
- Dropped planes are declared. When a solid's faces do not all yield a usable plane, the status line reads ⚠ 8 of 12 planes rather than simply 8 planes, and the tooltip says why. Building an arrangement out of fewer planes than the solid has is the one failure that looks perfectly healthy: you get a stellation, of a different solid.
Second round
- The hover outline sat off the face it marked. A regression from making the model scale sticky: the highlight still computed its own scale, so the yellow triangle floated over the wrong place.
- Fit and home are on the view itself. Fit existed but was inside a collapsed panel section, so it could not be found. Both are now always visible in the corner of the 3-D view. home is the canonical orientation — x right, y up, z toward you.
- Zoom scales the projection instead of moving the camera, so magnifying no longer swings the viewpoint round the solid, and the range is wide enough to frame the largest arrangements. Picking was corrected to match the new frustum.
- Fit eases into place rather than snapping, over about four tenths of a second, and home turns the solid to the canonical orientation along the shortest arc. Any drag or wheel cancels the movement, so it never fights the pointer.
- The camera now retreats as the selection grows. Holding it at a fixed distance was wrong once a stellation reached past radius 6 while the camera sat at 3.3 — the viewpoint ended up inside the solid. It now backs off by the same factor the projection is scaled by, which leaves the on-screen size and the perspective untouched.
- ctrl is the exact inverse of shift. Both now walk inward: shift adds a cell with everything supporting it, ctrl removes that same set. Before, shift reached inward and ctrl reached outward, so the pair never cancelled.
- Sub-cell groups start collapsed, with an arrow beside each showing how many parts are hidden. Sub-cells are drawn smaller than their parent so the grouping reads at a glance. Under a low symmetry one orbit can hold 120 sub-cells, which used to run off the panel.
- Symmetry axes can be drawn in the 3-D view — the rotation axes of the current stellation group, through the origin. Checked against group theory: 31 for I and Ih, 13 for O and Oh, 7 for T, 3 for D₂.
- Inward-facing regions in the diagram are less faint. They were pale enough to be missed.
Controls
The largest group, and the one that changes how the app feels.
- Shift always adds; ctrl always removes. Neither toggles any more. Shift-clicking an already-selected cell used to undo the previous shift-click, so the same gesture sometimes added and sometimes removed depending on what you had just done. The two are now plain inverses.
- A bare click no longer edits in the 3-D view or the diagram. It turns the solid and pans the diagram respectively; only the Cells table spends a plain click on toggling. Previously a click meant one thing in one pane and something else in another.
- Right-click does nothing. It used to carve. On macOS ctrl-click is the system right-click, so the two are told apart by whether the ctrl key was actually held — a real right-click is ignored, a ctrl-click removes.
- One vocabulary on both platforms. The remove key is now called ctrl everywhere, because ctrl-click now works on macOS too. Option-click still works there as an alternative.
The Cells table
- Turned the right way up. The core is now the bottom row and each shell sits on the one below it, so the table grows the way the solid does — from the inside out. Row numbers are unchanged.
The diagram
- Inward-facing surfaces are drawn pale and dashed. The diagram shows the surface of the solid, not its volume, and a filled region invited the reading that there is material behind it — when an inward-facing face means the opposite, that there is a cavity. Solid fill now means outward, pale means inward.
Symmetry
- Only genuine subgroups are offered. The dropdowns listed all 85 groups regardless of the solid; for the icosahedron they now list the 13 that are actually subgroups of Ih, and the stellation symmetry is restricted to subgroups of whatever the polyhedron symmetry is set to. Membership is decided by testing the matrices, not from a hand-written table.
- That also fixes the "everything is broken" case. The all-zeros table came from choosing T (order 12) as the polyhedron symmetry with I (order 60) as the stellation symmetry — not a lowering at all, so every group had exactly one sub-cell. That pairing can no longer be selected. The sub-cell splitting itself was correct: under Ih → T an icosahedron's layers split 3/5/10, and under Ih → E into all 120.
Layout and view
- The panes can be dragged. Both dividers resize, and the positions are remembered — a deep arrangement can run a row of the Cells table far wider than the default column.
- The solid no longer resizes itself as you build. The scale was recomputed on every change, so adding a shell shrank everything already on screen. It is now fixed when the arrangement is built, with a fit button to rescale on demand.
- Edge weight now defaults to 1.
Documentation
- A short Controls & views page — the two gestures, the three views and what each pane is for, on one screen. The Cells panel now links there instead of to the walkthrough, under a shorter label.
- This page.
Investigated, not changed
Deliberately left alone, with the findings written down.
- Planes through the origin. Described in the session as a fundamental defect: a plane stored as a single point cannot represent one that passes through the centre, which is why twenty hemipolyhedra and their duals are commented out of the catalogue — the reason is written in the source, in the author's hand.
Investigated rather than fixed, on the instruction not to start it yet. The short version: the JavaScript port already stores four numbers, so the representation is not the blocker — one guard line is. Removing it does let all ten hemipolyhedra build, u80 included, in under a third of a second. But the guard turns out to be doing a second, unrelated job, and a prototype that removed it naively destroyed seven working solids. The discriminator that separates the two cases cleanly is face planarity, which differs between them by sixteen orders of magnitude. Written up with both prototypes, the measurements and an acceptance test in the design notes. - Clicking a region that has cells on both sides. On the diagram a plane has a cell above and a cell below, and there was a proposal to reach them separately — shift for one, ctrl for the other. Left as it is for now: shift and ctrl are spent on add and remove, which is the more valuable pair, and the session concluded "counterintuitive but ok, can leave as is".
- 3-D rotation in the original Java applet. Noted as a separate to-do against the original program, not this port.
Questions still open — what the "polyhedron" symmetry is for, what "compensate completely" should mean, the cube's orientation, and the cells-versus-surface confusion — are written up in the design notes. Source and notes on GitHub. See Controls & views for how the app works now.