Skip to content

Sheet metal: Convert to Sheet Metal can make a flat 3D print that folds into the body (#13905) - #13906

Draft
cvengels wants to merge 6 commits into
tangency-labs:mainfrom
cvengels:feat/foldable-print-claim
Draft

cvengels wants to merge 6 commits into
tangency-labs:mainfrom
cvengels:feat/foldable-print-claim

Conversation

@cvengels

@cvengels cvengels commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Change

This draft claims #13905. It adds a "Foldable 3D print" option to Convert to Sheet Metal. The option turns a solid or shelled body into one flat part for a 3D printer. After printing, the user folds the part by hand into the body.

Each bend becomes a V-groove with a thin film under it, and the film is the hinge. Edges that are not bends meet butted or mitred, or are joined by fingers and a channel for a piece of filament. Bend edges can get the same filament joint. A print that overlaps itself splits at the edges the user picks. Refold and Unfold work on the print, and the flat pattern shows its bend lines.

The code is ready locally and is being checked on real prints (PLA now, PETG and TPU next). I will push it to this branch when the test prints are good.

Changes a default: no

Validation

To follow with the code: cargo xtask ci, the new tests in crates/engine/src/cmd/sheet_convert_tests.rs and crates/ui-egui/src/dialogs_sheet_tests.rs, and measured sizes of the folded test prints.

Screenshots of the behavior (when observable)

Original test cube:
cube_original_en

Unfolded flat cube:
msp7q7s

Test print and assembly:
IMG_20261108_210219
IMG_20261108_212016
IMG_20261108_212113

Channels for raw filament:
IMG_20261108_211821

Integration status

Branched from upstream main at c7fb4f7. Draft, claim only.

🤖 Generated with Claude Code

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

coderabbitai Bot commented Nov 8, 2026 •

Copy link
Copy Markdown
Contributor

Important

Draft PR not reviewed

Draft PRs are not automatically reviewed by default.

  • Trigger a manual review

To automatically review draft PRs, update your CodeRabbit configuration:

reviews:
  auto_review:
    drafts: true
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

cvengels and others added 3 commits November 11, 2026 04:34
Work in progress, not ready for review. A new wizard in the Sheet Metal tab,
"Unfold for Printing", in six steps: pick the base face, set bend and cut
edges, unfold flat against a printer bed, split at bends, choose wall and
joints, and build the printable solid. Steps 1 to 4 are tested by hand,
steps 5 and 6 on a box. Known gaps: carving out faces into groups, per-wall
thickness, saved custom printers. Some tests in the full suite fail on main
as well and are not caused by this change.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…ers (tangency-labs#13905)

The wizard and the print wall hints called functions that moved to the
shared ui-text and theme crates and to ui_kit on main; they use the new
places now. No change in behaviour.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
…gency-labs#13905)

Faces that can't fold with the rest of the pattern (the walls of a hole)
are carved out into a part of their own in step 2. The part folds at the
inside corners of the body, on the film, and its border follows what the
cuts get: fingers that stand in sockets of the faces it meets (press fit
or filament), a mitre, or a butt end.

Also: a chamfer's straight spline edges count as straight, the new tab
hides the origin, printers of one's own are kept in the preferences, and
the fingers of two walls that lie side by side in the flat end short of
the line halfway between them.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@cvengels

cvengels commented Nov 11, 2026 •

Copy link
Copy Markdown
Contributor Author

WIP update, 11 November (commit efd5084). Still a draft: cargo xtask ci and the wasm build have not been run on this state.

Added

  • Step 2 can carve faces out of the pattern into a part of their own (print.unfold.group, print.unfold.ungroup), for faces that can't fold with the rest, such as the walls of a hole. The part folds at the inside corners of the body, on the film alone, with a slit over each bend, and is made as a body of its own beside the print.
  • The border of a carved-out part follows what the cuts get: fingers that stand in sockets of the faces it meets (press fit with nubs and dimples, or a filament channel), a mitre, or a butt end. sheet.convert takes print_sockets and print_mitres for the matching edges of holes in a foldable print.
  • Step 3 keeps printers of one's own (a name and a bed size) in the preferences.
  • A regression test for a box with flat chamfers, and tests for the carved-out chain (butt, press fit, mitre).

Changed

  • The design a body is unfolded in starts with the origin hidden: nothing is sketched there, and it lay over the edges to click.
  • In step 2 the carved-out faces show as a wide band under their edges, so cuts, bends and the faces still missing stay readable on top of it.
  • A wall of a foldable print ends at least 0.4 mm short of an inside corner, so it prints apart from the panel it lies beside in the flat.

Fixed

  • A body with flat chamfers was refused as having curved faces: a chamfer's edges are splines of two points, which are straight lines. Straight polylines and splines now count as straight edges.
  • Fingers of two walls that lie side by side in the flat (walls on a corner of less than 90° of the face they hang on) leaned into each other and fused. They now end short of the line halfway between the two walls, and a finger cut back to a fin is left out.
  • Corner fills that came out as thin fins, and loose crumbs under 5 mm³, are left out of the print.

Known open

  • The joints still come out wrong in places on a real part (a letter P with 45° corners), in ways that change from fix to fix. The plan is to look at how the joints are generated as a whole rather than patch more single cases.
  • With mitre at the cuts that part is refused as overlapping itself in the flat; with butt, press fit and filament it is made.
  • Refolding does not fold a carved-out part, a wall thickness per wall is not built, and curved faces are still refused.

🤖 Generated with Claude Code

image image image

…ngency-labs#13905)

Generator 2 makes the printable parts from the body's own walls: each
face's outline taken into the material by the wall thickness, mitred
where two faces meet round the outside of the body, then turned flat
with a film under each bend. Folded up, the walls are the body's shell.

A cut can be a press fit: the corner two walls share is dealt out along
the edge in fingers, a nub on each finger's end face and a dimple in
what stands next to it. Bends are never press fits, the ends of a cut
stay mitred, and a cut gets no fingers where another wall lies beside it
in the flat pattern.

Step 1 of the wizard chooses the generator (1 stays the default); step 5
offers mitre or press fit for the cuts of generator 2.

Not run yet: cargo xtask ci, the wasm build.

Co-Authored-By: Claude Fable 5.2 <noreply@anthropic.com>
@cvengels

cvengels commented Nov 12, 2026 •

Copy link
Copy Markdown
Contributor Author

Daily WIP update, 12 November (commit b75a5fa). Still a draft: cargo xtask ci and the wasm build have not been run on this state.

Why a second generator. The first printed test (letter P, made with fingers, press nubs and filament channels) clamped together, but it needed manual fixes: small fragments at corners where three faces meet, and one bend that could not fold because a joint collided with a wall. Those all came from computing joints edge by edge in the flat. The second generator turns the order round: it builds the walls on the folded body and unfolds them afterwards, so folded up again they are the body's shell by construction.

Added

  • Generator 2 (crates/doc/src/print_unfold_walls.rs). Each face becomes a wall where it lies on the body: its outline taken into the material by the wall thickness. Where two faces meet round the outside of the body, both walls end on the plane halfway between them, half the clearance short of it (a mitre). Inside corners end square; a bend there gets a slit down to the film. The walls are then moved into the flat pattern and joined by a film under each bend.
  • Press fits for generator 2. A cut can be a press fit instead of a mitre: the corner the two walls share is dealt out along the edge in fingers, by turns. A finger has a nub on its end faces, and what stands next to it gets the matching dimple. Only cuts whose faces meet square and that are long enough get fingers.
  • Choosing the generator in step 1 of the wizard (a drop-down, generator 1 stays the default), stored as generator in the design (absent for 1). print.unfold.start takes generator.
  • Step 5 for generator 2: cuts are "mitre" or "press fit", for all cuts or for a single cut clicked.
  • Tests: a block with mitres, a block with press fits, and an L-shaped body for the inside-corner case below.

Changed

  • For generator 2, print.unfold.joint accepts plain (mitred) and press on cuts only, and says why when a cut can't be a press fit. print.unfold.joints treats press as a press fit and every other choice as a mitre.
  • The parts of a pattern are joined into one body or not made at all: if the union of all pieces at once is refused, they are joined one after the other, never left side by side as loose pieces.
  • UI strings for the generator and its joints in all eight languages.

Fixed

  • Fingers beside a folded-out wall. At an inside corner of a face's outline, the wall folded out next to a cut lies right beside it in the flat. A finger there would have printed as one piece with that wall and blocked the bend. A cut now gets no fingers along such a stretch and stays mitred there; step 5 shows it as mitred.
  • Bends are untouched by press fits, and both ends of every cut stay mitred, so corners where three faces meet end exactly as in the glued version.

Tested by hand

  • Letter P with generator 2 and mitres: printed, glued, folds cleanly with all edges closed.
image
  • Letter P with generator 2 and press fits: generated as two bodies, each one closed solid without loose fragments; the print is running.
image image

Still open

  • cargo xtask ci and the wasm build.
  • Wall thickness per wall.
  • Refold does not fold the parts of generator 2.
  • Curved faces.

@h0witzer

Copy link
Copy Markdown
Contributor

Hi @cvengels, the foldable print is a great idea, and the test prints look good. A heads-up before you push the code, so it lands on the right base.

#9245 (#6748, surface-first sheet metal) is about to land and replaces the flat-pattern model this PR builds on. sheet_convert.rs is deleted, and Convert to Sheet Metal becomes the surface converter (sheet_surface_convert.rs). sheet::convert_body and SheetBody go away too. Once it merges, this branch will conflict throughout sheet.rs, sheet_convert.rs and eval_more.rs.

Your geometry fits the new model well. In #9245, sheet metal is surfaces plus edges with attributes plus rules. A print hinge (V-groove and film) is an attribute on a bend edge, and your finger and filament joints are attributes on a seam or rip edge. The flat comes from developing the surfaces, so your groove, film and clearance values would live in the rule.

Our suggestion: hold the push until #9245 merges, then rebase onto the surface converter. Your print tests (measured folded sizes) carry straight over as the spec. I'm happy to walk through where each piece goes in the new code. Ping me here or on #6748.

@bherbruck

Copy link
Copy Markdown
Collaborator

Holding this briefly: a sheet-metal refactor that replaces the flat-pattern model is landing first, and this will need to sit on top of it. I will ping you when it is in.

@bherbruck bherbruck added the status:hold-sheetmetal Held until the sheet-metal flat-pattern refactor lands (owner, Nov 12) label Nov 12, 2026
@cvengels

Copy link
Copy Markdown
Contributor Author

Hey @h0witzer and @bherbruck

Thank you for the info!
I'm already holding back the merge request because this project started right after the first release candidate of 0.40 was announced. Me and Claude weren't 100% sure wether SolidCore would change too much of the basic geometry code or other stuff.
Now I'm tinkering to get more reliable connections of the surfaces as mentioned in the last update.

Please ping me when the #9245 merge is ready, I will instruct Claude to test and adapt our feature accordingly after that.

@raykholo

Copy link
Copy Markdown
Contributor

@cvengels this PR is held for the sheet-metal refactor in #9245 (RFC #6748). To keep it from starting over when that lands, it has been ported onto the refactor as a draft: h0witzer#27. Your tests are its spec, and it credits you as the author. Have a look when you can; it retargets to main once #9245 merges.

…and press joints (tangency-labs#13905)

The first generator (a foldable print made through Convert to Sheet
Metal, with V-grooves and joints computed edge by edge in the flat) is
removed. Its joints kept breaking at corners where three faces meet;
the printed tests of the second generator, which builds the walls on
the folded body and only then lays them flat, folded cleanly. That
generator is now the only one, and step 1 no longer offers a choice.

With it, every sheet metal file is back as it is on main: sheet.rs,
sheet_convert.rs, eval_more.rs, cmd/sheet.rs, the sheet schema and
dialog, and their tests. sheet_print_fold.rs and the carved-group
generator are gone. The measures the joints are made to (film,
clearance, nub, filament channel, the core of a joint on a bend) live
in print_joint.rs.

Joints:
- A cut is mitred, or a press fit, or a filament joint: fingers that
  share the corner of the two walls by turns, with a nub and a dimple
  where two meet, or a channel through the middle of the corner.
- A bend turns on its film, or holds its fold with a filament joint or
  a press fit: fingers that are a sector round the bend's edge, with
  the channel or the nub on the line halfway between the two faces.
  The other wall is cut back round them down to its film.
- A cut gets no fingers where another wall of the part lies beside it
  in the flat, and a bend none where they would stand in another wall.
- The ends of every edge stay mitred.

Defaults from the test prints: 3 mm wall, cuts mitred, nub 1.0 mm round
and 0.5 mm high, 0.2 mm between two fingers, fingers from 3 mm wide,
press fits from a 1.5 mm wall, a 0.3 mm slit over inside-corner bends.

Not run yet: cargo xtask ci, the wasm build. The wizard's tests, the
sheet metal tests and clippy passed before the last two default values
changed.

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

Copy link
Copy Markdown
Contributor Author

Thank you @raykholo, that's very kind, and thanks for keeping the authorship!

One thing you should know before spending more time on it: after the test prints we dropped generator 1 (the path through Convert to Sheet Metal) entirely. Its joints kept breaking at corners where three faces meet. The second generator, which builds the walls on the folded body and only then lays them flat, printed and folded cleanly, so it is now the only one. It has since gained filament joints and press fits on cuts and on bends. My latest branch no longer touches sheet.rs, sheet_convert.rs, eval_more.rs or cmd/sheet.rs at all.

So most of the sheet-side port may not be needed. I've just pushed the current state as a WIP update (e1d54db) so you can see it. Happy to go through what's left with you once #9245 is in.

@cvengels

Copy link
Copy Markdown
Contributor Author

The corners are now closed, only small gaps visible. The new generator replaces the initial version completely. Tests go very well, development should be finished by next week.

image image image

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

status:hold-sheetmetal Held until the sheet-metal flat-pattern refactor lands (owner, Nov 12)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants