Belt printer: classic tree branches land on the belt instead of sliding down it (#16263)

Classic tree supports (tree hybrid / slim / strong) on a belt slid down
the belt plane ahead of the part instead of landing on it.
`TreeSupportData` added the belt surface to every layer's outlines, so
the belt fed the collision and avoidance maps, and a node that descends
onto an obstacle is pushed out of it; on a tilted surface that walks the
branch down the belt. This takes the belt out of the outlines. The belt
is where a branch ends, and that is already handled: `drop_nodes()`
stops a node once its whole circle is in the belt
(`belt_node_landed()`), and `draw_circles()` clips every layer's circles
to the belt plane, so the branch tapers to a tip on it. Organic got the
same treatment in #16236 (the belt is no longer a support blocker
there).

One file, +7/−12. Non-belt printers are untouched: the removed block
only ran when the belt floor context was active.

## Before / after

Cube with a fin whose underside is parallel to the layers, 20 mm ahead
of the cube, tree hybrid, Left view:

| | support footprint along the belt | filament for support |
|---|---|---|
| before | belt Z 43–139 (sweeps 72 mm ahead of the part) | 2403 mm |
| after | belt Z 60–139, columns parallel to the up direction | 1606 mm
|

Organic on the same model: belt Z 74–139 (unchanged). Before/after
screenshots follow in a comment.

## Tests

- *Belt supports reach the belt under a leading overhang* passes for
normal, organic and tree_hybrid; all `[belt]` tests pass;
`fff_print_tests` 355 and `libslic3r_tests` 1116 pass on the branch.
- `scripts/clang_tidy_diff.py --base upstream/belt-printer`: no
findings.
- Fork CI (Build all) on this change: unit tests green on Linux x86_64,
Linux aarch64 and macOS arm64
(https://github.com/HarrierPigeon/OrcaSlicer/actions/runs/37601644023;
its Windows and slice-check failures are the ones #16262 fixes).
- Scripted GUI pass on belt-printer + this change: tree hybrid, organic
and normal supports at Y≈120 all reach the belt (lowest 0.17–0.19 mm);
with the part within its height of Y = 0 all three generators now behave
the same (support before the belt start, plate-boundary error shown),
where tree hybrid used to be the odd one out (clipped, hanging 9.5 mm
above the belt).
- Written with Claude Code; reviewed and run by me.
This commit is contained in:
Joseph Robertson
2026-10-07 14:21:34 -05:00
committed by GitHub
+7 -12
View File
@@ -3927,18 +3927,13 @@ TreeSupportData::TreeSupportData(const PrintObject &object, coordf_t xy_distance
poly.simplify(scale_(m_radius_sample_resolution), &outline);
}
// Belt floor: add belt surface polygon to layer outlines so the
// collision system treats the belt as a physical surface.
{
BeltFloorContext ctx;
double local_print_z = layer->print_z - object.belt_global_z_offset();
if (ctx.init_local(object.slicing_parameters(), object.print()->config(),
object.belt_global_z_offset())) {
Polygons belt_surface = ctx.surface_polygon(local_print_z);
for (auto &p : belt_surface)
outline.emplace_back(ExPolygon(p));
}
}
// The belt surface is deliberately NOT part of the outlines. The outlines
// feed the collision and avoidance maps, and a node descending onto an
// obstacle is pushed out of it: with the belt as an obstacle the nodes slid
// down the tilted surface, ahead of the part, instead of landing on it. The
// belt is where a branch ENDS: drop_nodes() stops a node once its whole
// circle is in the belt (belt_node_landed()) and draw_circles() clips every
// layer's circles to the belt plane, so the branch tapers to a tip on it.
if (layer_nr == 0)
m_layer_outlines_below.push_back(outline);