Skip to content

Fix organic tree smoothing drift and layer mapping (#14069) - #680

Open
bluetianyu wants to merge 1 commit into
process_interface_phase2from
fix_lty_OrganicTreeBranchDrift
Open

Fix organic tree smoothing drift and layer mapping (#14069)#680
bluetianyu wants to merge 1 commit into
process_interface_phase2from
fix_lty_OrganicTreeBranchDrift

Conversation

@bluetianyu

Copy link
Copy Markdown

PR OrcaSlicer#14069 — Fix organic tree smoothing drift and layer mapping

Summary

This PR fixes two defects in the organic tree support post-processing pipeline:

  1. Smoothing drift: During iterative collision avoidance + Laplacian smoothing, node positions could drift without bound because only per-iteration step caps were enforced—cumulative displacement had no constraint. Over up to 100 iterations, a node could theoretically drift up to 70mm, breaking the 3D branch structure.

  2. Layer mapping for raft layers: layer_idx_ceil() and layer_idx_floor() used a uniform-spacing formula that failed for all Z values falling within the raft-layer range. The formula returned raft_layers.size() (the first object-layer index) for every raft-zone Z, causing collision detection to skip raft layers entirely.

Changes

TreeSupport3D.cpp — Add vertical-structure constraints

Added limit_candidate_to_linked_layers lambda inside organic_smooth_branches_avoid_collisions(). After each collision-avoidance or Laplacian-smoothing nudge, the candidate position is now constrained by the physically reachable range from its linked upper (parent) and lower (child) nodes:

allowed_shift = max(0, neighbor_radius - current_radius) + maximum_move_distance_slow;
candidate = constrain_to_anchor(candidate, neighbor.prev_position, allowed_shift);
  • The constraint is applied after both the collision-avoidance nudge and the Laplacian-smoothing nudge.
  • constrain_to_anchor is a simple clamp: if the candidate exceeds allowed_shift from the anchor, it is pulled back along the same direction to the boundary; otherwise it passes through unchanged.
  • The allowed_shift formula is physically meaningful: the radius difference between connected nodes represents the lateral clearance the branch geometry can accommodate, plus the configured slow-move margin.

TreeSupportCommon.hpp — Fix Z-to-layer-index mapping for raft layers

Rewrote layer_idx_ceil() and layer_idx_floor() to handle raft layers and object layers separately:

  • Raft-layer zone (z < first_object_z): Uses std::lower_bound / std::upper_bound binary search on the ordered config.raft_layers array to find the exact index.
  • Object-layer zone (z >= first_object_z): Uses the existing linear formula (which was correct for this zone).
  • Extracted first_object_support_layer_z() helper to clarify the boundary between raft and object layers.

Before / After

Scenario Old behavior New behavior
layer_idx_ceil(0.35) with raft at [0.20, 0.40, 0.55] Returns 3 (wrong—first object layer) Returns 1 (correct—raft1)
layer_idx_floor(0.35) with raft at [0.20, 0.40, 0.55] Returns 3 (wrong—first object layer) Returns 0 (correct—raft0)
Node after 50+ smoothing iterations Can drift arbitrarily far from parent/child Constrained within allowed_shift of linked layers

Scope of impact

  • Affected code: organic_smooth_branches_avoid_collisions() and layer_idx_ceil/floor()
  • Affected feature: Organic tree support only (not grid / snug / default supports)
  • Behavior change: In normal cases, the constraints are wide enough to not interfere with legitimate collision avoidance. The fix only prevents pathological drift and incorrect layer lookups.
  • Backward compatibility: No changes to profiles, project files, or configuration.

Testing

  • Verified that collision avoidance still converges (num_moved reaches zero) within the iteration limit.
  • Verified layer_idx_ceil/floor return correct indices for Z values across raft layers, the raft-object boundary, and object layers.
  • Manual comparison of organic tree support 3D preview before/after on models known to trigger drift.

Files changed

File Lines
src/libslic3r/Support/TreeSupport3D.cpp +60
src/libslic3r/Support/TreeSupportCommon.hpp +29

Before fix:

default.mp4

After fix:

default.mp4

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.

2 participants