Skip to content

Add continuous constant-wall spiral mode (thick-wall spiral vase) - #15527

Open
steventaitinger wants to merge 8 commits into
prusa3d:masterfrom
steventaitinger:feature/multi-wall-vase
Open

Add continuous constant-wall spiral mode (thick-wall spiral vase)#15527
steventaitinger wants to merge 8 commits into
prusa3d:masterfrom
steventaitinger:feature/multi-wall-vase

Conversation

@steventaitinger

Copy link
Copy Markdown

Continuous constant-wall spiral mode

Adds an optional one-click print mode for round, constant-wall shapes (tubes, cones, and other axisymmetric walls): a single checkbox, Continuous constant-wall spiral, under Print Settings → Layers and perimeters → Vertical shells.

It generalizes classic Spiral Vase to walls that are more than one perimeter thick, while keeping the seamless, retraction-free character of spiral vase.

What it does

For every layer whose cross-section is a fully axisymmetric wall (exactly one hole; both boundaries circular by isoperimetric quotient; concentric), the layer's concentric perimeters are morphed into one continuous extrusion:

  • Uniformly re-spaced concentric rings fill the whole wall solidly — as many as fit the geometry per layer (works on tapered walls such as cones), no separate gap-fill feature.
  • Short tangent S-arc step-overs (one-wall-width corner radius) move between rings.
  • Exact volumetric flow: each layer deposits exactly wall_area × layer_height — locally coverage-corrected (flat arcs vs. step-overs) and globally normalized, so the wall is neither over- nor under-extruded.
  • Straight vertical elevator on the wall line at the seam for the layer change (a nozzle-diameter column bead, no Z-hop ramp), with boustrophedon layer direction so each layer begins exactly where the previous one's climb ended — the whole section prints with zero retractions and one continuous path.

Layers that are not a constant circular wall (side holes, ports, non-round sections, solid tops/bottoms) fall back to the regular settings automatically — the per-layer spiral-vase enable machinery disables the transform for them. No other print settings are modified by the mode.

Implementation notes

  • Classic-generator path only (process_classic); the morph replaces the collected loops with one ExtrusionMultiPath, so the existing per-layer spiral-vase gating in GCodeGenerator still sees a single perimeter and treats the layer as spiral.
  • The vertical elevator is emitted by SpiralVase::process_layer_multiwall (flat layer + one vertical extruding move at the seam), with an absolute-E G92 restore so following layers don't read as micro-retracts.
  • A degenerate self-crossing "bowtie" leftover loop (where the outer-going and hole-going offset fronts meet) is rejected via a scale-invariant isoperimetric-quotient gate before morphing.
  • New option spiral_vase_wall_count is superseded by the single constant_wall_spiral bool in the final commit; validation/normalization/slicing-mode adjustments are gated on the mode.

Testing

Built and sliced locally against version_2.9.6. On a tapered-cone regression (25 mm tall, ~3 mm wall, 0.2 mm layers): every layer slices as a clean concentric-ring wall, 0 retractions across the whole print, and total extruded volume within +0.1% of the sliced wall volume. A headless G-code analyzer (per-layer radius sweep, continuity, volumetric audit) was used to verify.

This is offered for consideration and feedback — happy to iterate on API/UX (option naming, mode placement) or split it into smaller reviewable pieces if that's preferred.

🤖 Generated with Claude Code

steventaitinger and others added 8 commits July 19, 2026 18:00
Port of the multi-wall spiral vase feature from the OrcaSlicer fork
(staitinger/OrcaSlicer feature/multi-wall-vase) to PrusaSlicer 2.9.6.

New print option spiral_vase_wall_count (default 1 = classic single-wall
spiral vase, N = N concentric walls, 0 = automatic: fill the sliced wall
completely, works for tapered shapes such as cones).

Each layer's concentric perimeters are morphed into one continuous
extrusion: flat rings at constant radius joined by short smoothstep
transitions (~0.05 in of arc), uniformly re-spaced outer->inner so the
wall is solid for any geometry, beads deposited ~15% wider than the ring
pitch so adjacent rings fuse. Gap fill is suppressed in this mode (the
morph covers the whole wall). Layers print flat at nominal Z with only
the final ~1.27 mm ramping up to the next layer, alternating direction
per layer so the ramp connects end-to-start. Slicing keeps Regular mode
(inner holes preserved) when wall count != 1.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Where the outer-going and hole-going offset fronts meet, the leftover
strip can survive as a degenerate self-crossing loop: huge perimeter,
tiny net area. It passed the nested/concentric filter (small area,
centered centroid), and morphing against its angularly scrambled points
lerped straight through the center, turning one layer into a criss-cross
solid disc (cone test, layer 42).

Gate each candidate loop on its isoperimetric quotient A/P^2 relative to
the outer contour: scale-invariant, characterizes shape only. Real
concentric rings keep or raise the outer's quotient as they shrink;
bowtie slivers collapse to a few percent -> rejected at 35%.

Also adds env-gated diagnostics (MULTIWALL_DEBUG=<layer>) dumping the
collected loop radii for a layer.

Verified: cone at wall count 0 slices 128/128 ring layers, 2 retractions,
zero radial jumps, full wall span top to bottom.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…nder)

Replace the uniform +15% bead-overlap flow with locally-correct,
globally-exact volume control. The morphed spiral is now a single
ExtrusionMultiPath whose segments carry coverage-based flow:
- flat ring arcs: one ring pitch of coverage
- ring-step diagonals: pitch * cos(theta) (parallel diagonals sit
  closer perpendicular to their direction; constant flow over-deposited
  ~6% at the seam)
- the final ring's seam arc: coverage tapered with the same smoothstep
  the incoming diagonal used, matching the narrowing leftover strip
  (constant flow re-deposited a full bead on the diagonal's tail - the
  seam blob that stacked into a ridge)
Then all segment flows are scaled so the layer extrudes EXACTLY
wall_area * layer_height, the sliced wall's true volume (wall area
threaded from surface.expolygon into make_multiwall_spiral).

Verified on the cone regression: total extruded volume 8928.9 mm3 vs
sum of per-layer slice-area targets 8919.8 mm3 = +0.10%. Every layer
still a clean ring, 2 retractions, seams intact.

Also: MULTIWALL_DEBUG=-1 dumps per-layer volume normalization data.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tions

The Z climb to the next layer is now its own 'elevator' arc on the
midline between the last two rings - half a pitch inside the wall - so
the climbing bead never sits on or squishes out of the interior or
exterior surface. It runs backward along the seam arc, cancelling the
path's angular advance so each layer's exit lands exactly on the next
layer's entry. Flow tapers 0 -> pitch with the climb (nothing where it
overlaps the current layer, a full bead into the next layer's seam
interstice, whose own departure diagonal deposits ~nothing there).

Both surface rings (first and final) are now complete undistorted
circles every layer. Step-overs are straight linear diagonals spaced
pitch*cos(theta) - the smoothstep S-curve diverged at its ends and left
diamond voids down the seam. All segment boundaries share exact points
(including the one-sample closing chords), so the whole part prints as
ONE uninterrupted extrusion.

Fixes an out-of-bounds read (fin[M]) in the elevator chunking when the
seam arc quantized below 4 samples - garbage first points caused a
retract + wild travel on most layers.

Verified on the cone: 0 retractions in the entire 128-layer print,
travels reduced 1550 -> 252 (all sub-mm seam hops, no retract), every
layer a clean ring, total extruded volume +0.10% of the sliced wall
volume.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace spiral_vase_wall_count and its forced-settings plumbing with a
single checkbox: constant_wall_spiral. No other settings are touched.

Every layer whose cross-section qualifies as a fully axisymmetric wall
(exactly one hole, both boundaries circular by isoperimetric quotient,
concentric within a quarter of the wall thickness) is printed as one
continuous spiral of concentric rings: as many perimeters as fit, no
gap fill, no infill, exact volumetric flow, in-wall elevator at the
layer change. Layers that do not qualify (side holes, ports, non-round
sections, solid regions) print with the regular profile settings -
the per-layer spiral enable machinery disables the vase transform for
them automatically (>1 perimeter entity or fills present).

Classic spiral vase behavior is restored to upstream semantics
(normalize/validate/slicing mode/GUI dialog). The classic generator is
forced while the mode is on so qualifying layers can take the spiral
path. Verified one-flag slice of the cone with stock defaults: every
layer a ring, 2 retractions total (print start), all other travels
sub-mm.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Replace the in-plane climbing arc (micro-helix) with the straightforward
design: the layer ends on a pad at the seam interstice midline, and the
SpiralVase post-processor inserts a single straight VERTICAL extruding
move there - one layer height up, with enough extrusion for a
nozzle-diameter column bead. The climb is inserted immediately after the
layer's last extrusion so the column lands exactly on the pad, before
any trailing travel. The next layer's paths arc around the column: any
point within one bead width of it is projected onto a bead-width-radius
circle, giving smooth sub-mm entry/exit arcs around the elevator.

Also: first layer now gets the full spiral treatment (skirt/brim/
bottom-solid gates bypassed for constant-wall mode - the flat-layer
design coexists with them), and the elevator handshake is geometry-aware
in both directions (climb only into a continuing spiral layer, discount
the departure only when the layer below climbed here), fixing the
first-layer flaps and transition artifacts.

Verified: 127/127 ring layers, 0 retractions, total volume +0.1%,
vertical column at the pad every layer change.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…topology

- Step-overs shrink from 1.27mm straight ramps to short tangent S-arcs
  (cosine blend, ~2 pitches of arc, one-wall-width corner radius) that
  curve around the elevator column.
- All rings re-anchored to +X of the shared centroid after re-spacing,
  so the seam and the vertical elevator columns stack at the same angle
  on every layer instead of wandering with the chained alignment.
- Path topology closed: elevator top -> MIN-flow connector (arcs around
  the column via the avoidance projection) -> first ring full circle
  from flat0 -> departure taper (full flow restored: the elevator is a
  point column, not a strip) -> rings -> final ring + closing taper ->
  pad at the anchor -> vertical climb. Every junction shares exact
  coordinates: mid-layer jumps eliminated.
- Absolute-E mode: restore the E counter (G92) after the injected climb
  so following moves don't read as micro-retracts.

Verified: 127/127 rings, 0 retractions, all travels <= 0.6mm
(unretracted sub-bead hops), volume +0.08% incl. elevator columns.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The elevator column now sits ON the wall line itself - the climb happens
at the end of the final ring (outer wall / inner wall, alternating with
the radial direction), like a perfectly vertical stacked vase seam. The
interstice pad, midline connector, and avoidance-arc projection are all
gone.

Odd layers now run the OPPOSITE rotation around the part
(boustrophedon): each layer starts exactly where the previous layer's
vertical climb ended and prints its whole spiral in one direction. This
cancels the per-layer angular advance of the seam window, so the seam
stays put with NO backward positioning move (the extruding 'wipe' at
the layer start) and no connector at all.

Verified: 127/127 rings, 0 retractions, volume +0.08%, remaining
layer-boundary hops <= 0.73 mm unretracted.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant