mirror of
https://github.com/bherbruck/solidcraft.git
synced 2026-11-06 12:01:10 +00:00
65b02ff7ab28eb60055ecd5e501ced94de8b1765
98 Commits
| Author | SHA1 | Message | Date | |
|---|---|---|---|---|
|
|
7c14ae2ce2 |
Wave 287/509: Continuity Analysis measures G3 and G4; the dialogs offer what each construction builds
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
fceb07b797 |
Wave 283/509: STEP import: an edge through a face's pole is split there (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
34c5bc74a5 |
Wave 270/509: kernel-cases: a continuity check, and ladder 07/015 graded by it (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
335278e3c7 |
Wave 266/509: Profiler: commands, feature evaluation, io; diagnostics.profile; CLI --profile (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
176202b238 |
Wave 261/509: Format 40: a thread's hand on tapped holes too; v0.24.0's handedness opens as hand (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
27b8046c6f |
Wave 256/509: Rebase onto main: what the merged code needs to build together
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
0de308b21d |
Wave 213/509: kernel: a tangent chain stops at a smooth edge (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
8b3eedd0aa |
Wave 211/509: doc, engine, ui: placing the model returns its error; placements are checked where they are set
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
50ca3c5a61 |
Wave 192/509: kernel: corner rules for direction, rails and closed paths; no feature gate on SMLib sweeps (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
816e43c5d0 |
Wave 191/509: engine: no boolean retries to report; overlaps are SMLib's exact intersection (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
540aa0da1b |
Wave 185/509: engine: feature replies carry no boolean diagnostics (and 1 more)
2 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
b9e0543ef5 |
Wave 178/509: kernel-cases: the rig runs SMLib only and keeps each run's SMLib dumps
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
ab9c676627 |
Wave 169/509: kernel: an intersection curve is where SMLib's imprint cuts, exactly (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
966af74030 |
Wave 168/509: The truck crates leave the workspace; the rig and threads run on SMLib alone
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
0bd4531c7c |
Wave 110/509: WIP kernel: Body::mesh(&MeshTolerance) as the one mesher (does not build yet)
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
e63bcc3808 |
Wave 104/509: solidcraft-smlib: pin the fork at 2d7c7ed, the second round of SMLib C++ fixes (and 1 more)
2 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
5f743c46b7 |
Wave 86/509: kernel: one switch, SOLIDCRAFT_KERNEL, picks the kernel for every operation (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
924ed1b57d |
Wave 75/509: kernel-cases: tessellation cases from mesh-hole reports grade watertightness (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
96aae9c316 |
Wave 71/509: kernel-cases: a thread off its hole or shaft size is refused (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
68033b4357 |
Wave 68/509: kernel-cases: fillets cases from #1008, #1191, #3276 and #3753 (and 2 more)
3 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
ed5bed8f00 |
Wave 67/509: kernel-cases: sweeps skipped sources (72) (and 3 more)
4 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
03e3bee095 |
Wave 31/509: kernel: boolean runner grades the seeds against a reference volume (and 1 more)
2 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
9f1b47d689 |
Wave 30/509: kernel-cases: a regression rig that grades each kernel against the case's own answer
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
6224363182 |
Wave 8/509: brep: a surface point's parameters move to geom (and 2 more)
3 commits, squashed; the originals stay reachable from tag archive/merge-main-develop. - |
||
|
|
4b72c3e257 |
Wave 7/509: naming: the corpus rebuilds with the same names and references
1 commits, squashed; the originals stay reachable from tag archive/merge-main-develop.
-
|
||
|
|
a7c1909766 |
CLI: evaluate scripts on the input design (#6861) (#6872)
* claim: #6861 eval scripts on input designs * fix(cli): evaluate scripts on the input design (#6861) * fix(cli): validate eval options before opening inputs Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
03bf992bc1 |
Keep linked components valid through Undo after Save As (#6860) (#6877)
* claim: #6860 * fix: preserve linked component targets across Save As history (#6860) |
||
|
|
189b47c750 | Chamfer and Fillet refuse a point where several edges meet (#5173) (#5177) | ||
|
|
b3cbbe7bd5 |
CLI: reject incomplete and unsupported run/eval options (#6918) (#6919)
* claim: #6918 validate run and eval options * fix(cli): reject invalid run and eval options (#6918) |
||
|
|
dfde1e032d |
mcp setup: add SolidCraft to the AI clients on this computer; plain mcp finds a late app (#6379)
solidcraft-cli mcp setup (alias install) and Help > Connect AI assistants edit each installed client's own configuration in place, with this program's absolute path: OpenCode, Claude Desktop, Claude Code, Cursor, Codex, Gemini CLI, Copilot CLI, Windsurf, Zed and VS Code. Only the solidcraft entries change; a stale path is refreshed and an entry the user changed is left alone. Plain mcp keeps looking for the app while its headless session has no work, and says on every tool result that it is headless when the app was not found. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
0520910bfd |
Control: name the token file and spot a stale one when a call is unauthorized (#4664) (#4670)
* claim: #4664 * Control: name the token file and spot a stale one when a call is unauthorized (#4664) When the app refuses a token that the MCP client read from a token file, the error now names that file, when it was written and how long ago, without printing the token. The app also writes `<port>.pid` beside the token file (its process id and, on Linux, its start time) and removes both at exit; when that process has exited, the error says the token file is stale. The process check runs only after a refusal, and the token file itself stays one line, so existing clients keep working. Document force-quit leftovers and the MSIX AppData redirection. * Bench assistant: read the token out of the new ClientToken Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com> --------- Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
9e6e0b8df1 |
Render workspace: complete experimental ribbon, resources and effects integration (#5493) (#5494)
* wip(render): reconcile completed material and image pipeline source with 0.20 (#5493) Source-only integration reference for staged review, not a merge-ready aggregate. Donor: 0xlillith/solidcraft@aea20b0115. Upstream: |
||
|
|
b7b25f9e2b |
Render workspace: first basic delivery to main (#6050)
* Normalize UI container violation paths across platforms (#5599) Report repository-relative paths with forward slashes so diagnostics and the existing nested-package regression assertions agree on Windows and Unix. Keep the container detection rules unchanged. Validation: official ui-containers gate and all seven focused xtask tests passed; rustfmt and diff checks passed. Only xtask/dependencies were compiled; no application build or heavy tests. (cherry picked from commit |
||
|
|
5e0e7a4c6a |
CLI: --help on each subcommand prints its usage and exits 0 (#4538) (#4545)
* claim: #4538 * CLI: --help on each subcommand prints its usage and exits 0 (#4538) Every command now answers `--help` and `-h` with its own usage on stdout and exit 0, the way the top level has since #1828. Before, each subcommand answered differently: `fuzz --help` started a fuzz run with the default seeds and ran until it was stopped, `recipe --help` took the flag for a file name, and `snapshot`, `render`, `oracle`, `run`, `eval`, `script` and `crashes` answered with an error on stderr and exit 1. The help is read before the command runs, so `--help` never starts work: no fuzz run, no MCP server, no file read. `fuzz` also refuses an argument it doesn't take, as `snapshot` already did: a flag it doesn't know and a stray word are errors, not arguments to ignore while a hundred seeds run. The usage lives in one place now: each command's lines are a constant, and the top-level usage is composed from them, so the two cannot drift apart. The top-level usage is unchanged, byte for byte. # Conflicts: # apps/solidcraft-cli/src/main.rs |
||
|
|
0dffb206b1 |
Assembly: ground the first part; drag free joint chains (#2804) (#2805)
* assembly(feat): ground first parts and drag free joint chains Ground the first top-level part when it is created and let face dragging reposition free occurrences or any member of a floating joint chain in one undo step. Preserve exact repeated-placement frames, joint values, modifier selection and Escape cancellation. Keep the accumulated fixture, viewport layout and documentation integration fixes from the existing PR. Signed-off-by: Karl Von Richter<karl@embeint.com> * assembly(fix): update movable fixtures for first-part grounding Accept the documented grounded override in component creation, explicitly free movement fixtures, and keep linked clipboard pastes movable even in an empty document. Cover first and reused linked pastes, default insertion grounding, and single-step undo in the existing link tests. Signed-off-by: Karl Von Richter<karl@embeint.com> * assembly(test): keep the motion-cost crank free Unground the first component in the document-level joint-face measurement fixture so its motion samples can rotate after first-part grounding. Preserve the rotation and shared-measurement assertions that caught the Linux CI failure. Signed-off-by: Karl Von Richter<karl@embeint.com> * assembly(test): free the frame placement fixture Create the frame-member placement fixture ungrounded before moving it above its root sketch. Keep its world-space member assertions while respecting first-part grounding in the frame tests added on main. Signed-off-by: Karl Von Richter<karl@embeint.com> --------- Signed-off-by: Karl Von Richter<karl@embeint.com> |
||
|
|
98c4f335e8 |
Control channel and MCP on by default, with a setting to turn it off (#5561)
The app opens its localhost control channel on port 27878 (or the next free one) unless Preferences > Assistant turns it off; --control and SOLIDCRAFT_CONTROL_PORT still win. A current.port discovery file lets solidcraft-cli mcp find the running app with no arguments. Co-authored-by: Claude Sonnet 5.5 <noreply@anthropic.com> |
||
|
|
e33c371e99 |
Model cache: thin the checkpoints of a design too big for its file instead of leaving the cache out (#3220) (#4882)
* claim: #3220 * Model cache: keep fewer states of a design too big for its file instead of none (#3220) A model cache over the container's budget keeps the final state, then the slowest features' states while the bodies they add fit (a body several states hold counts once), and is left out only when not even the final state fits. Opening evaluates just the features whose state the file left out, each from the state before it, so the model is whole afterwards. * Model cache: keep each encoded body apart, copy only what a cache stores Encoding a model too big for its file no longer copies every distinct body into one buffer before thinning: the payload is copied from the encodings once its size fits, so saving holds no more than before. * Model cache tests: canonical runs in the timeline fixture; rustfmt * Model cache: count the records a thinned cache keeps; always try the final state Thinning counted only the bodies, so a model of many copies of one part (records, not bodies, filling the room) shrank its budget to nothing and saved no cache although its final state fitted. The choice now counts the records of what it keeps, always keeps the final state, and says what it counted, so each retry keeps less and the final state alone is always tried. * docs: a thinned model cache counts its records and always tries the final state * Model cache test: the slowest feature's state holds bodies 16 to 23 * Model cache: thinned opens with fingerprints that read the state before a feature Since #3397 a feature's fingerprint reads where the bodies before it lie. After a state the file left out, adopt takes the saved fingerprint and the evaluation that works the state out checks it. A result evaluated ahead is never taken as one the file left out. The thinned round trips include the placed components' design, whose cut reads those placements. --------- Co-authored-by: MateuszSychXpl <151755914+MateuszSychXpl@users.noreply.github.com> |
||
|
|
dad28abecf |
solidcraft-cli bench-assistant: the standard Assistant model test (#4851) (#4930)
* claim: #4851 * solidcraft-cli bench-assistant: the standard Assistant model test Runs the eleven v1 tasks of #4851 against a desktop app that is already running with a control port. Each task starts a new design and a new chat with All permissions, runs only the prescribed setup, sends the prompt once and waits for the turn. The result is checked on the design (document.inspect with measurements): body count, volume within 1% (0.3% for the fillet), bounding-box size in any orientation, the lowest corner, the body name, live feature kinds, and changed or unchanged content; the volume question is checked on the reply. Failures get the issue's categories from the conversation's items. Prints a table, and writes the issue's comment template (--markdown) and the raw results with each conversation (--json). |
||
|
|
c54b711345 |
CLI: --help prints usage to stdout and exits 0 (#1818) (#1828)
* claim: #1818 * claim: #1818 * fix(cli): --help, -h and help print usage to stdout and exit 0 (#1818) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
93a2922c5e |
Display plans and the model cache for large STEP assemblies (#2814) (#4021)
* STEP import: mesh band faces that wrap around a closed surface correctly Fixes two related bugs that caused SolidCraft to fail to mesh a face wrapping all the way around a closed, non-periodic surface (a revolved ridge band, or a tube-shaped B-spline surface): a missing face, a folded/self-overlapping triangulation, or a hole in the rendered body. 1. Ring edges that run slightly off their surface. STEP files write a surface and the curves bounding it to the file's own declared uncertainty, so a ring edge can legitimately sit a few micrometres off the surface it bounds. The code finding where a ring edge crosses the planned split line compared against the edge's raw (off-surface) point using a hardcoded tolerance far stricter than the file's own precision, rejecting a valid cut. Now matches against the point on the surface directly below the ring crossing, respecting the file's declared tolerance. 2. Closed B-spline surfaces, their slits and their slivers. truck only treats the rotation of a revolved surface as periodic; a face on a B-spline surface whose control net closes on itself (a tube) wasn't recognized as wrapping around at all. This produced a folded face, a hole (a boundary loop landing a full period away from where it should cut), and one near-zero-width sliver face costing the entire body its tessellation plan. Adds periodicity detection for closed B-spline surfaces, period- aware hole-loop alignment, dropping of zero-width slit boundaries, and isolating a too-thin-to-triangulate face so it no longer takes the rest of the body down with it. The GPU shader's periodic wrap mirrors the CPU math so the two don't drift apart. Regression tests: band_faces_split_when_ring_edges_run_off_their_surface, band_face_with_a_zero_width_slit_is_still_meshed, a_sliver_face_too_thin_to_triangulate_does_not_cost_the_body_its_plan. Ablation-tested: disabling either mechanism in (2) reproduces its target test's original failure message while leaving the other test unaffected. * STEP import: mesh the band's split faces, not just split them jyviko asked whether a band wall missing from the interactive app's render was a shading issue or a genuinely missing face. It was missing: the ring- edge split fix made the band's topology correct, but plan_face still produced zero triangles for the two new sub-faces. Two causes, both in plan_face (crates/kernel/src/tess/mod.rs): 1. The tolerance for how far an imported boundary may lie off its surface was tied to the requested mesh's chord tolerance instead of to the body's own size. A finer display tolerance could then reject a boundary a coarser one had just accepted, so the face would drop out exactly when zooming in on it. 2. Near a sharp corner of this flat-panelled band, several boundary points that are legitimately a few micrometres apart (within the STEP file's own declared precision) all projected onto the same surface point. The boundary loop then repeated a point in (u, v), which a triangulator can't follow, so the face's plan failed outright. One face without a plan costs the whole body its plan, and the fallback mesher can't handle a closed B-spline surface either, leaving both halves of the split band with no triangles at all: present in the topology, invisible in every renderer, and absent from the body's volume. Fix: scale the off-surface tolerance to the body's own extent (new Rules::extent), and collapse a run of boundary nodes that land on the same surface point to one (drop_collapsed) before triangulating. Regression test additions to band_faces_split_when_ring_edges_run_off_their_surface: the body's volume now matches the analytic pentagon prism (was a third of it - only the top cap - before this fix); display_plan leaves no face without triangles from coarse to fine tolerance; and the actual tolerance and facet angle the viewport draws with gives the split band its full lateral area on both halves. Confirmed on review_band_big.step, the fixture behind the review screenshots: volume's relative error against the analytic pentagon prism drops from 1.4e-4 to 4.1e-6, and the band wall now occludes the floor grid behind it in a snapshot the same way the top and bottom caps always did. Full kernel suite: 739 tests, 0 failed. * STEP import: hold an imported boundary to the file's own tolerance, not the part's size jyviko: the off-surface acceptance added in the last commit (rules.extent * OFF_SURFACE) scaled with the part, so a 2 m part silently accepted a boundary 2 mm off its surface while a 20 mm copy of the same part accepted only 0.02 mm. A STEP file's own declared uncertainty does not grow with the part, so the bound shouldn't either. Body gains boundary_tol: Option<f64>, Some(file's declared tolerance) for a body read from STEP (crate::step_in::Units::tol, already used by the ring-split fix in split.rs), None for anything this kernel built. It's set before the import's own unmeshed-face check runs, and carried over by the two face-split operations that re-cut an imported surface (splitface.rs, outline.rs), since the file's uncertainty still describes those boundaries afterward. plan_face's accept now reads: the file's own tolerance when the body declares one, or the old chord-tolerance/extent bound otherwise. The old bound's tol * 10.0 term had to go too, not just the extent term: at a 2 m part's typical display tolerance that term alone is ~20 mm, nearly ten times the extent bound jyviko objected to, so keeping it would have left the exact 2 m/2 mm example still silently accepted. Two new tests in step_in/tests.rs: - band_faces_split_when_a_scaled_copy_runs_off_its_surface: the same band fixture at a realistic 2 m scale with the same absolute slop and declared uncertainty as the small one, meshes the same way at every chord tolerance from coarse to fine. - off_surface_budget_follows_the_file_not_the_part_size: the actual regression. The same off-surface error is accepted or refused the same way whether the part is 20 mm or 2 m; a 2 mm error against a 1 µm declared uncertainty is refused at both sizes now (accepted at 2 m under the old bound, refused at 20 mm - that asymmetry was the bug). Checked at both a coarse and a fine display tolerance. Known gap, not fixed here: a STEP-imported body saved into a .solidcraft design and reopened loses boundary_tol (native.rs's decoder has no field to read it from) and falls back to the old extent-based bound on reload. Today's design format has no concept of this value at all; persisting it is a real format change, out of scope for this fix. Full kernel suite: 776 tests, 0 failed. clippy -D warnings clean. * Display plans for STEP threads and pointed ends (#3847) Three faces cost a threaded or pointed STEP part its whole display plan, so it was drawn from the reference mesh: cracked, faceted, and never refined up close. - A loop through a pole (a cone's apex on the boundary) seemed to wind around the surface: the jump at the apex, unwrapped to the nearest copy, was arbitrary. The loop is turned to end where it leaves the pole, so the step that closes it is an ordinary one (`seam::close_through_pole`). - Projection onto a spline with hundreds of spans (a helical flank) restarted from a 16 x 16 grid and settled on another turn; it now starts from two points per span, capped. - Sag refinement no longer inserts a point exactly on a boundary side, which split the side and failed the face. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * tess: a refused face's edges are divided finer and it is planned again (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * tess: sliver faces plan empty; a face no method plans is filled flat from its nodes (#2814) A face whose boundary runs out and back along itself (two edges between the same vertices, a rounding apart, as STEP files write slivers) encloses nothing and is planned with no triangles. A face still refused after its edges are divided finer (a cusp, a sliver whose sides sag across each other, a small cap at a pole) is filled flat from its shared boundary nodes, so the rest of the body keeps its display plan instead of falling back to the reference mesh. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * display mesh tests: a rim the chord tolerance leaves a line is divided again (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * portable B-rep: up to 8192 control points along a spline direction (#2814) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * solidcraft-cli: --debug logs what the engine reports to stderr Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * STEP import: a spline written over a tiny parameter range is read over one (#2814) Some writers parameterize splines over a few millionths (a humanoid robot's edges span 5.4e-6). The kernel tells parameters apart only to 1e-6, so over such a range it evaluated the curve's end wrongly, and trimming an edge to its vertices dropped a control point: the bodies could not be stored exactly and the whole model cache was left out of the design. The knots are now stretched to span one; the curve is the same and edges are trimmed by their vertices, so nothing read from the file refers to the old parameters. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * model cache: a body keeps its file's declared accuracy (#2814) A body restored from the cache dropped the accuracy the file it was read from declares, so the planner held its boundaries to the kernel's own bound and a reopened design drew differently from the import. It is stored with the body's runtime values, and only when there is one. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * tess: a boundary within a hundredth of its body lies on its surface, at every quality (#2814) #1721 held a body read from a file to the accuracy the file declares. A writer declares what it aims for, not a bound its edges keep: a 251-body robot assembly declaring 0.01 µm has boundaries 10 to 30 µm off their surfaces, and 95 of its bodies lost their display plans. The bound is a hundredth of the body again, what Normal quality always allowed, and now the same at every quality, so zooming in still never drops a face (#1721's point). A file declaring more raises it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM * STEP import: keep faces whose edge vertices sit slightly off their curves Some exporters write an edge's vertex beside the end of its curve, further off than the accuracy the file declares (a surface export declares 0.01 mm and puts a vertex 0.19 mm off two spline ends). The reader refused such edges and left the face, and with single-face bodies the body, out. A vertex may now sit up to the file's tolerance or 1/1000 of the model's size (the diagonal around its VERTEX_POINTs), whichever is larger, never more than the existing 1 mm ceiling. Spline and open-conic edges have the end control point moved onto the vertex, so every such edge meets its vertices exactly. The file's declared accuracy still governs closed-curve, seam and circle checks. * tess, io: review clean-ups (#2814) - A sliver face is one whose loops are all slit: drop_slits finds it in the retry after a failed plan, so the pre-check on every face (folded) is gone. - The flat fill uses cdt::triangulate (a lenient fill that leaves out sides crossing one already kept) and its flood-fill inside test, and the plane from geom::Plane. - Refinement only builds its indexes when a face was refused, takes the faces to plan again from edge_faces, and re-samples edges on the pool; Rules::finer for the finer rules. - One PackageWriter::fits for the model cache, the preview and the thumbnail. - The band split's ring tolerance lives in split.rs; comments say what the off-surface bound is now. - The CLI logger prints Level::as_str(). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM --------- Co-authored-by: David Lackovic <lackovicdavid1234@gmail.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Ray <raykholo@users.noreply.github.com> |
||
|
|
9e78e86b92 |
perf: renaming a body evaluates nothing (#3044) (#3095)
A body rename changes names only, but committing it went through the general "design changed" path: the whole timeline was evaluated again. On an imported assembly that means reading the STEP file again and meshing every body (about 100 s on the Prusa Core One, and the same again for undo). When the only change from the previous design is one body rename (the features' stored body names and the body-keyed maps the rename updates), the model now renames the body in its results instead: every body keeps its geometry and meshes, and the fingerprints are set to the renamed design's so the next evaluation reuses everything. Undo and redo of the rename take the same path. A rename the model can't follow that way (the body is changed or named by a later feature, sheet metal, threads) still evaluates the design as before. `bench-open --ops script.json` times commands and their undo on an opened design, with the view work each leaves. Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
e98e065584 |
Open saved designs from the model they were saved with (#3053) (#3102)
* WIP: adopt the saved model on open (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * WIP: tests * WIP: bench-open opens as Open does * docs: opening from the saved model * Tests: an edit after opening evaluates from the feature it changes * clippy * Read SOLIDCRAFT_NO_MODEL_CACHE through the env helper * Open: no picture from the model when the model itself opens; cancel test evaluates * Saved model: bodies passed through found without writing their record; states list runs of bodies * Adopted results go into the evaluation cache: an undone edit, or the marker rolled forward, takes them again * Model cache size guard: the saved model's writer --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
953fd7d5f8 |
Typed parameter contracts and JSON Schemas for solid.box and solid.extrude (#2829) (#2611)
* Spike: typed parameter contracts and JSON Schemas for solid.box and solid.extrude The schema RFC's spike (plan/schema-spike.md). solid.box and solid.extrude get typed contracts with generated JSON Schemas (2020-12), checked in front of the unchanged handlers by a per-session level: off (the default, which changes nothing), warn (the call runs and gains param_warnings) or strict (the call is refused and the design left alone). Also engine.describe and the MCP tool describe_command, `solidcraft-cli mcp --param-check off|warn|strict`, a FeatureResult type for feature replies, and an env-var audit recorder (SOLIDCRAFT_PARAM_AUDIT) used to check the contracts against every test. Local spike branch; not for upstream as is (see the results report). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Parameter contracts: put the audit recorder behind a feature; drop two ignored test keys The audit recorder is now on only in a build with the engine's `param-audit` feature and `SOLIDCRAFT_PARAM_AUDIT` set. Its code is still compiled, linted and tested without the feature. `scripts/param_audit.py` summarises a test run's audit logs, and the schema module's docs give the steps for converting a further command. Two tests passed keys their command ignores, which the audit found: `position` on `solid.box` (`hole_face_tests.rs`) and `symmetric` on `solid.extrude` (`face_tests.rs`). Both are removed, so the tests build what they always did. Comments no longer call the contracts a spike. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
d0afc31632 |
Save the evaluated model with every design: exact, stored once, scaled caps (#3053) (#3093)
* Model cache written by default: exact bodies, stored once, scaled caps (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * bench-open: say why bodies were not kept * Exact planes and revolutions; budgets for large bodies (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Native B-rep: rebuild shells as the kernel made them (closed and seam edges) (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * docs: the model cache and the exact native B-rep (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * bench-open: time a save without the cache too * Model cache entries are Deflate-compressed (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Model cache: one that does not fit the design file is left out, never a failed save (#3053) Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
803ae6d5be |
Script replay keeps a feature name another feature has (#1990) (#1997)
A sketch and the feature built from it may share a name, and the sample and oracle designs do. `timeline.add` refused such a recorded name, so a design's own exported script failed to replay. `Document::insert_feature` now keeps the name, as `add_feature` does; a blank name still gets a fresh one. Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
31b41978fc |
Construction geometry on model vertices follows them when a parameter moves them (#568) (#2409)
Thanks @rlartot. |
||
|
|
26f42ae09b |
Snapshot: draw a see-through appearance see-through, and show a tool body inside its target (#2329) (#2330)
* Snapshot: draw a see-through appearance see-through, and give the CLI --body, --tool and --section A headless picture dropped a body's opacity: the scene carried only a colour, so a design with a translucent appearance was drawn opaque by `solidcraft-cli snapshot`, by MCP screenshots and in a design's thumbnail, although the window has always drawn it as glass. There was then no way to look at the body a cut would remove inside the material it meets: only a volume to measure and reason about, which hides exactly the errors a picture makes obvious (a tool that stops short, or lands in the wrong place). - `SceneMesh` carries the body's opacity; `view::build_scene` takes it from the design (`model_body_opacity`), and a selected body stays solid so the selection colour reads. - The GPU capture routes a see-through body into the scene's glass at its own alpha, as the viewport does; the CPU rasterizer draws the solid bodies first (they own the depth buffer), then the see-through ones blended over them, far sides before near sides and without writing depth, so what lies inside shows and a line between the two is not hidden. - `snapshot --body NAME:opacity=0.3,color=#rrggbb`, `--tool NAME` (that body solid in the tool colour, the rest see-through) and `--section z=27` run the commands the app itself runs (`appearance.assign`, `inspect.section`): the options are shortcuts, not a second renderer. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Tests: measure the tool colour as it is drawn through a see-through target The tool-colour filter was derived on paper and demanded a red more than twice either other channel, which the target in front of it tints away (measured: (200, 108, 85) through opacity 0.3); and the colour check painted the tool, which a solid target hides. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * fmt * Snapshot options: strip the colour's # rather than slicing it; README Slicing `value[1..]` on an input-derived string is what the house rules ask us not to write, even where a length check has already made it safe. The error a failed assignment reports now names the body rather than claiming it came from --body, since --tool reaches it too. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * --tool: assign the bodies around the tool in groups, not one command at a time Each appearance.assign is an undo step with a document snapshot behind it, so one per body made --tool cost grow with the size of the design for no reason: the bodies around the tool all get the same opacity, and the ones that share a colour can be named in one call. A design whose bodies all wear the default grey now costs two commands whatever its size. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> * Rasterizer: say where its glass and the GPU's differ Splitting each see-through body by facing orders its own two layers; it does not sort across bodies, which the GPU does. Worth stating rather than leaving a reader to find it. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
6f93e7a851 |
fix(examples): cut both mounting holes in the bracket (#1515)
Co-authored-by: bherbruck <brennen.herbruck@gmail.com> |
||
|
|
f3505f0db6 |
World placement on all cores (#3053) (#3123)
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |
||
|
|
7ad5130cd2 |
refactor: geom::UnitVec3 for unit axes and normals (#2603)
* geom: UnitVec3; a face's analytic axes and normals are unit by type Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * geom: UnitVec3 adds to and subtracts from a Vec3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * kernel, doc, engine: cylinder axes and measured normals held as UnitVec3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * kernel, engine: functions that take a unit axis or direction say so by type Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * doc: a face's normal goes to Plane::from_normal as is Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * kernel, doc: main's new cylinder helpers take the face's axis as a UnitVec3 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com> |