Commit Graph
460 Commits
Author SHA1 Message Date
jyvikoandClaude Opus 5.5 3d38753cad geometry: a partition the kernel can only nudge off its plane is refused (#427)
The kernel's last-resort boolean retry moves the tool 1.3 µm and turns it
2 µrad. For a partition that puts the cut beside the face it was meant to
run along and leaves a cell bounded by slivers (the open boundary at x = 130
on the crank half). halves() now refuses a result-altering retry and names it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-16 00:20:02 -04:00
jyvikoandClaude Opus 5.5 1af87f1f98 mesh: a disk's O-grid follows the region's elongation (#198)
A smooth loop (straight sides running tangent into arcs, as a slot or a
rounded pocket) is meshed as a disk. Its middle block was a square halfway
to the loop's quarter points, which on the crank's 6:1 pocket floor
squashed elements to a scaled Jacobian of 0.16. The block is now a
rectangle on the region's principal axes, inset by the same distance all
round (the old square on a circle), its corners paired with the loop nodes
nearest their diagonals, its sides spaced as the nodes they pair with, and
the O-grid is smoothed (untangled first) before the validity check.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:55:02 -04:00
jyvikoandClaude Opus 5.5 e9801e4528 ui: draw the marked elements in the error colour
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:32:47 -04:00
jyvikoandClaude Opus 5.5 75b8c7e26e engine: mesh.quality.mark marks the elements below quality limits as a set
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:32:47 -04:00
jyvikoandClaude Opus 5.5 33d69fc53d mesh: list the elements that fail quality limits, worst first
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:32:47 -04:00
jyvikoandClaude Opus 5.5 44de124d9d engine: geometry.check reports what is small against the element size
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:17:39 -04:00
jyvikoandClaude Opus 5.5 5cee94f947 geometry: check bodies for short edges, small and sliver faces, near faces
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:17:39 -04:00
jyvikoandClaude Opus 5.5 06c4a8d73d mesh: projection divisions from the mean edge length of each class, thin-layer tests (#418)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 23:09:50 -04:00
jyvikoandClaude Opus 5.5 f9a0282acc engine: results.export.vtu writes a solved step for ParaView
Static, frequency (per mode), nonlinear and explicit (per frame, with a
.pvd collection) and heat results; fluid steps are refused. Wedges keep
the model's node order: VTK 9's wedge has the same orientation.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:55:12 -04:00
jyvikoandClaude Opus 5.5 439dfc678f io: write VTK XML unstructured grids and PVD collections
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:55:12 -04:00
jyvikoandClaude Opus 5.5 68016f69f7 engine: the crank half y > 0 divides where its mirror does (#283)
The kernel failure is reported as such since #381; the failure itself came
from split_by_plane's oversized boxes, which #384 replaced with body-sized
ones. The regression test now requires the cut (x = 110, 148, reversed
normal, the diagonal plane) from commands, with the cells' volumes adding up.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:45:27 -04:00
jyvikoandClaude Opus 5.5 92d49debec mesh: a screw hole's ring takes in the fillet of its rounded corner; frames centred on the hole (#402)
The projection layout gave every fillet a blend layer along the sides it runs between, so a
screw hole close to a rounded corner sat inside the layer and the plan fell back to frame cuts
and swept cells, which fan into the hole. A corner fillet that lies inside the square from the
hole to the two sides is now taken in by the hole's O-grid ring: the frame reaches both sides,
its outer corner projects onto the middle of the fillet, and no layer is needed. An O-grid's
frame is centred on its hole (a near side is the frame, the far side as far), and the plan
reports the layout's frames and drops the frame-cut notes when it does not cut.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:43:02 -04:00
jyvikoandClaude Opus 5.5 1d71a9f8af engine: mesh.export.stl writes the outer surface or a set's faces
Binary by default, ASCII on request; in the Mesh tab's Verify panel.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:34:02 -04:00
jyvikoandClaude Opus 5.5 87710a83ab io: write element faces as binary and ASCII STL
Model::skin_faces gives the mesh's outer skin: the exterior faces of
the solids and the top side of every shell.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 22:34:02 -04:00
jyvikoandClaude Opus 5.5 eecdcb5b96 mesh: projection divisions follow the curvature of curved targets, max_arc_angle (#418, #402)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 21:53:38 -04:00
jyvikoandClaude Opus 5.5 464417d84d mesh: test that a plane is trimmed to its face (#418)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 21:53:38 -04:00
jyvikoandClaude Opus 5.5 c107ea8105 mesh: a point of a plane past its face's triangles is off the face (#418)
project_trimmed accepted the analytic projection within a fifth of the nearest
triangle's size; a plane face's triangles can span the whole face, so nodes in a
3 mm fillet landed on the untrimmed box planes (mesh volume = the unfilleted box).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 21:53:38 -04:00
jyvikoandClaude Opus 5.5 390ddcd6cc cli, mcp: snapshot --section and --field; headless MCP screenshots on the GPU
--section x|y|z[=VALUE] hides the elements on the camera's side of a plane
(at the mesh's middle by default) so the element faces inside show;
--field contours a nodal field of the solved step (results.contour). The
MCP server's headless screenshot draws with the viewport's pipeline on the
shared device and its reply, like snapshot's, names the renderer.

Refs #422

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 20:50:40 -04:00
jyvikoandClaude Opus 5.5 c9163e98ad gpu: captures draw name labels; a shared capturer and a PNG with the CPU as last tier
render::draw_labels draws a scene's labels over finished pixels in the CPU
rasterizer's font. capture::shared opens the process's device once by the
FIELDCRAFT_GPU policy; capture::png draws on it or on the CPU and reports
which (Renderer).

Refs #422

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 20:50:40 -04:00
jyvikoandClaude Opus 5.5 fee978c7e4 cli: snapshot draws a script's model to a PNG with no window
fieldcraft-cli snapshot script.json --out shot.png [--view] [--size WxH]
draws the engine's framed scene (engine::view::frame, shared with the CPU
render_png) with the viewport's GPU pipelines offscreen: hardware GPU, then
a software one, then the CPU rasterizer (FIELDCRAFT_GPU=auto|hardware|
software|cpu). CI installs lavapipe so the GPU path runs there.

Refs #422

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 20:19:00 -04:00
jyvikoandClaude Opus 5.5 248e74ca9e gpu: the viewport's pipelines move to a crate of their own (fieldcraft-gpu)
ui-egui keeps only the egui_wgpu paint callback; the shaders, batching and
pipelines are fieldcraft-gpu's view module, so an offscreen picture can draw
with the window's pipelines.

Refs #422

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 20:19:00 -04:00
jyvikoandClaude Opus 5.5 575ae10dbf mesh: tests pin projection smoothing's edge ratio and regular grids (#418)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 19:39:01 -04:00
jyvikoandClaude Opus 5.5 58d3b351ff mesh: projection smoothing keeps a result that holds the grid's quality (#418)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 19:39:01 -04:00
jyvikoandClaude Opus 5.5 5306450413 mesh: projection smoothing guards edge ratio and never leaves the grid worse (#418)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 19:39:01 -04:00
jyvikoandClaude Opus 5.5 d29334a7a7 mesh: mesh.plan.apply builds rings and fillet/chamfer blend layers as one projected block layout (#402)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 18:59:02 -04:00
jyvikoandClaude Opus 5.5 361ac2e7b3 ui: an icon for Extrude to Surface (mesh.hex.extrude)
develop CI failed every_catalogue_entry_has_an_icon_and_every_icon_an_entry since #414.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 17:39:22 -04:00
jyvikoandClaude Opus 5.5 febd40fadc mesh: split a projection block through its whole sheet; name twisted elements' block junction (#399)
Topology::split cuts a block at given fractions and every block chained to it
through parallel edges, orienting the fractions through the chain, so the
topology stays conforming. A certified-invalid element is reported with its
block, cell, centre and the block vertex and blocks meeting there; the mesh is
never emitted.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:57:05 -04:00
jyvikoandClaude Opus 5.5 4dadaa50aa ci: docs/releasing.md: release jobs run in parallel; only the draft waits for verify
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:52:48 -04:00
jyvikoandClaude Opus 5.5 e468133f9a ci: package releases in parallel with the verify jobs; only the draft job waits for both
The release job (the only one that signs SHA256SUMS.txt or touches a GitHub Release) now needs
every verify and packaging job; packaging no longer waits for verify. Verify jobs restore
develop's CI caches through shared keys (same CARGO_* env as ci.yml); saving stays main-only.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:52:48 -04:00
jyvikoandClaude Opus 5.5 c82c13019a docs: regenerate features.md after the rebase
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:44:40 -04:00
jyvikoandClaude Opus 5.5 d703cdde0b docs: extrude up to a surface in the literature, MCP and meshing skill (#400)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:44:40 -04:00
jyvikoandClaude Opus 5.5 c077131285 ui: Extrude to Surface form picks the source face, then the target surface (#400)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:44:40 -04:00
jyvikoandClaude Opus 5.5 4ac31d3988 engine: mesh.hex.extrude, hex layers up to a target surface (#400)
The section comes from a set (a 2D mesh or element faces), the mesh already
on the source faces (tagged, or a neighbouring body's boundary lying on
them, whose nodes are shared so the meshes conform), or a fresh quad mesh
of one planar face. Target and side faces project through the tet mesher's
B-rep projection. Replaces the body's mesh like the other meshers, tags the
body's own source, target and side faces, and is on the MCP mesh tool as
hex_extrude.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:44:40 -04:00
jyvikoandClaude Opus 5.5 600b2ff633 mesh: hex extrusion of a quad section up to a target surface (#400)
Each source node follows its own path (a direction or the section normal)
to the target, found by Newton on the target's tangent plane; layers are
graded by a bias; side faces, when given, hold the boundary nodes of every
layer (alternating projections at the target), and interior nodes take the
boundary-residual correction. Source nodes are kept, so a section taken from
a neighbouring mesh conforms with it.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:44:40 -04:00
jyvikoandClaude Opus 5.5 d6b336538a docs: start hex meshing from the provenance graph (#402)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:38:51 -04:00
jyvikoandClaude Opus 5.5 efe90ec50e mesh: geometry.features, mesh.plan and mesh.plan.apply from the feature graph (#402)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:38:51 -04:00
jyvikoandClaude Opus 5.5 8dd7446569 model: mesh plans, saved definitions with templates, rings, cuts and copies (#402)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:38:51 -04:00
jyvikoandClaude Opus 5.5 4cfb6dd3de geometry: the replayed feature graph per body (#402); a partition may list a cut body for its cells
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:38:51 -04:00
jyvikoandClaude Opus 5.5 d3ac6395bb engine: Projection Blocking form takes levels and merge
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:37:07 -04:00
jyvikoandClaude Opus 5.5 62fc00755a engine: a form for Projection Blocking (mesh.hex.project)
every_command_has_a_form failed on develop since #399.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:37:07 -04:00
jyvikoandClaude Opus 5.5 d781d6e427 engine: mesh.hex.project command, MCP, docs and meshing skill (#399)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:05:38 -04:00
jyvikoandClaude Opus 5.5 6efad8feeb mesh: projection blocking — block topology, projection onto the B-rep, elliptic smoothing (#399)
A block topology (carved grid, butterfly and seven-block sphere templates,
O-grid, extrude, connect) projected onto a body: outer block faces onto their
smooth face groups, edges onto the curve of two targets and vertices onto the
point of three by tangent-plane iteration, nodes by transfinite interpolation,
then Winslow smoothing with the boundary on the geometry and a compass search
on the worst elements.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 16:05:38 -04:00
jyvikoandClaude Opus 5.5 8092c39892 mesh.cells: a tie inside one design body says why (#396)
Every tied interface between cells of one design body carries `why`: the tet cell (and why
auto fell back), the reason the body's cells did not sweep together, or the cell meshed alone
by its method; so an agent knows which cut or method to change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 15:59:01 -04:00
jyvikoandClaude Opus 5.5 4610876384 mesh: square corners round rectangular openings; no sliver or unassignable blocks (#397)
The swept cross-section's decomposition:
- An opening with concave corners gets a layout that continues its sides to the outer loop
  (side strips and corner blocks, every corner near 90°). The thin air ring round the Pi
  enclosure's square pedestal was left to the free mesher, which put a node 1e-5 from the
  opening's corner: edge ratio 341,515.
- A piece's score is capped by its quadrilaterals' aspect against their longest edge or the
  target size, so thin strips and pieces much smaller than the elements no longer score as
  square blocks; the free mesh is scored alike for "do no harm".
- A disk is not cut into wedges round its centre (its O-grid is the scheme).
- Cuts whose pieces cannot be given division counts together (mapped pieces round a hole that
  chain back to a longer side) are refused, instead of failing the whole cross-section.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 15:59:01 -04:00
Preetinder Kalsi 2be6aff2f9 Bundle the macOS CLI inside FieldCraft.app 2026-10-15 15:43:32 -04:00
Preetinder Kalsi 991dd354cb solver: share Cholesky and LDLT triangular solves 2026-10-15 15:43:15 -04:00
jyvikoandClaude Opus 5.5 c012a9e442 ui: collapse the Relax-around-worst-element condition (clippy)
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
v0.6.0
2026-10-15 15:22:18 -04:00
jyvikoandClaude Opus 5.5 5a0605741b release: version 0.6.0
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 15:13:31 -04:00
jyvikoandClaude Opus 5.5 ef77deff5f build(deps): finish the zip 9 port and lock it
The 3MF reader's name_for_index now returns a Result in zip 9, and the
geometry test writer still wrapped last_modified_time in Some. Cargo.lock
gains zip 9.0.3 beside SolidCraft's zip 3.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UhhZMBTviDQxZvwnyP89fo
2026-10-15 15:08:13 -04:00
Skywalkingzulu1 4ffce253f2 fix(io): adapt to zip 9 API
- last_modified_time takes DateTime directly, drop the Some() wrapper
- file_names() returns Result<Cow<str>, ZipError>: propagate errors, compare
  the Cow<str>, and push the resolved name into seen
- test helper: ZipFile::name() now returns Result, unwrap it
- update the Cargo.toml comment explaining why we moved ahead of
  SolidCraft (still on zip 3)
- update Cargo.lock to zip 9.0.3
2026-10-15 15:08:13 -04:00