mirror of
https://github.com/OrcaSlicer/OrcaSlicer.git
synced 2026-09-11 11:07:40 +00:00
Fixes for Wipe Tower Position Clamping
Validation grows the estimated body by the brim before the tower is generated, so a tower whose brim leaves the bed is rejected up front instead of at export. The scene reload re-clamps the stored position, since set_default_wipe_tower_pos_for_plate does not rerun when painting changes the filament count. The rectangle-wall footprint polygon gets its two missing brim corners (it was a skewed quad), so the post-generation check covers the whole brim.
This commit is contained in:
@@ -1046,6 +1046,7 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
|||||||
const WipeTowerData &wipe_tower_estimate = print.wipe_tower_data(filaments_count);
|
const WipeTowerData &wipe_tower_estimate = print.wipe_tower_data(filaments_count);
|
||||||
float width = wipe_tower_estimate.width;
|
float width = wipe_tower_estimate.width;
|
||||||
float depth = wipe_tower_estimate.depth;
|
float depth = wipe_tower_estimate.depth;
|
||||||
|
float brim_width = wipe_tower_estimate.brim_width;
|
||||||
|
|
||||||
Polygons convex_hulls_temp;
|
Polygons convex_hulls_temp;
|
||||||
if (print.has_wipe_tower()) {
|
if (print.has_wipe_tower()) {
|
||||||
@@ -1084,17 +1085,15 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
|||||||
// No gate on "is there a tower": one that is not printed estimates to zero, so the hull
|
// No gate on "is there a tower": one that is not printed estimates to zero, so the hull
|
||||||
// is degenerate and every check passes. Re-deriving it here missed the wrapping-detection
|
// is degenerate and every check passes. Re-deriving it here missed the wrapping-detection
|
||||||
// tower on a single-filament plate.
|
// tower on a single-filament plate.
|
||||||
// Pre-generation only the body square is tested — the auto-brim estimate can overshoot
|
// Pre-generation, grow the body by the brim to match what the generator draws;
|
||||||
// the generated brim by several mm and must not hard-fail a print that physically fits.
|
// post-generation the mesh already includes it.
|
||||||
// Post-generation the mesh bottom already includes the real brim, so the exact
|
|
||||||
// footprint is tested.
|
|
||||||
// The shared printable polygon is plate-local, while the tower polygons above are
|
|
||||||
// already shifted by the plate origin.
|
|
||||||
Polygons printable_polys = print.get_extruder_shared_printable_polygon();
|
Polygons printable_polys = print.get_extruder_shared_printable_polygon();
|
||||||
const Point plate_shift(scale_(plate_origin.x()), scale_(plate_origin.y()));
|
const Point plate_shift(scale_(plate_origin.x()), scale_(plate_origin.y()));
|
||||||
for (Polygon &p : printable_polys)
|
for (Polygon &p : printable_polys)
|
||||||
p.translate(plate_shift);
|
p.translate(plate_shift);
|
||||||
if (!diff(convex_hulls_temp, printable_polys).empty())
|
Polygons tower_polys_with_brim = print.is_step_done(psWipeTower) ?
|
||||||
|
convex_hulls_temp : offset(convex_hulls_temp, float(scale_(brim_width)));
|
||||||
|
if (!diff(tower_polys_with_brim, printable_polys).empty())
|
||||||
return {L("Prime Tower") + L(" is partially outside the printable area, and it cannot be printed.\n")};
|
return {L("Prime Tower") + L(" is partially outside the printable area, and it cannot be printed.\n")};
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
@@ -5961,8 +5960,8 @@ void WipeTowerData::construct_mesh(float width, float depth, float height, float
|
|||||||
wipe_tower_mesh_data->real_wipe_tower_mesh = make_cube(width, depth, height);
|
wipe_tower_mesh_data->real_wipe_tower_mesh = make_cube(width, depth, height);
|
||||||
wipe_tower_mesh_data->real_brim_mesh = make_cube(width + 2 * brim_width, depth + 2 * brim_width, first_layer_height);
|
wipe_tower_mesh_data->real_brim_mesh = make_cube(width + 2 * brim_width, depth + 2 * brim_width, first_layer_height);
|
||||||
wipe_tower_mesh_data->real_brim_mesh.translate({-brim_width, -brim_width, 0});
|
wipe_tower_mesh_data->real_brim_mesh.translate({-brim_width, -brim_width, 0});
|
||||||
wipe_tower_mesh_data->bottom = {scaled(Vec2f{-brim_width, -brim_width}), scaled(Vec2f{width + brim_width, 0}), scaled(Vec2f{width + brim_width, depth + brim_width}),
|
wipe_tower_mesh_data->bottom = {scaled(Vec2f{-brim_width, -brim_width}), scaled(Vec2f{width + brim_width, -brim_width}),
|
||||||
scaled(Vec2f{0, depth})};
|
scaled(Vec2f{width + brim_width, depth + brim_width}), scaled(Vec2f{-brim_width, depth + brim_width})};
|
||||||
} else {
|
} else {
|
||||||
wipe_tower_mesh_data->real_wipe_tower_mesh = WipeTower::its_make_rib_tower(width, depth, height, rib_length, rib_width, fillet_wall);
|
wipe_tower_mesh_data->real_wipe_tower_mesh = WipeTower::its_make_rib_tower(width, depth, height, rib_length, rib_width, fillet_wall);
|
||||||
wipe_tower_mesh_data->bottom = WipeTower::rib_section(width, depth, rib_length, rib_width, fillet_wall);
|
wipe_tower_mesh_data->bottom = WipeTower::rib_section(width, depth, rib_length, rib_width, fillet_wall);
|
||||||
|
|||||||
@@ -2906,8 +2906,20 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||||||
float brim_width = float(footprint.brim_width);
|
float brim_width = float(footprint.brim_width);
|
||||||
Vec3d wipe_tower_size(footprint.width, footprint.depth, footprint.height);
|
Vec3d wipe_tower_size(footprint.width, footprint.depth, footprint.height);
|
||||||
|
|
||||||
// The stored position is already clamped onto the bed, by
|
// set_default_wipe_tower_pos_for_plate doesn't rerun when painting changes the
|
||||||
// set_default_wipe_tower_pos_for_plate and again on every drag.
|
// filament count, so redo its clamp here on every reload.
|
||||||
|
{
|
||||||
|
Vec3d clamped_pos, clamped_size;
|
||||||
|
part_plate->estimate_wipe_tower_polygon(full_config, plate_id, clamped_pos, clamped_size);
|
||||||
|
if (std::abs(x - (float) clamped_pos(0)) > EPSILON || std::abs(y - (float) clamped_pos(1)) > EPSILON) {
|
||||||
|
x = (float) clamped_pos(0);
|
||||||
|
y = (float) clamped_pos(1);
|
||||||
|
ConfigOptionFloat wt_x_opt(x), wt_y_opt(y);
|
||||||
|
dynamic_cast<ConfigOptionFloats*>(proj_cfg.option("wipe_tower_x"))->set_at(&wt_x_opt, plate_id, 0);
|
||||||
|
dynamic_cast<ConfigOptionFloats*>(proj_cfg.option("wipe_tower_y"))->set_at(&wt_y_opt, plate_id, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) {
|
if (!current_print->is_step_done(psWipeTower) || !current_print->wipe_tower_data().wipe_tower_mesh_data) {
|
||||||
// update for wipe tower position
|
// update for wipe tower position
|
||||||
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
|
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(1000 + plate_id, x + plate_origin(0), y + plate_origin(1),
|
||||||
|
|||||||
Reference in New Issue
Block a user