Skip to content

feat: G2/G3 Arc Support + Bambu Studio Wipe Fix#51

Closed
adele-with-a-b wants to merge 2 commits intoGeekDetour:mainfrom
adele-with-a-b:main
Closed

feat: G2/G3 Arc Support + Bambu Studio Wipe Fix#51
adele-with-a-b wants to merge 2 commits intoGeekDetour:mainfrom
adele-with-a-b:main

Conversation

@adele-with-a-b
Copy link

@adele-with-a-b adele-with-a-b commented Mar 8, 2026

feat: G2/G3 Arc Support — Bounding Box, Wipe Path, and Absolute Extrusion Fix

This PR adds proper G2/G3 arc support to BrickLayers across three areas, enabling users to safely use Arc Fitting in their slicer without needing to disable it.

Summary of Changes

Area Problem Fix
Bounding box GCodeStateBBox only used arc endpoints, ignoring the arc bulge New compute_arc() method computes true arc bounding box via cardinal angle crossing detection
Wipe path wipe() and wipe_movement() used chord distance for G2/G3 segments Arc-aware distance calculation and arc interpolation for wipe endpoints
Absolute extrusion (issue #17) G92 E reset used wrong E value after deferred perimeters Reset now uses E value from before the deferred block

1. Arc Bounding Box (compute_arc)

The existing GCodeStateBBox.compute() only feeds the arc endpoint into the bounding box. For arcs that bulge beyond their endpoints (any arc crossing a cardinal angle — 0°, 90°, 180°, 270°), this underestimates the bounding box.

compute_arc() computes the true bounding box by:

  1. Finding the arc center from I/J offsets
  2. Computing the sweep angle (CW vs CCW)
  3. Checking which cardinal angles fall within the sweep
  4. Including those extreme points in the bbox

Unit tests: 10/10 passing across quarter circles, semicircles, full circles, 270° arcs, small arcs, cardinal crossings, tiny radius fallback, and offset centers.

[PASS] Quarter circle CCW
[PASS] Quarter circle CW
[PASS] Semicircle CCW (top)
[PASS] Semicircle CW (bottom)
[PASS] Full circle CCW
[PASS] 270° arc CCW
[PASS] Small arc (no cardinal crossing)
[PASS] Arc crossing 90°
[PASS] Tiny radius fallback
[PASS] Offset center quarter arc

Results: 10/10 passed

Visual proof (blue dashed = correct arc bbox, red dotted = endpoint-only bbox):

Real-world impact: Tested with a petal vase model (78K+ arc commands). The patch corrected 1 loop placement (48 G-code lines changed). Current slicers produce short arcs (median 6.3° sweep) so the impact is small but prevents edge cases. With arc fitting OFF, output is identical (zero regression).

2. Arc-Aware Wipe Path

The wipe() and wipe_movement() functions retrace part of the printed loop while retracting. They calculate segment distance using Point.distance_between_points() — the chord length. For G2/G3 arcs, the actual path length is longer than the chord.

Problems this caused:

  • Wipe distance underestimated (stops too early)
  • Retraction distributed unevenly across wipe segments
  • Wipe endpoint cuts across the arc instead of following the curve

Fix: New helper methods detect G2/G3 segments and use true arc length and arc interpolation:

  • Point.arc_length() — computes r × sweep_angle
  • Point.point_along_arc() — interpolates a point at a given distance along the arc
  • Point.parse_arc_ij() — extracts I/J offsets from G-code string
  • _wipe_segment_info() / _wipe_interpolate() — shared helpers used by both wipe functions

Test results (star vase, 49K arc commands, arc fitting ON):

  • 8,584 wipe lines changed
  • Wipe endpoints shifted to follow arc curves
  • Retraction amounts redistributed more evenly
  • Micro-segments eliminated (e.g., E-0.00054 artifacts gone)

Sample diff:

< G1 X191.246 Y159.897 E-0.49272 ; BRICK: Wipe   (chord interpolation)
> G1 X191.756 Y159.810 E-0.49272 ; BRICK: Wipe   (arc interpolation)

< G1 X181.008 Y167.193 E-0.28697 ; BRICK: Wipe   (wrong retraction split)
> G1 X181.008 Y167.193 E-0.28887 ; BRICK: Wipe   (correct retraction split)

3. Absolute Extrusion E Reset (Issue #17)

When BrickLayers defers inner wall perimeters and replays them with relative extrusion (M83), the G92 E reset at the end used myline.previous.e — the E value that includes the deferred perimeters' extrusion. But since those perimeters were replayed with relative extrusion, the firmware's E register never advanced by that amount.

This caused a massive blob at the start of the next feature (outer wall) in PrusaSlicer with absolute extrusion mode, as reported in #17.

Fix: G92 E now uses self.last_noninternalperimeter_state.e — the E value from before the deferred perimeters. Applied to both generate_deffered_perimeters() and the kept perimeters path.

Note: This is a no-op for Bambu Studio and OrcaSlicer which use relative extrusion (M83) by default.

Testing

  • Unit tests: tests/test_compute_arc.py — 10/10 geometric correctness tests
  • Visual validation: tests/visualize_arc_bbox.py generates bbox comparison diagram
  • Before/after comparison: pr-validation/compare_before_after.py (local) runs unpatched vs patched on any G-code file
  • Test models: Petal vase and star vase STLs with build123d source included
  • Regression test: Arc fitting OFF produces identical output (zero diff)

Files Changed

  • bricklayers.py — 199 insertions, 29 deletions

README Update

With these changes, the "Disable Arc fitting (for now)" warning in the README can be removed or updated to indicate arc fitting is now supported.

Related

4. Wipe Block Travel Fix (Bambu Studio Preview)

BrickLayers was storing travel line references during wipe blocks (; WIPE_START / ; WIPE_END), then replacing them with BRICK: Travel Fix Up moves that included Z changes. This broke the wipe sequence in two ways:

  1. Preview: Bambu Studio's G-code renderer showed missing chunks at every brick layer transition because the wipe sequence was malformed
  2. Print quality: The interrupted wipe caused incomplete nozzle cleaning, likely producing strings or small blobs at brick layer transition points

Fix: One-line change — added and not feature.wiping check when storing the last_noninternalperimeter_xy_line reference (line 2188). This prevents BrickLayers from modifying travel moves that are part of a wipe sequence.

Impact: Affects Bambu Studio format G-code only. OrcaSlicer format was unaffected because its wipe handling doesn't produce the same travel pattern inside wipe blocks.

Verification: Sliced BrickLayersChallengeSimple.stl in Bambu Studio with BrickLayers enabled — missing chunks in preview are gone. Dragging the exported G-code into unmodified Bambu Studio also renders correctly.


Slicer Preview

BambuStudio and OrcaSlicer do not automatically show post-processing script changes in the preview — you normally have to export the G-code and drag it back in.

A patched BambuStudio fork is available that re-parses G-code after post-processing scripts run, showing the BrickLayers toolpath directly in the preview without manual re-import. The wipe fix in this PR is required for the preview to render correctly without missing chunks.

…sion fix

Arc bounding box:
- compute_arc() on GCodeStateBBox computes true arc bbox via cardinal
  angle crossing detection for G2/G3 moves in loop depth calculation

Arc-aware wipe:
- wipe() and wipe_movement() use true arc path length and arc
  interpolation instead of chord distance for G2/G3 segments
- New helpers: Point.arc_length(), Point.point_along_arc(),
  Point.parse_arc_ij(), _wipe_segment_info(), _wipe_interpolate()

Absolute extrusion fix (issue GeekDetour#17):
- G92 E reset after deferred perimeters uses pre-deferred E value
  (last_noninternalperimeter_state.e) instead of myline.previous.e
- Fixes blob at outer wall start in PrusaSlicer absolute extrusion mode
- No-op for Bambu Studio/OrcaSlicer (relative extrusion)
BrickLayers was storing travel line references during wipe blocks,
then replacing them with Travel Fix Up moves that broke the wipe
sequence. This caused:
1. Missing chunks in Bambu Studio's G-code preview
2. Incomplete nozzle wipe at brick layer transitions (print quality)

One-line fix: added 'and not feature.wiping' check when storing
last_noninternalperimeter_xy_line reference.

Affects Bambu Studio format only — OrcaSlicer format was unaffected.
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.

Absolute extrusion mode issue

1 participant