Rotate instead of shear for slicing stage (#30)

* initial commit

* fix upper bounds for assemblies

* significantly less Z shift issues, still not quite tamped down yet though

* add instrumentation to logs

* finally found the issue

* update printer defaults
This commit is contained in:
Joseph Robertson
2026-05-22 15:21:33 -05:00
committed by GitHub
parent 218881c6f6
commit a9bae54f20
16 changed files with 513 additions and 96 deletions
+66 -20
View File
@@ -4462,7 +4462,23 @@ void TabPrinter::build_fff()
belt_og->append_single_option_line("belt_printer");
belt_og->append_single_option_line("belt_printer_angle");
belt_og->append_single_option_line("belt_printer_infinite_y");
// Per-axis shear: group mode + angle + source on one row per axis
// Mesh rotate (default belt-side transform): isometric, no distortion.
// Shown above the per-axis shear/scale rows because most users should
// pick rotation; shear/scale is the expert escape hatch.
{
Line line = { L("Mesh rotate"),
L("Global mesh rotation applied before slicing. Isometric "
"(no distortion); the back-transform inverts it before the "
"machine-frame remap. Default belt transform. Mutually "
"exclusive with per-axis shear/scale in the UI.") };
line.append_option(belt_og->get_option("belt_slice_rotation"));
line.append_option(belt_og->get_option("belt_slice_rotation_angle"));
line.append_option(belt_og->get_option("belt_slice_rotation_global"));
belt_og->append_line(line);
}
// Per-axis shear/scale: expert escape hatch for non-rigid belt transforms
// (BlackBelt-style 1/sin scaling, asymmetric belt geometries, etc.).
// Group mode + angle + source on one row per axis.
{
Line line = { L("Mesh shear X"), L("Shear applied to the X axis before slicing") };
line.append_option(belt_og->get_option("belt_shear_x"));
@@ -5594,17 +5610,19 @@ void TabPrinter::toggle_options()
bool expert_or_above = (m_mode >= comExpert);
toggle_line("belt_printer_angle", is_belt);
toggle_line("belt_printer_infinite_y", is_belt);
// Mesh shear/scale: only shear Z and scale Y are shown in Advanced; the others
// are Expert-only. Each Line packs all its options on one row, so toggle the
// Line here in addition to the per-option mode gating.
// Mesh rotate: advanced (visible by default in belt mode).
toggle_line("belt_slice_rotation", is_belt);
// Mesh shear/scale: expert-only (the rigid rotation above is the
// primary belt transform; shear/scale is reserved for power users
// matching BlackBelt-style 1/sin scale or asymmetric belt geometries).
toggle_line("belt_shear_x", is_belt && expert_or_above);
toggle_line("belt_shear_y", is_belt && expert_or_above);
toggle_line("belt_shear_z", is_belt);
toggle_line("belt_shear_z", is_belt && expert_or_above);
toggle_line("belt_scale_x", is_belt && expert_or_above);
toggle_line("belt_scale_y", is_belt);
toggle_line("belt_scale_y", is_belt && expert_or_above);
toggle_line("belt_scale_z", is_belt && expert_or_above);
for (auto el : {"belt_mesh_transform_order",
"belt_origin_snap_x", "belt_origin_snap_y", "belt_origin_snap_z"})
toggle_line("belt_mesh_transform_order", is_belt && expert_or_above);
for (auto el : {"belt_origin_snap_x", "belt_origin_snap_y", "belt_origin_snap_z"})
toggle_line(el, is_belt);
// Remap, back-transform, and global mesh-transforms toggles are gated by belt
@@ -5619,31 +5637,59 @@ void TabPrinter::toggle_options()
// preslice_remap_global: superseded by belt_preslice_global
toggle_option("preslice_remap_global", is_belt && !belt_global);
// Mutual exclusion (UI only): slicing rotation and per-axis shear/scale are
// alternatives in the printer panel. The pipeline math composes them; this
// just disables the inactive set so users pick one path or the other.
auto rot_axis = m_config->option<ConfigOptionEnum<BeltRotationAxis>>("belt_slice_rotation")->value;
bool rotation_active = is_belt
&& rot_axis != BeltRotationAxis::None
&& std::abs(m_config->opt_float("belt_slice_rotation_angle")) > 1e-9;
bool shear_or_scale_active = is_belt && (
m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_x")->value != BeltShearMode::None ||
m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_y")->value != BeltShearMode::None ||
m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_z")->value != BeltShearMode::None ||
m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_x")->value != BeltScaleMode::None ||
m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_y")->value != BeltScaleMode::None ||
m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_z")->value != BeltScaleMode::None);
bool allow_shear_scale = !rotation_active;
bool allow_rotation = !shear_or_scale_active;
// Disable shear/scale mode dropdowns when rotation is active.
for (auto el : {"belt_shear_x", "belt_shear_y", "belt_shear_z",
"belt_scale_x", "belt_scale_y", "belt_scale_z",
"belt_mesh_transform_order"})
toggle_option(el, is_belt && allow_shear_scale);
// Disable rotation controls when any shear/scale is active.
toggle_option("belt_slice_rotation", is_belt && allow_rotation);
toggle_option("belt_slice_rotation_angle", is_belt && allow_rotation && rot_axis != BeltRotationAxis::None);
toggle_option("belt_slice_rotation_global", is_belt && allow_rotation && rot_axis != BeltRotationAxis::None);
// Gray out angle/from sub-options when their parent shear/scale mode is None.
// Per-axis globals are superseded when belt_preslice_global is on.
auto sx = m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_x")->value;
toggle_option("belt_shear_x_angle", is_belt && sx != BeltShearMode::None);
toggle_option("belt_shear_x_from", is_belt && sx != BeltShearMode::None);
toggle_option("belt_shear_x_global", is_belt && sx != BeltShearMode::None && !belt_global);
toggle_option("belt_shear_x_angle", is_belt && sx != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_x_from", is_belt && sx != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_x_global", is_belt && sx != BeltShearMode::None && !belt_global && allow_shear_scale);
auto sy = m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_y")->value;
toggle_option("belt_shear_y_angle", is_belt && sy != BeltShearMode::None);
toggle_option("belt_shear_y_from", is_belt && sy != BeltShearMode::None);
toggle_option("belt_shear_y_global", is_belt && sy != BeltShearMode::None && !belt_global);
toggle_option("belt_shear_y_angle", is_belt && sy != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_y_from", is_belt && sy != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_y_global", is_belt && sy != BeltShearMode::None && !belt_global && allow_shear_scale);
auto sz = m_config->option<ConfigOptionEnum<BeltShearMode>>("belt_shear_z")->value;
toggle_option("belt_shear_z_angle", is_belt && sz != BeltShearMode::None);
toggle_option("belt_shear_z_from", is_belt && sz != BeltShearMode::None);
toggle_option("belt_shear_z_global", is_belt && sz != BeltShearMode::None && !belt_global);
toggle_option("belt_shear_z_angle", is_belt && sz != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_z_from", is_belt && sz != BeltShearMode::None && allow_shear_scale);
toggle_option("belt_shear_z_global", is_belt && sz != BeltShearMode::None && !belt_global && allow_shear_scale);
auto scx = m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_x")->value;
toggle_option("belt_scale_x_angle", is_belt && scx != BeltScaleMode::None);
toggle_option("belt_scale_x_angle", is_belt && scx != BeltScaleMode::None && allow_shear_scale);
auto scy = m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_y")->value;
toggle_option("belt_scale_y_angle", is_belt && scy != BeltScaleMode::None);
toggle_option("belt_scale_y_angle", is_belt && scy != BeltScaleMode::None && allow_shear_scale);
auto scz = m_config->option<ConfigOptionEnum<BeltScaleMode>>("belt_scale_z")->value;
toggle_option("belt_scale_z_angle", is_belt && scz != BeltScaleMode::None);
toggle_option("belt_scale_z_angle", is_belt && scz != BeltScaleMode::None && allow_shear_scale);
// Machine-frame transforms: shown only in belt mode.
// Mirror the Advanced/Expert split used for mesh shear/scale.