Skip to content

Sequential print: only material above height-to-rod can collide with the beam (stacked on #630) - #793

Open
KuzuriAo wants to merge 14 commits into
Snapmaker:mainfrom
KuzuriAo:above-rod-clearance
Open

Sequential print: only material above height-to-rod can collide with the beam (stacked on #630)#793
KuzuriAo wants to merge 14 commits into
Snapmaker:mainfrom
KuzuriAo:above-rod-clearance

Conversation

@KuzuriAo

Copy link
Copy Markdown

@zackaree-shen

Stacked on #630. The first commit in this PR is #630 unchanged; the second is this change. It builds on the constraint graph #630 introduces, so it can't land before it.

The practical result: with #630 and this change together, the plates that started this whole thread, the ones that sliced and printed fine on my X1C but were "too tall" on the U1 no matter how I arranged them, now slice and print on the U1. Objects or assemblies usually need to move a little, but only a little: no splitting assemblies and repacking them by hand, no rotating, no bumping height-to-rod. #630 finds the print order; this change stops counting material the rod can't reach. Those two are the slicer-check half. The physical half is #532, the toolchange G-code that lifts the head over already-printed objects, which is merged but not yet in a release; my prints were done with it in place. Each piece alone helps; all three together turn print-by-object on the U1 from something I fought with on every multi-part model into something that just works.

What this changes

Print::sequential_print_clearance_valid() decides which already-printed objects the X rod could hit while a later object prints by testing whether the objects overlap in Y. Today it uses each object's whole footprint for that test. But the rod sits extruder_clearance_height_to_rod above the nozzle, so the only material it can physically touch is the part of an object that reaches above that height. This PR computes that above-the-rod Y extent per instance and uses it, instead of the full footprint, for the object that could be hit. The later object (the one being printed, i.e. everywhere the nozzle can be) keeps its full footprint plus the extruder_clearance_radius / 2 reach, exactly as before.

In the same function:

  • a per-instance above_rod_min_y / above_rod_max_y is computed from the transformed mesh (any triangle with a vertex above the rod contributes all three vertices, so it's conservative; modifiers, support blockers and negative volumes are skipped because they aren't printed);
  • "is this object tall" becomes "does any of it reach above the rod" (same thing for objects sitting on the bed; correct for objects sunk into it);
  • the ordering constraints from Fix sequential print collision check depending on object list order #630 and the final vertical check both test that extent, with the same 0.1 mm tolerance the footprint test already used.

Nothing else moves: the ±radius/2 reach of the rod is unchanged (still symmetric, still conservative), the height-to-lid rule is unchanged, the toolhead-radius "too close" check is unchanged.

Why

I measured my U1's actual nozzle-to-rod clearance with a printed gauge (details in #630): the rod's underside is 27.2 to 27.4 mm above the nozzle tip, so the profile's 27.5 is right. That also means the rod only ever meets the top few millimeters of a 30 mm object, and with most real models that is a small fraction of the footprint. Pulled from my own files:

object height full footprint depth depth of material above 27.5 mm
Squirtle tail 27.52 32 mm 0.8 mm (a spike)
Squirtle shell / bottom 30.50 66 / 68 mm 28 / 37 mm
a two-part assembly from another model 31.18 145 mm 16 mm (one tip)
its neighbour on the same plate 52.82 140 mm 86 mm

With the current rule those last two need 321 mm of front-to-back space in separate bands on a 262 mm bed: impossible, and the only ways out were rotating them or splitting the assembly and repacking its parts by hand. With this rule the same plate slices after moving the 145 mm assembly 66 mm forward, no rotation, no splitting. The Squirtle plate's three tall objects go from needing 238 mm of Y to 138 mm.

What it does not do

  • It doesn't make anything pass that the rod would actually hit. The extent is taken at the rod height itself (not rod height + first layer), triangles are counted if any vertex is above, and the rod's Y reach is unchanged, so every case this newly allows is one where the rod passes over material that is below it.
  • It doesn't model which side of the nozzle the rod is on. That needs a per-printer field and is a separate discussion.

Cost

This runs in Print::validate(), the check that fires when an object is moved or a setting changes (it's what draws the red "too tall" plane) and once more when you press Slice. It never runs inside the slicing pipeline itself. What it adds is one extra pass over each printed instance's mesh (a transform per vertex, a comparison per triangle). The check already walks the same meshes to build the convex hulls, so this at most doubles a cost that isn't noticeable today. I haven't profiled it, but I ran every plate in the testing section below on both this build and the official 2.3.6, moving objects around and slicing, and if there is a difference it isn't noticeable by eye.

Testing

Built on Snapmaker Orca v2.3.6 + #630, macOS Apple Silicon.

aboverod_test.3mf.zip

  • aboverod_test.3mf (attached above): two 40 x 30 x 2 mm slabs 25 mm apart in Y, each with one 32 mm fin on the edge facing away from the other. Stock 2.3.6 refuses it ("A back-fin plate is too tall": two tall objects whose footprints overlap in Y). This build slices it with the objects untouched, and it printed on the U1 with no contact. Minimal reproduction, ~8 g of filament.

Here is the aboverod_test.3mf loaded in Snapmaker Orca v2.3.6 (official):

aboverod_test-2 3 6-official

Here is the aboverod_test.3mf loaded in Snapmaker Orca v2.3.6 (compiled with #630 and this height-to-rod patch):

aboverod_test-2 3 6-height-to-rod-patch

Here is the video of aboverod_test.3mf successfully printing with the above patches:

https://photos.app.goo.gl/VGWgU8iyUwxpffFD8

  • The real-world plate from the table above (not attached, licensed model): fails today ("Assembly is too tall"), slices clean with this change.
  • The Squirtle plate from Fix sequential print collision check depending on object list order #630 as originally arranged: still fails (both shells' above-rod caps sit inside each other's sweep band), same message as before.
  • Plates that pass today still pass: two by-object plates that slice in stock 2.3.6 (a two-tower test plate at height-to-rod 30.5, and the rearranged Squirtle layout at 27.5) slice clean on this build. No new failures are possible in principle either, since the tested extent is a subset of the old one.
  • Rod gauge plates (rod_gauge.3mf, rod_gauge_low.3mf) slice clean, as before.

None of this is U1-specific; the check reads the same three profile values for every printer.

Related

zhouzengping and others added 14 commits August 17, 2026 18:38
…r#722)

The modal progress dialog in load_toolpaths() pumps the event loop,
allowing dispatched events to re-enter reset() and zero m_moves_count.
This causes unsigned underflow in reserve(m_moves_count -
biased_seams_ids.size()), throwing std::length_error.

Guard reset() with an m_loading flag armed via RAII ScopeGuard,
and move reset() before the flag is set. Replace manual
gcode_result.unlock() with ScopeGuard for exception safety.
Also add a defensive clamp on the ssid_count computation in
load_toolpaths() as a belt-and-suspenders measure.

Co-authored-by: zhangzhendong <zzdong0119@foxmail.com>
Sign macOS builds for branches matching refs/heads/release_* (e.g. release_2_3_6, release_2_3_7) and skip the unsigned DMG step for them so it no longer overwrites the notarized DMG.
…UI, preset and logging fixes (OrcaSlicer#735)

* fix:Modify the preset temperature value of the cold plate

* Fix dark-mode icons and layout shift in mixed filament batch dialog

- Center the preview placeholder by logical size (GetScaledSize) so the
  Retina-rasterized bitmap is no longer shifted toward the top-left on macOS
- Add _light icon variants for the add/remove and tray nav buttons, and set
  explicit disabled-state bitmaps (muted opposite-palette asset) so the four
  states are distinguishable in both themes
- Pin title rows to 20 DIP and manual-card rows to 30 DIP (matching the
  recommended card), and pin add/remove buttons to 16x16 DIP, so cards no
  longer shift when switching between recommended and manual modes
- Refine zh_CN translation of the mix-ratio range warning

* fix(gui): rescale batch match button on DPI/theme change

Button::Rescale() refreshes icons, re-measures the cached text
extent (messureSize) and re-applies the style. It was missing for
m_btn_batch_match in Sidebar::msw_rescale() and sys_color_changed(),
so the label drifted/clipped after a DPI or theme change while the
sibling flushing-volume button stayed correct.

* chore(log): downgrade GetFilamentInfo failure log to info (OrcaSlicer#727)

* Reset assembly view camera fit state when opening a project (OrcaSlicer#730)

* fix: prevent re-entrant reset crash in GCodeViewer::load()

The modal progress dialog in load_toolpaths() pumps the event loop,
allowing dispatched events to re-enter reset() and zero m_moves_count.
This causes unsigned underflow in reserve(m_moves_count -
biased_seams_ids.size()), throwing std::length_error.

Guard reset() with an m_loading flag armed via RAII ScopeGuard,
and move reset() before the flag is set. Replace manual
gcode_result.unlock() with ScopeGuard for exception safety.
Also add a defensive clamp on the ssid_count computation in
load_toolpaths() as a belt-and-suspenders measure.

* fix: disable macOS memory guard detection (OrcaSlicer#724)

- get_available_physical_memory() returns 0 on macOS, so the runtime
  memory guard skips sampling entirely (avail == 0 short-circuit in
  check_memory_guard): no low-memory dialog, no guard actions
- The vm_statistics64-based estimate counted free pages only and
  ignored reclaimable cache (inactive/purgeable), sitting far below
  the guard threshold on any normally-used system; it raised false
  low-memory warnings even for small models
- Windows and Linux behavior is untouched

* revert try catch for the mqtt connect. (OrcaSlicer#723)

* fix revert try catch for the mqtt connect.

* fix add try catch for mqtt.

* feature add the exception catch for mqtt.

* fix exception not catch question

---------

Co-authored-by: joyx_desktop <y.iesteem@gmail.com>
Co-authored-by: Kenshin627 <Kenshin627@users.noreply.github.com>
Co-authored-by: ZhangZheng <67276816+LuckZAE@users.noreply.github.com>
Co-authored-by: XieJiajun <68017138+PILIPALA030@users.noreply.github.com>
Co-authored-by: zackaree-shen <zackary_shen@qq.com>
Co-authored-by: Alves <LiuLikeQian@users.noreply.github.com>
…pdate (OrcaSlicer#733)

* fix: correct parent of title bar and task panel to content panel

The title bar and task panel were added to m_content_panel's sizer but
their parent was still 'this' (the dialog), so wxWidgets could not
locate/render them, leaving the download list blank. Reparent them to
m_content_panel so ownership matches the sizer they live in.

* fix: eliminate download popup flicker on Windows

- Use wxBORDER_NONE on Windows (wxBORDER_SIMPLE kept elsewhere)
- Enable double buffering on the popup subtree
- Repaint the border ring on every paint event on Windows

* chore: update flutter_web resources to v2.3.26 (build 20260817160540)

* chore: update flutter_web resources to v2.3.26 (build 20260818172502)

---------

Co-authored-by: YukiMacMini <yukimacmini@YukiMacMinideMac-mini.local>
…er#736)

- Remove the "Beta version" line drawn under the brand name
- Append a localized "Release" tag to the version string on the
  splash screen (zh_CN: 版本), rendered as "V2.3.6 版本"
- Add the "Release" msgid to the zh_CN catalog and the pot template;
  other languages fall back to English until translated
…aSlicer#738)

- SSWCP.cpp sw_WakeupFind(): the Bonjour kick block was left as a bare
  '{ ... } catch (...) {}' — restore the missing 'try' keyword so the
  catch has an associated try block (error C2318)
- MoonRaker.cpp Moonraker_Mqtt ctor: drop the stray '{' left over when
  the socket probe was wrapped in try/catch; the unbalanced brace kept
  the constructor open and cascaded C2601/C2065/C1075 errors

Both are one-line brace/keyword fixes; no logic changes. Verified with
a full Release build of Snapmaker_Orca on MSVC (0 errors).
TimelapseDownloadPopup.cpp (introduced in OrcaSlicer#733) and ParamsPanel.cpp use
wxWindowUpdateLocker without including <wx/wupdlock.h>; they only compiled
because the PCH (pchheader.hpp) pulls the header in. The Flatpak build sets
-DSLIC3R_PCH=OFF, so TimelapseDownloadPopup.cpp failed with
'wxWindowUpdateLocker was not declared in this scope' in CI (run 32143560654).
ParamsPanel.cpp has the same latent dependency and is fixed preemptively.

Same pattern as 46e6284 (MixedFilamentBatchDialog.cpp).
…cer#742)

Snapmaker.json references the preset via sub_path
"process/0.10mm Color Mixing @Snapmaker U1 (0.4 nozzle).json"
(lowercase), but the file on disk was named "(0.4 Nozzle)".
PresetBundle::load_vendor_configs_from_json resolves each manifest
entry by the exact sub_path string, so on case-sensitive filesystems
(Linux AppImage/Flatpak/deb) the open fails and loading of the whole
Snapmaker vendor bundle aborts with ConfigurationError.

Rename the file to match both the manifest sub_path and the preset's
own "name" field. No preset content changed. Audited all 570
sub_path entries in Snapmaker.json — this was the only mismatch.
The same mismatch also exists on main.
…er#759)

* Fix:从默认列表移除冷打板

* Hide Cool Steel Plate bed temperature rows in filament settings for U1 default list

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

---------

Co-authored-by: Claude Opus 4.7 <noreply@anthropic.com>
* fix: refresh sidebar nozzle UI on preset switch

Printer preset switches from non-sidebar entries (Machine Settings
combo, preset deletion, UnsavedChangesDialog transfer, physical
printer linkage) left the sidebar nozzle selector stale: old
diameter, old candidate list, dual-nozzle pages not rebuilt.

After a successful FFF printer preset switch in Tab::select_preset,
schedule a CallAfter refresh of Sidebar::update_nozzle_settings()
via a weak ref to the sidebar (shutdown/GUI recreation safe). Also
harden update_nozzle_settings():
- null-safe printer_variant read (bare configs lack the key; the
  old code dereferenced it unchecked)
- focus recorded before the destructive rebuild and only reassigned
  when it was inside the rebuilt notebook
- wxWindowUpdateLocker around the rebuild (no flicker)

The sidebar combo paths now rebuild once directly and once via the
deferred refresh; the second rebuild is idempotent.

Guard the plater dereference at schedule time: GUI_App::plater_ is
never re-nulled on MainFrame destruction, so a preset switch reached
during recreate_GUI teardown would otherwise dereference a dangling
pointer.

* fix: explicitly initialize nozzle diameter string in sidebar
…caSlicer#775)

* fix: resolve ambiguous ternary operands breaking GCC/Clang builds

wxEmptyString is a macro that expands to const wxChar* (wchar_t* in
unicode builds), so the conditional introduced in OrcaSlicer#769 mixed a raw
pointer with wxString. Each converts to the other implicitly, which
makes the conditional expression ambiguous per [expr.cond]: GCC 13
and Apple Clang reject it while MSVC accepts it, so only the Linux,
macOS and Flatpak CI jobs broke (run 32856432114).

Use wxString() so both operands share one type. No behavior change:
the empty branch still produces an empty string.

* chore: bump minimum required firmware version to 1.6.0
Replace the object-list-order sort in Print::sequential_print_clearance_valid
with a search for a valid print order: a topological sort over the
"must print before" constraints implied by extruder_clearance_height_to_rod
and extruder_clearance_height_to_lid. If a valid order exists it is used;
if none exists (a genuine, unavoidable collision) the original object-list
order is kept so the existing error is still reported.

Same change as Snapmaker#630 (and OrcaSlicer#14987).

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

The X rod sits extruder_clearance_height_to_rod above the nozzle and spans
the whole X axis, so the only part of an already-printed instance it can hit
while a later instance prints is the part that reaches above that height.
The check used each instance's whole footprint for the Y-overlap test, which
turns a 145 mm deep assembly with a 16 mm tip above the rod into a 145 mm
wide obstacle.

Compute, per instance, the Y extent of its geometry above the rod height
(any triangle with a vertex above the rod contributes all three vertices;
modifiers, blockers and negative volumes are skipped) and use that extent,
instead of the full footprint, both when building the print-order
constraints and in the final vertical clearance check. "Tall" becomes
"reaches above the rod", which is the same thing for objects on the bed and
correct for objects sunk into it. The later instance keeps its full
footprint plus the radius/2 reach, the lid rule and the horizontal
clearance check are unchanged.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@zackaree-shen

Copy link
Copy Markdown

@KuzuriAo
I am very glad to see your enthusiasm and contributions on this matter, and I am also very sorry that we have been busy recently and unable to respond quickly.
I will take some time to look at this PR.
At the same time, we have also started to pay attention to existing issues; hearing everyone's voices and feedback helps us become better.

@KuzuriAo

KuzuriAo commented Sep 2, 2026

Copy link
Copy Markdown
Author

@zackaree-shen I know you all are really busy, I totally understand. Launching something like the U1 and Snorca is no small undertaking.

I figure if it's something that's causing me problems, it's probably doing the same for others (based on the Snorca/Orca issues, it seems to be the case). So, when I have time I try and solve the problem for myself and when successful, I open a PR.

aceRage added a commit to aceRage/Snapmaker-Ultra that referenced this pull request Sep 4, 2026
…-793

fix(print): sequential clearance Kahn sort + above-rod Y extent (Snapmaker#630, Snapmaker#793)
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.

6 participants