Documentation site and CI workflows
An mdBook under docs/book: a user guide (getting started, UI tour, sketching, features, parameters, components and joints, sheet metal, plastic, files, shortcuts, MCP) and a developer guide (CONTRIBUTING, architecture, command engine, kernel boundary, persistent naming, test harnesses, and the existing docs/*.md pages). `cargo xtask book` generates the command reference from `solvecraft-cli commands` and renders the screenshots with `solvecraft-cli snapshot`, then runs mdbook. .github/workflows/pages.yml publishes the book at /solvecraft/ and the web app at /solvecraft/app/ (skipped while the repository is private). .github/workflows/ci.yml runs `cargo xtask ci` on pull requests. README and Help → Documentation link to the book. Fixes #28 Fixes #8 Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
2c3fec087e
commit
0d7e456bc1
35 files changed
+792
-5
No files matched your search
@@ -0,0 +1,2 @@
|
||||
/src/generated/
|
||||
/src/reference/commands.md
|
||||
@@ -0,0 +1,29 @@
|
||||
[book]
|
||||
title = "SolveCraft"
|
||||
description = "An open-source parametric 3D CAD application in pure Rust: user guide and developer guide."
|
||||
authors = ["SolveCraft contributors"]
|
||||
language = "en"
|
||||
src = "src"
|
||||
|
||||
[build]
|
||||
build-dir = "../../target/book"
|
||||
create-missing = false
|
||||
|
||||
[output.html]
|
||||
git-repository-url = "https://github.com/bherbruck/solvecraft"
|
||||
edit-url-template = "https://github.com/bherbruck/solvecraft/edit/main/docs/book/{path}"
|
||||
site-url = "/solvecraft/"
|
||||
no-section-label = false
|
||||
|
||||
[output.html.search]
|
||||
enable = true
|
||||
|
||||
[output.html.redirect]
|
||||
# Pages included from the repository (CONTRIBUTING.md, docs/*.md) keep their repository-relative
|
||||
# links; these send them to the right place.
|
||||
"/dev/mcp.html" = "../guide/mcp.html"
|
||||
"/dev/docs/oracle.html" = "../oracle.html"
|
||||
"/dev/README.html" = "https://github.com/bherbruck/solvecraft/blob/main/README.md"
|
||||
"/dev/ATTRIBUTION.html" = "https://github.com/bherbruck/solvecraft/blob/main/ATTRIBUTION.md"
|
||||
"/dev/AGENTS.html" = "https://github.com/bherbruck/solvecraft/blob/main/AGENTS.md"
|
||||
"/dev/ROADMAP.html" = "https://github.com/bherbruck/solvecraft/blob/main/ROADMAP.md"
|
||||
@@ -0,0 +1,7 @@
|
||||
{"commands": [
|
||||
{"command": "solid.box", "params": {"length": 70, "width": 45, "height": 25, "body_name": "Enclosure"}},
|
||||
{"command": "solid.fillet", "params": {"edges": [[0, 0, 12], [70, 0, 12], [70, 45, 12], [0, 45, 12]], "radius": 6}},
|
||||
{"command": "solid.shell", "params": {"faces": [[35, 22, 25]], "thickness": 2}},
|
||||
{"command": "plastic.boss", "params": {"position": [12, 12, 2], "diameter": 7, "height": 14, "hole_diameter": 2.5}},
|
||||
{"command": "plastic.boss", "params": {"position": [58, 33, 2], "diameter": 7, "height": 14, "hole_diameter": 2.5}}
|
||||
]}
|
||||
@@ -0,0 +1,11 @@
|
||||
{"commands": [
|
||||
{"command": "sketch.create", "params": {"plane": "XZ", "name": "Section"}},
|
||||
{"command": "sketch.line", "params": {"points": [[6, 0], [30, 0], [30, 4], [12, 4], [12, 20], [6, 20]], "closed": true}},
|
||||
{"command": "sketch.finish", "params": {}},
|
||||
{"command": "solid.revolve", "params": {"axis": "Z", "body_name": "Hub"}},
|
||||
{"command": "sketch.create", "params": {"plane": "XY", "name": "Bolt holes"}},
|
||||
{"command": "sketch.circle.center", "params": {"center": [22, 0], "diameter": 5}},
|
||||
{"command": "sketch.finish", "params": {}},
|
||||
{"command": "solid.extrude", "params": {"distance": 4, "operation": "cut", "name": "Bolt hole"}},
|
||||
{"command": "solid.pattern.circular", "params": {"features": ["Bolt hole"], "axis": "Z", "count": 6}}
|
||||
]}
|
||||
@@ -0,0 +1,9 @@
|
||||
{"commands": [
|
||||
{"command": "sheet.manage_rules", "params": {"name": "Steel 1.5", "thickness": "1.5 mm", "bend_radius": "1.5 mm", "k_factor": 0.44, "active": true}},
|
||||
{"command": "sketch.create", "params": {"plane": "XY", "name": "Base"}},
|
||||
{"command": "sketch.rectangle.two_point", "params": {"p0": [0, 0], "p1": [80, 50]}},
|
||||
{"command": "sketch.finish", "params": {}},
|
||||
{"command": "sheet.flange", "params": {"type": "base"}},
|
||||
{"command": "sheet.flange", "params": {"edges": [[40, 0, 1.5]], "height": 20}},
|
||||
{"command": "sheet.flange", "params": {"edges": [[40, 50, 1.5]], "height": 20}}
|
||||
]}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Summary
|
||||
|
||||
[Introduction](introduction.md)
|
||||
|
||||
# User guide
|
||||
|
||||
- [Getting started](guide/getting-started.md)
|
||||
- [A tour of the window](guide/ui-tour.md)
|
||||
- [Sketching and constraints](guide/sketching.md)
|
||||
- [Solid features](guide/features.md)
|
||||
- [Parameters and expressions](guide/parameters.md)
|
||||
- [Components and joints](guide/assemblies.md)
|
||||
- [Sheet metal](guide/sheet-metal.md)
|
||||
- [Plastic parts](guide/plastic.md)
|
||||
- [Import and export](guide/files.md)
|
||||
- [Keyboard shortcuts](guide/shortcuts.md)
|
||||
- [Driving SolveCraft with an AI agent (MCP)](guide/mcp.md)
|
||||
|
||||
# Developer guide
|
||||
|
||||
- [Contributing](dev/contributing.md)
|
||||
- [Architecture](dev/architecture.md)
|
||||
- [The command engine](dev/commands.md)
|
||||
- [The kernel boundary and truck](dev/kernel.md)
|
||||
- [Persistent naming](dev/naming.md)
|
||||
- [Test harnesses](dev/testing.md)
|
||||
- [Control protocol](dev/control-protocol.md)
|
||||
- [Fusion oracle](dev/oracle.md)
|
||||
- [Command parity](dev/parity.md)
|
||||
- [STEP import](dev/step-import.md)
|
||||
|
||||
# Reference
|
||||
|
||||
- [Command reference](reference/commands.md)
|
||||
@@ -0,0 +1,22 @@
|
||||
# Architecture
|
||||
|
||||
SolveCraft is a Cargo workspace in layers. A crate only depends on crates in lower layers, and
|
||||
`cargo xtask layers` fails the build otherwise.
|
||||
|
||||
{{#include ../../../../README.md:architecture}}
|
||||
|
||||
The web app, `apps/solvecraft-web`, is the desktop front end compiled to wasm with
|
||||
[trunk](https://trunkrs.dev). `xtask` holds the repository's own tooling: `cargo xtask ci`,
|
||||
`layers`, `assets`, `oracle`, `parity`, `step-corpus` and `book`.
|
||||
|
||||
A few rules follow from the layering:
|
||||
|
||||
- **Only `crates/kernel` touches truck.** Everything above it sees SolveCraft's own types:
|
||||
bodies, faces, edges, meshes and measures. See [The kernel boundary](kernel.md).
|
||||
- **The document knows nothing about commands or the UI.** `crates/doc` holds the parameters,
|
||||
the feature timeline and the component tree, and evaluates them into a model.
|
||||
- **Everything the user can do is a command** in `crates/engine`. See
|
||||
[The command engine](commands.md).
|
||||
- **The front end is swappable.** Nothing below `ui-egui` depends on egui. The CLI and the MCP
|
||||
server run the same engine without a window, and `crates/render` has a CPU rasterizer so
|
||||
headless screenshots work anywhere.
|
||||
@@ -0,0 +1,38 @@
|
||||
# The command engine
|
||||
|
||||
Every user-visible action is a **command**: a `CommandSpec` registered in
|
||||
`crates/engine/src/cmd/`, with a dotted, lower-case id (`solid.extrude`, `sketch.create`,
|
||||
`timeline.rollback`). The toolbar, dialogs, marking menu, S box, scripts, the CLI, the control
|
||||
channel and MCP all run commands through `Session::execute(id, params)`. Commands take JSON
|
||||
parameters and never open dialogs; a dialog is a front-end form that builds the parameters.
|
||||
|
||||
```rust
|
||||
CommandSpec::new("solid.fillet", "Fillet", fillet)
|
||||
.at("SOLID", "MODIFY") // toolbar tab and panel ("" = not on the toolbar)
|
||||
.icon("fillet") // drawn in code, crates/ui-egui/src/icons.rs
|
||||
.key("F") // default shortcut
|
||||
.params("edges: [[x,y,z] | {body, index}]; radius: expr; …"),
|
||||
```
|
||||
|
||||
`run` is `fn(&mut Session, &Value) -> Result<Value>`, and `enabled` is
|
||||
`fn(&Session) -> Result<(), String>`; the error string is the disabled-button tooltip. The
|
||||
`params` string is the one-line documentation shown by `solvecraft-cli commands`, MCP's
|
||||
`list_commands` and the [command reference](../reference/commands.md).
|
||||
|
||||
A command that changes the design is undoable by default: the session snapshots the document
|
||||
before it runs, and a failing command leaves the document unchanged. Feature commands add a
|
||||
feature to the timeline and let the document evaluate it; they validate their inputs first
|
||||
(units, ranges, references) and return `BadParams` instead of building a broken feature.
|
||||
|
||||
Ids used before the 2026-10 rename still resolve through `crates/engine/src/legacy_ids.rs`, so
|
||||
old scripts, recipes, saved shortcuts and toolbar layouts keep working.
|
||||
|
||||
## Adding a command
|
||||
|
||||
1. Add a `CommandSpec` to the right file in `crates/engine/src/cmd/` and implement `run`.
|
||||
2. Write engine tests that measure the result: volume, area, and face/edge/vertex counts
|
||||
against values you can derive by hand.
|
||||
3. The hostile-input test (`hostile_params_never_panic` in `crates/engine/src/tests.rs`) runs
|
||||
your command automatically with every documented parameter set to junk. It must return
|
||||
errors, never panic.
|
||||
4. For UI work, add a scenario (see [Test harnesses](testing.md)).
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../../CONTRIBUTING.md}}
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../control-protocol.md}}
|
||||
@@ -0,0 +1,37 @@
|
||||
# The kernel boundary and truck
|
||||
|
||||
`crates/kernel` is SolveCraft's B-rep kernel. It wraps
|
||||
[truck](https://github.com/ricosjp/truck) (Apache-2.0) for topology, NURBS geometry, booleans,
|
||||
tessellation and STEP parsing, and it is the only crate allowed to use truck. Callers get
|
||||
SolveCraft types (`Body`, face and edge indices, meshes, measures) and a
|
||||
`KernelError` instead of truck types and panics.
|
||||
|
||||
## `guard`
|
||||
|
||||
truck can panic on geometry it doesn't handle. Every call into it goes through
|
||||
`solvecraft_kernel::guard`, which catches the panic and turns it into
|
||||
`KernelError::Internal`, leaving the model unchanged:
|
||||
|
||||
```rust
|
||||
pub fn guard<T>(what: &str, f: impl FnOnce() -> Result<T>) -> Result<T>
|
||||
```
|
||||
|
||||
A failing feature shows an error on the timeline; it never takes the app down.
|
||||
|
||||
## What is our own
|
||||
|
||||
truck has no fillets, chamfers, shells or face edits, so these are SolveCraft code in the
|
||||
kernel: constant, chord and variable-radius fillets with corner blends, chamfers, shell and
|
||||
offset, Delete Face, Split Face, Replace Face, sewing, STEP and IGES reading and writing beyond
|
||||
truck's parser, and face provenance (which input face each output face came from, for
|
||||
[persistent naming](naming.md)).
|
||||
|
||||
## Vendored truck crates
|
||||
|
||||
Patched copies of `truck-shapeops`, `truck-stepio` and `truck-meshalgo` live in `vendor/`,
|
||||
wired in with `[patch.crates-io]`. The patches fix robustness bugs found by our tests and the
|
||||
STEP corpus. `vendor/` is excluded from our fmt and clippy rules, and each patch should go
|
||||
upstream when it can.
|
||||
|
||||
Some truck assertions only run in debug builds and can fail on valid geometry, so tests and CI
|
||||
run with `--release`.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Persistent naming
|
||||
|
||||
A fillet stores the edges it rounds, and a sketch stores the face it sits on. If those were face
|
||||
and edge *indices*, an upstream edit that adds a face would move the fillet to the wrong edge.
|
||||
SolveCraft stores **names** instead (`crates/doc/src/naming.rs`):
|
||||
|
||||
- A face of an evaluated body is named after how it was made. A face lying on a face of the
|
||||
feature's input keeps that face's name; a face new to the feature is named by its role:
|
||||
`F<feature>:side:<sketch curve>`, `F<feature>:start` and `:end`, `F<feature>:blend:<k>` and
|
||||
so on.
|
||||
- Pieces of a split face get `#1`, `#2`, … in order along the longest axis.
|
||||
- An edge is named by the two faces it separates.
|
||||
- Pattern and mirror copies are named after their sources plus the instance.
|
||||
|
||||
Names are computed lazily, the first time something asks, from the body, the feature that made
|
||||
it and the model just before that feature. Face provenance from the kernel (which input face an
|
||||
output face came from) does most of the work.
|
||||
|
||||
When a feature evaluates, each stored reference is resolved by name. If no face has the name
|
||||
any more, the reference falls back to the geometry it recorded (a point on the face, a normal),
|
||||
and the feature shows a warning so the user can check it. A reference that matches nothing is
|
||||
an error, never a guess.
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../oracle.md}}
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../parity.md}}
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../step-import.md}}
|
||||
@@ -0,0 +1,40 @@
|
||||
# Test harnesses
|
||||
|
||||
`cargo xtask ci` runs everything a pull request must pass: fmt, clippy with `-D warnings`, the
|
||||
tests in release mode, `xtask layers`, `xtask assets` and the wasm build check.
|
||||
|
||||
| Harness | Where | What it catches |
|
||||
|---|---|---|
|
||||
| Unit and engine tests | next to the code, `*_tests.rs` | measured results: volume, area, topology counts against derived values |
|
||||
| Hostile input | `hostile_params_never_panic`, `crates/engine/src/tests.rs` | every command × every documented parameter × junk values: errors, never panics |
|
||||
| Sketch fuzz | `crates/engine/src/cmd/sketch_fuzz_tests.rs` | random sketches through the solver and profile finder |
|
||||
| UI scenarios | `crates/ui-egui/tests/scenarios/*.json` | the real app, headless: clicks, keys, drags, assertions |
|
||||
| Layout tests | `crates/ui-egui/tests/ui_layout.rs`, `window_widths.rs` | panels and dialogs at every window width |
|
||||
| Design-file corpus | `apps/solvecraft-cli/tests/corpus` | every saved file version still opens and evaluates the same |
|
||||
| Kill mid-save | `apps/solvecraft-cli/tests/kill_mid_save.rs` | a save killed at any moment leaves a readable file |
|
||||
| Fusion oracle | `cargo xtask oracle` → [docs/oracle.md](oracle.md) | parts rebuilt from recipes, compared with Fusion's measurements |
|
||||
| STEP corpus | `cargo xtask step-corpus` → [docs/step-import.md](step-import.md) | STEP files from Fusion opened and measured |
|
||||
|
||||
## UI scenarios
|
||||
|
||||
A scenario is a JSON list of steps run against the real app with a headless egui context:
|
||||
|
||||
```json
|
||||
[
|
||||
{"start": "sketch.create"},
|
||||
{"click": {"plane": "XY"}},
|
||||
{"start": "sketch.rectangle.two_point"},
|
||||
{"click": {"sketch": [0, 0]}},
|
||||
{"click": {"sketch": [40, 30]}},
|
||||
{"expect": {"errors": 0}}
|
||||
]
|
||||
```
|
||||
|
||||
A new file in `crates/ui-egui/tests/scenarios/` is picked up automatically. To record a bug
|
||||
before it's fixed, add a `{"pending": "why"}` step; its test is then ignored with that reason, and
|
||||
the fix removes the step.
|
||||
|
||||
## Release mode
|
||||
|
||||
CI runs the tests with `--release`, because some truck assertions only exist in debug builds
|
||||
and fail on valid geometry. If a test fails only in debug, say so in the PR.
|
||||
@@ -0,0 +1,22 @@
|
||||
# Components and joints
|
||||
|
||||
A design is a tree of **components**. **New Component** (`component.create`) adds one, and
|
||||
**Create Components from Bodies** (`component.from_bodies`) turns bodies into components. Each
|
||||
component has its own origin, bodies, sketches and timeline entries. The **active component**
|
||||
(the radio button in the browser) receives new sketches and features; the others are drawn
|
||||
faded.
|
||||
|
||||
A component is placed by its **occurrences**. Paste creates another instance of the same
|
||||
component, and **Paste New** creates an independent copy. Move an occurrence with the move
|
||||
triad, then **Capture Position** to keep it or **Revert** to put it back. SolveCraft asks before
|
||||
the next command if a move wasn't captured. **Ground** fixes an occurrence in place.
|
||||
|
||||
**Joints** (`joint.create`, J) connect two components by joint origins that snap to faces, edges,
|
||||
circles and vertices: rigid, revolute, slider, cylindrical, pin-slot, planar and ball, with
|
||||
offsets, flip and limits. **As-built Joint** keeps the current position, **Rigid Group** locks
|
||||
components together, **Drive Joints** moves a joint through its values, and **Motion Link**
|
||||
couples two joints. Contact sets stop motion where bodies would pass through each other,
|
||||
**Motion Study** keys joint values along a timeline, and **Interference** shows overlapping
|
||||
volumes in red.
|
||||
|
||||
STEP export writes the component tree as an assembly.
|
||||
@@ -0,0 +1,24 @@
|
||||
# Solid features
|
||||
|
||||
Features live on the **timeline** and rebuild incrementally from the first one that changed.
|
||||
Each one can be edited (double-click), suppressed, renamed, reordered (if nothing it depends on
|
||||
moves after it), rolled back to, and deleted. Deleting asks first when other features depend on
|
||||
it.
|
||||
|
||||
| Panel | Features |
|
||||
|---|---|
|
||||
| Create | extrude (one side, two sides, symmetric, taper, start offset, to a distance or through all; new body, join, cut, intersect), revolve, sweep, loft, box, cylinder, sphere, torus, coil, pipe, rib, web, emboss, hole (simple, counterbore, countersink, tapped; on faces or at sketch points), thread, rectangular/circular/path patterns, mirror |
|
||||
| Modify | press pull, fillet, chamfer, shell, draft, scale, combine, split body, offset face, replace face, move/copy, align, remove |
|
||||
| Construct | offset plane, plane at angle |
|
||||
| Inspect | measure, section analysis, interference, curvature comb and map, zebra, draft, minimum radius, isocurves, centre of mass |
|
||||
|
||||
Fillets and chamfers handle straight edges between planar faces, whole smooth loops, runs of
|
||||
neighbouring edges with mitred or spherical corners, and closed chains of curved edges (a rolling
|
||||
ball). See the roadmap's known limitations for the rest.
|
||||
|
||||
Feature references to faces and edges are stored by name, so an upstream edit that moves geometry
|
||||
keeps them on the right face (see [Persistent naming](../dev/naming.md)). When a reference can't
|
||||
be found, the feature warns instead of silently picking another face.
|
||||
|
||||
Press **Delete** on anything selected (bodies, faces, sketches, features, planes, components,
|
||||
canvases). It runs as one undoable step and lists the features that would go with it or fail.
|
||||
@@ -0,0 +1,19 @@
|
||||
# Import and export
|
||||
|
||||
| Format | Read | Write |
|
||||
|---|---|---|
|
||||
| `.solvecraft` (JSON design, versioned) | yes | yes |
|
||||
| STEP (AP203, AP214, AP242) | solids, assemblies, units, names, colours | AP242 with names, colours and the component tree |
|
||||
| IGES 5.3 | manifold solids, or trimmed surfaces sewn into solids | manifold solids with names and colours |
|
||||
| 3MF, STL, OBJ | mesh bodies | yes |
|
||||
| DXF, SVG | into a sketch | sketches and flat patterns as DXF |
|
||||
| PNG, JPEG | canvases and decals | |
|
||||
|
||||
Opening a STEP or IGES file creates a design with the file's bodies as a base feature, and
|
||||
inserting one adds them to the current design. Later features build on them. Mesh bodies render,
|
||||
measure, move and export, but solid features need B-rep bodies.
|
||||
|
||||
Saves are atomic: a crash at any moment leaves either the old file or the new one, and the
|
||||
replaced version is kept as `<file>.bak`. Unsaved changes are autosaved to a recovery folder,
|
||||
and the next launch offers to recover them. Older design files are upgraded on open, and files
|
||||
from a newer version are refused with a message.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Getting started
|
||||
|
||||
## Desktop
|
||||
|
||||
Download the latest build from the
|
||||
[releases page](https://github.com/bherbruck/solvecraft/releases), or build it yourself with
|
||||
stable Rust (1.90 or newer):
|
||||
|
||||
```sh
|
||||
git clone https://github.com/bherbruck/solvecraft && cd solvecraft
|
||||
cargo run --release -p solvecraft -- --sample # opens with a sample part
|
||||
```
|
||||
|
||||
`solvecraft part.step` opens a STEP, IGES, 3MF, STL or OBJ file as a new design, and
|
||||
`solvecraft design.solvecraft` opens a saved design. Windows builds cross-compile from Linux with
|
||||
`cargo xwin build --release --target x86_64-pc-windows-msvc -p solvecraft`.
|
||||
|
||||
## Web
|
||||
|
||||
The same app runs in the browser: [open SolveCraft on the web](../app/) (`?sample` opens the sample
|
||||
part, `?webgl` forces WebGL2 where WebGPU is missing). Designs are saved in the browser's private
|
||||
file storage, which needs HTTPS or localhost. To build it yourself:
|
||||
|
||||
```sh
|
||||
rustup target add wasm32-unknown-unknown
|
||||
cd apps/solvecraft-web && trunk serve --release
|
||||
```
|
||||
|
||||
## CLI
|
||||
|
||||
`solvecraft-cli` runs the same commands without a window:
|
||||
|
||||
```sh
|
||||
cargo run --release -p solvecraft-cli -- commands # every command, as JSON
|
||||
cargo run --release -p solvecraft-cli -- run examples/bracket.json --out bracket.step
|
||||
cargo run --release -p solvecraft-cli -- eval examples/bracket.json # volume, area, faces…
|
||||
cargo run --release -p solvecraft-cli -- snapshot examples/bracket.json --out bracket.png
|
||||
cargo run --release -p solvecraft-cli -- exec solid.box '{"length": 20, "width": 10, "height": 5}'
|
||||
```
|
||||
|
||||
A script is a list of commands:
|
||||
|
||||
```json
|
||||
{"commands": [
|
||||
{"command": "sketch.create", "params": {"plane": "XY"}},
|
||||
{"command": "sketch.rectangle.two_point", "params": {"p0": [0, 0], "p1": [40, 30]}},
|
||||
{"command": "sketch.finish", "params": {}},
|
||||
{"command": "solid.extrude", "params": {"distance": 20}},
|
||||
{"command": "solid.fillet", "params": {"edges": [[0, 0, 10]], "radius": 3}}
|
||||
]}
|
||||
```
|
||||
|
||||

|
||||
|
||||
Units are millimetres and degrees unless an expression says otherwise (`"1 in"`, `"30 deg"`),
|
||||
and Z is up.
|
||||
@@ -0,0 +1 @@
|
||||
{{#include ../../../mcp.md}}
|
||||
@@ -0,0 +1,21 @@
|
||||
# Parameters and expressions
|
||||
|
||||
Every dimension and feature input is a **model parameter** (`d1`, `d2`, …). **User parameters**
|
||||
are ones you add yourself, with a unit, an expression and an optional comment. Change them in
|
||||
**Change Parameters** (`parameters.change`). The timeline rebuilds from the first feature that
|
||||
uses them.
|
||||
|
||||
Expressions are unit-aware: `2 * width + 5 mm`, `angle / 2`, `sqrt(area)`, `1 in + 3 mm`, using
|
||||
`+ - * / ^`, parentheses, `sin cos tan asin acos atan atan2 sqrt abs min max floor ceil round mod
|
||||
trunc` and unit conversion. A length where an angle is expected (or the other way round) is an
|
||||
error, not a silent conversion. Cycles are reported with their path (`a → b → a`), renaming a
|
||||
parameter updates every expression, dimension and feature input that uses it, and a parameter
|
||||
in use can't be deleted (the error lists its users).
|
||||
|
||||
The design's units (Document Settings in the browser: mm, cm, m, in or ft) set how a bare number
|
||||
typed into a feature is read. In an inch design `2` means 2 in. Changing the units never moves
|
||||
existing geometry.
|
||||
|
||||
Parameters export to and import from CSV or JSON (`parameters.export`, `parameters.import`).
|
||||
**Configurations** (`config.*`) keep a table of rows, each with its own parameter values and
|
||||
suppressed features, switched with `config.activate`.
|
||||
@@ -0,0 +1,13 @@
|
||||
# Plastic parts
|
||||
|
||||
The PLASTIC tab has a small enclosure subset:
|
||||
|
||||
- **Boss** (`plastic.boss`): screw bosses with a hole, fillets and optional ribs.
|
||||
- **Lip / Groove** (`plastic.lip`): the mating lip and groove along a shell's opening.
|
||||
- **Snap Fit** (`plastic.snap_fit`): a cantilever snap hook and its catch.
|
||||
- **Rest** (`plastic.rest`): a pad for a part to rest on.
|
||||
- **Plastic Rules** (`plastic.manage_rules`, `plastic.assign_rule`): wall thickness, draft and
|
||||
clearance per material, used as the features' defaults.
|
||||
|
||||
Rib and web (on the SOLID tab) complete the set. These features are checked against
|
||||
hand-computed geometry rather than a Fusion oracle.
|
||||
@@ -0,0 +1,15 @@
|
||||
# Sheet metal
|
||||
|
||||
The SHEET METAL tab builds parts from a sheet of constant thickness under a **sheet metal rule**
|
||||
(thickness, bend radius, K-factor), set in **Sheet Metal Rules** (`sheet.manage_rules`).
|
||||
|
||||
- **Flange** (`sheet.flange`): a base flange from a sketch profile, a contour flange from an open
|
||||
sketch, or an edge flange from a part edge.
|
||||
- **Hem** (`sheet.hem`) and **Fold** (`sheet.fold`) along a sketch line.
|
||||
- **Unfold / Refold** (`sheet.unfold`, `sheet.refold`) for working on the flat part.
|
||||
- **Convert** (`sheet.convert`) turns a solid of constant thickness into sheet metal.
|
||||
- **Create Flat Pattern** (`sheet.flat_pattern`) shows the flat part with its bend lines and a
|
||||
bend table, and exports it as DXF.
|
||||
|
||||
Bends follow the rule's K-factor, so flat lengths match what a press brake will make. The
|
||||
oracle checks these against parts built in Fusion.
|
||||
@@ -0,0 +1,29 @@
|
||||
# Keyboard shortcuts
|
||||
|
||||
Command shortcuts can be changed in File › Keyboard Shortcuts; these are the defaults.
|
||||
|
||||
| Key | Command | Key | Command |
|
||||
|---|---|---|---|
|
||||
| L | Line | E | Extrude |
|
||||
| R | Two-Point Rectangle | Q | Press Pull |
|
||||
| C | Center Diameter Circle | F | Fillet |
|
||||
| D | Sketch Dimension | H | Hole |
|
||||
| X | Construction | M | Move/Copy |
|
||||
| O | Offset | J | Joint |
|
||||
| T | Trim | I | Measure |
|
||||
| P | Project | A | Appearance |
|
||||
| Ctrl+Z | Undo | Ctrl+Y | Redo |
|
||||
| Ctrl+N | New Design | Ctrl+O | Open |
|
||||
| Ctrl+S | Save | Delete | Delete the selection |
|
||||
|
||||
Keys handled by the window itself:
|
||||
|
||||
| Key | Action |
|
||||
|---|---|
|
||||
| S | the S box: search every command at the cursor |
|
||||
| V | show or hide the selected bodies, sketches and planes |
|
||||
| F2 | rename the selected browser or timeline item |
|
||||
| F6 | fit the view to the model |
|
||||
| Esc | cancel the running command, or clear the selection |
|
||||
|
||||
Help › Keyboard Shortcuts in the app lists the current bindings, including any you changed.
|
||||
@@ -0,0 +1,34 @@
|
||||
# Sketching and constraints
|
||||
|
||||
A sketch lies on a plane: an origin plane, a construction plane or a planar face. Start one with
|
||||
**Create Sketch** (`sketch.create`) and click a plane, or pick a face first. **Finish Sketch**
|
||||
returns to the model.
|
||||
|
||||
## Geometry
|
||||
|
||||
Lines and polylines (L), rectangles (two-point R, three-point, centre), circles (centre C,
|
||||
two-point, three-point, tangent), arcs (three-point, centre, tangent), polygons, slots, ellipses,
|
||||
fit-point and control-point splines, conics, points and text. **Construction** (X) turns curves
|
||||
into reference geometry that doesn't form profiles. Modify tools include trim (T), extend, break,
|
||||
fillet, chamfer, offset (O), mirror, patterns, move/copy and scale.
|
||||
|
||||
**Project** (P) and **Intersect** bring model edges into the sketch as linked geometry that
|
||||
follows later changes. Sketching on a face projects its edges automatically.
|
||||
|
||||
## Constraints and dimensions
|
||||
|
||||
The solver is SolveCraft's own (damped Gauss–Newton with degree-of-freedom analysis). Constraints:
|
||||
coincident, horizontal/vertical, parallel, perpendicular, tangent, equal, concentric, collinear,
|
||||
midpoint, symmetry, fix, curvature (G2) and polygon. **Sketch Dimension** (D) adds linear,
|
||||
aligned, horizontal, vertical, radius, diameter and angle dimensions. Each is a parameter
|
||||
(`d1`, `d2`, …), so it can hold an expression.
|
||||
|
||||
Under-constrained geometry is blue and fully constrained geometry turns dark, and the status
|
||||
shows the remaining degrees of freedom. A constraint or dimension that would over-constrain the
|
||||
sketch is refused rather than applied. Drag a point to move it; the solver keeps every
|
||||
constraint while you drag.
|
||||
|
||||
## Profiles
|
||||
|
||||
Closed loops become profiles automatically, including regions split by crossing lines and
|
||||
islands inside outlines. Extrude, revolve, sweep and loft pick profiles.
|
||||
@@ -0,0 +1,29 @@
|
||||
# A tour of the window
|
||||
|
||||

|
||||
|
||||
- **Title bar.** On Windows and Linux the application bar is the window's title bar: File, save,
|
||||
undo and redo, the start page, the theme, Help, and one tab per open design (each with its own
|
||||
undo history, selection and camera).
|
||||
- **Toolbar.** The workspace switcher (DESIGN) sits on the left. The tabs (SOLID, SURFACE,
|
||||
SHEET METAL, PLASTIC, UTILITIES, and SKETCH while you sketch) hold panels of commands. Click a
|
||||
panel's name for all its commands.
|
||||
- **Browser** (left). The design as a tree: document settings and units, named views, the
|
||||
origin, bodies, sketches, construction planes, canvases, joints and components. The eye shows or
|
||||
hides an item, a component's radio button makes it the active component, and right-clicking any
|
||||
row gives that item's menu. Rows drag into groups and other components.
|
||||
- **Viewport.** Click to select, Shift or Ctrl to add, drag for a window or crossing box. The
|
||||
wheel zooms at the cursor, the middle button pans and Shift+middle orbits (the mouse preset in
|
||||
Preferences switches to SolidWorks or Inventor style). The view cube and the navigation bar
|
||||
change the view. Right-click for the marking menu: eight commands around the cursor, plus a
|
||||
menu for whatever is under it.
|
||||
- **Dialogs** dock on the right with a live preview. Most features also show drag handles and a
|
||||
value box in the viewport.
|
||||
- **Timeline** (bottom). Every feature in order. Double-click to edit, drag the marker to roll
|
||||
back, and drag features to reorder them.
|
||||
- **S box.** Press S anywhere for a command search at the cursor. Pin the commands you use most
|
||||
to its top.
|
||||
|
||||
Preferences (File › Preferences) hold the theme, the units of new designs, the mouse preset, the
|
||||
visual style and autosave. Help › Keyboard Shortcuts lists every key, and File › Keyboard
|
||||
Shortcuts changes them.
|
||||
@@ -0,0 +1,32 @@
|
||||
# SolveCraft
|
||||
|
||||
SolveCraft is an open-source parametric 3D CAD application written in pure Rust. It works the way
|
||||
Fusion-style modellers do: sketch on a plane, constrain and dimension the sketch, turn profiles
|
||||
into solids with features on a timeline, and change a parameter to watch the whole timeline
|
||||
rebuild.
|
||||
|
||||

|
||||
|
||||
It runs as:
|
||||
|
||||
- a **desktop app** for Windows and Linux (egui + wgpu);
|
||||
- a **web app** in the browser (wasm, WebGPU or WebGL2), [try it here](app/);
|
||||
- a **headless CLI**, `solvecraft-cli`, that runs command scripts, measures and exports;
|
||||
- an **MCP server** that AI agents model with, headless or driving the running app.
|
||||
|
||||
Everything the user can do is a *command* with JSON parameters. The toolbar, the dialogs, scripts,
|
||||
the CLI, the control channel and MCP all run the same commands, so anything you can click you can
|
||||
also script, test or hand to an agent.
|
||||
|
||||
SolveCraft is early. Sketching, solid modelling, parameters, components with joints, sheet metal
|
||||
and a plastic-enclosure subset work; surfaces, drawings, CAM and simulation are deferred. The
|
||||
[roadmap](https://github.com/bherbruck/solvecraft/blob/main/ROADMAP.md) has the details, and
|
||||
[command parity](dev/parity.md) and the [Fusion oracle](dev/oracle.md) measure how far along it
|
||||
is.
|
||||
|
||||
This book has two halves: the **user guide** for people modelling with SolveCraft, and the
|
||||
**developer guide** for people working on it. The [command reference](reference/commands.md) is
|
||||
generated from the code on every build.
|
||||
|
||||
SolveCraft is licensed MIT OR Apache-2.0. It is a clean-room implementation and is not affiliated
|
||||
with Autodesk; Fusion is a trademark of Autodesk, Inc.
|
||||
Reference in new issue
Block a user