mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-10-05 06:41:10 +00:00
Both change emitted G-code, which is why they were kept out of the extraction commit. Both are wrong only where the machine mapping is non-identity, which is the definition of each bug. 1. Suppress lifts commanded through an unknown position. _travel_to_z() emits full XYZ whenever the mapping must emit every axis, because the mapping can make machine Z depend on logical X/Y, and it builds that point from m_pos. At print start, and after any custom G-code that invalidates position, m_pos.xy is the uninitialised origin; mapping (0, 0, z) through a non-identity remap produces a real but wrong machine point -- for a reverse mapping, build_vol_max, i.e. the far corner of the bed. The subsequent full-XYZ move corrects the position, but the lift has already commanded a rapid across the whole bed at travel speed. Belt kinematics already guarded this; the Cartesian path did not. The guard is now applied at all three lift sites through must_skip_lift_now(), not just the one the extraction covered: travel_to_xyz()'s pending-lift branch, lazy_lift(spiral_vase=true), and eager_lift(). The latter two also needed the state fix -- both recorded m_lifted = target_lift regardless, so suppressing only the emission would leave a later unlift() descending from a height that was never commanded. 2. Never emit a G2/G3 arc a mapping cannot represent. extrude_arc_to_xy() emitted G2/G3 with logical X/Y and I/J and never consulted the mapping. There is no general fix by transforming the arc: a permutation moves it out of the XY plane that I/J describes, a negation reverses handedness, and the belt shear maps a circle to an ellipse that G2/G3 cannot express at all. So supports_arc_moves() gates generation through the existing GCode::should_disable_arc_fitting() hook, and BeltGCode's special-case override is deleted -- belt now gets the same behaviour from the general rule instead of its own exception. supports_arc_moves() is m_remap_x == 0 && m_remap_y == 1, not !has_axis_remap(): an arc emits only X/Y/I/J, so a mapping that merely negates or reverses Z leaves every emitted word untouched and keeps its arcs. The fallback for an unrepresentable arc tessellates it into linear segments at a 0.005mm chord tolerance rather than substituting a single chord, and splits dE proportionally across the segments. The capability check is hoisted above every extrusion mutation: an earlier form ran it after filament()->extrude(dE) and so extruded 2*dE on the fallback path. Known limits of that fallback, since it is worth stating rather than discovering: emitted relative E is conserved only to per-segment rounding (a radius-5 semicircle with dE=1.5 emits 1.50012 across 36 segments); the 0.005mm bound is a logical-frame bound, about 0.00855mm in machine space under a 45-degree belt shear; unequal endpoint radii and non-finite inputs are unchecked. Ordinary export takes the original polyline when the mapping rejects arcs, so this path is a fallback rather than the normal route. Known gap, not claimed fixed: classic wipe towers have their own enable_arc_fitting and their own G2/G3 emitter in GCode/WipeTower.cpp, which should_disable_arc_fitting() does not govern. Belt printers are barred from classic wipe towers; a remapped Cartesian printer is not. Tests in tests/fff_print/test_gcodewriter.cpp: reverse-X remap with unknown and with known position plus an identity control; eager_lift emitting nothing and recording nothing; the arc-capability matrix including the Z-only cases; and the tessellated fallback. E accounting is asserted through used_filament() rather than E(), which resets per line in relative-E mode. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011jgzj1sf53KMLPweZ8yeUQ
OrcaSlicer tests
Building, running and writing tests is documented on the wiki, under How to Test.
Two files here rather than there, because coding agents only read what is in the repository: