Add Brim chamfer of wipetower (#131)

This commit is contained in:
xiaoyeliu
2026-01-22 16:27:54 +08:00
committed by GitHub
parent 44f198e1ed
commit ebae587e55
9 changed files with 1105 additions and 14 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -3152,6 +3152,12 @@ int CLI::run(int argc, char **argv)
ConfigOptionFloat* volume_option = print_config.option<ConfigOptionFloat>("prime_volume", true);
float wipe_volume = volume_option->value;
ConfigOptionFloat* brim_chamfer_max_width_option = print_config.option<ConfigOptionFloat>("prime_tower_brim_chamfer_max_width", true);
float brim_chamfer_max_width = brim_chamfer_max_width_option->value;
ConfigOptionBool* brim_chamfer_option = print_config.option<ConfigOptionBool>("prime_tower_brim_chamfer", true);
bool brim_chamfer = brim_chamfer_option->value;
Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, wipe_volume, filaments_cnt);
plate_obj_size_info.wipe_depth = wipe_tower_size(1);
@@ -3882,6 +3888,8 @@ int CLI::run(int argc, char **argv)
ConfigOptionFloat* width_option = m_print_config.option<ConfigOptionFloat>("prime_tower_width", true);
ConfigOptionFloat* rotation_angle_option = m_print_config.option<ConfigOptionFloat>("wipe_tower_rotation_angle", true);
ConfigOptionFloat* volume_option = m_print_config.option<ConfigOptionFloat>("prime_volume", true);
ConfigOptionFloat* brim_chamfer_max_width_option = m_print_config.option<ConfigOptionFloat>("prime_tower_brim_chamfer_max_width", true);
ConfigOptionBool* brim_chamfer_option = m_print_config.option<ConfigOptionBool>("prime_tower_brim_chamfer", true);
BOOST_LOG_TRIVIAL(info) << boost::format("prime_tower_width %1% wipe_tower_rotation_angle %2% prime_volume %3%") % width_option->value % rotation_angle_option->value % volume_option->value;
@@ -4136,6 +4144,8 @@ int CLI::run(int argc, char **argv)
ConfigOptionFloat* width_option = m_print_config.option<ConfigOptionFloat>("prime_tower_width", true);
ConfigOptionFloat* rotation_angle_option = m_print_config.option<ConfigOptionFloat>("wipe_tower_rotation_angle", true);
ConfigOptionFloat* volume_option = m_print_config.option<ConfigOptionFloat>("prime_volume", true);
ConfigOptionFloat* brim_chamfer_max_width_option = m_print_config.option<ConfigOptionFloat>("prime_tower_brim_chamfer_max_width", true);
ConfigOptionBool* brim_chamfer_option = m_print_config.option<ConfigOptionBool>("prime_tower_brim_chamfer", true);
BOOST_LOG_TRIVIAL(info) << boost::format("prime_tower_width %1% wipe_tower_rotation_angle %2% prime_volume %3%")%width_option->value %rotation_angle_option->value %volume_option->value ;

View File

@@ -1255,6 +1255,8 @@ WipeTower2::WipeTower2(const PrintConfig& config, const PrintRegionConfig& defau
m_wipe_tower_width(float(config.prime_tower_width)),
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
m_wipe_tower_brim_width(float(config.prime_tower_brim_width)),
m_prime_tower_brim_chamfer(config.prime_tower_brim_chamfer),
m_prime_tower_brim_chamfer_max_width(float(config.prime_tower_brim_chamfer_max_width)),
m_wipe_tower_cone_angle(float(config.wipe_tower_cone_angle)),
m_extra_flow(float(config.wipe_tower_extra_flow/100.)),
m_extra_spacing_wipe(float(config.wipe_tower_extra_spacing/100. * config.wipe_tower_extra_flow/100.)),
@@ -2081,27 +2083,53 @@ WipeTower::ToolChangeResult WipeTower2::finish_layer()
poly = generate_support_rib_wall(writer, wt_box, feedrate, first_layer, m_wall_type == (int)wtwRib, true, false);
}
// brim (first layer only)
if (first_layer) {
// brim with chamfer (gradual layer-by-layer reduction)
int loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
// Apply chamfer reduction if feature is enabled and brim width is configured
if (m_wipe_tower_brim_width > 0 && m_prime_tower_brim_chamfer) {
if (!first_layer) {
// Calculate distance from first layer with tool changes
size_t current_idx = m_layer_info - m_plan.begin();
int dist_to_1st = (int)current_idx - (int)m_first_layer_idx;
// Stop print chamfer if depth changes
bool depth_changed = (m_layer_info->depth != m_plan[m_first_layer_idx].depth);
if (depth_changed) {
loops_num = 0;
}
else {
// Limit max chamfer width to configured value
int chamfer_loops_num = (int)(m_prime_tower_brim_chamfer_max_width / spacing);
loops_num = std::min(loops_num, chamfer_loops_num) - dist_to_1st;
// Ensure loops_num doesn't go negative
if (loops_num < 0) loops_num = 0;
}
}
}
if (loops_num > 0) {
writer.append("; WIPE_TOWER_BRIM_START\n");
size_t loops_num = (m_wipe_tower_brim_width + spacing/2.f) / spacing;
for (size_t i = 0; i < loops_num; ++ i) {
for (int i = 0; i < loops_num; ++i) {
poly = offset(poly, scale_(spacing)).front();
int cp = poly.closest_point_index(Point::new_scale(writer.x(), writer.y()));
writer.travel(unscale(poly.points[cp]).cast<float>());
for (int i=cp+1; true; ++i ) {
if (i==int(poly.points.size()))
i = 0;
writer.extrude(unscale(poly.points[i]).cast<float>());
if (i == cp)
for (int j = cp+1; true; ++j) {
if (j == int(poly.points.size()))
j = 0;
writer.extrude(unscale(poly.points[j]).cast<float>());
if (j == cp)
break;
}
}
writer.append("; WIPE_TOWER_BRIM_END\n");
// Save actual brim width to be later passed to the Print object, which will use it
// for skirt calculation and pass it to GLCanvas for precise preview box
m_wipe_tower_brim_width_real = loops_num * spacing;
// Save actual brim width only on first layer
if (first_layer) {
m_wipe_tower_brim_width_real = loops_num * spacing;
}
}
// Now prepare future wipe.

View File

@@ -189,6 +189,8 @@ private:
float m_wipe_tower_cone_angle = 0.f;
float m_wipe_tower_brim_width = 0.f; // Width of brim (mm) from config
float m_wipe_tower_brim_width_real = 0.f; // Width of brim (mm) after generation
bool m_prime_tower_brim_chamfer = true; // Enable/disable brim chamfer
float m_prime_tower_brim_chamfer_max_width = 4.f; // Max chamfer width (mm)
float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis)
float m_internal_rotation = 0.f;
float m_y_shift = 0.f; // y shift passed to writer

View File

@@ -839,7 +839,7 @@ static std::vector<std::string> s_Preset_print_options {
"skin_infill_line_width","skeleton_infill_line_width",
"top_surface_line_width", "support_line_width", "infill_wall_overlap","top_bottom_infill_wall_overlap", "bridge_flow", "internal_bridge_flow",
"elefant_foot_compensation", "elefant_foot_compensation_layers", "xy_contour_compensation", "xy_hole_compensation", "resolution", "enable_prime_tower",
"prime_tower_width", "prime_tower_brim_width", "prime_volume",
"prime_tower_width", "prime_tower_brim_width", "prime_volume", "prime_tower_brim_chamfer", "prime_tower_brim_chamfer_max_width",
"wipe_tower_no_sparse_layers", "compatible_printers", "compatible_printers_condition", "inherits",
"flush_into_infill", "flush_into_objects", "flush_into_support",
"tree_support_branch_angle", "tree_support_angle_slow", "tree_support_wall_count", "tree_support_top_rate", "tree_support_branch_distance", "tree_support_tip_diameter",

View File

@@ -294,6 +294,8 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower_no_sparse_layers"
|| opt_key == "flush_volumes_matrix"
|| opt_key == "prime_volume"
|| opt_key == "prime_tower_brim_chamfer"
|| opt_key == "prime_tower_brim_chamfer_max_width"
|| opt_key == "flush_into_infill"
|| opt_key == "flush_into_support"
|| opt_key == "initial_layer_infill_speed"

View File

@@ -5743,6 +5743,24 @@ void PrintConfigDef::init_fff_params()
def->min = 0.;
def->set_default_value(new ConfigOptionFloat(3.));
def = this->add("prime_tower_brim_chamfer", coBool);
def->label = L("Brim chamfer");
def->tooltip = L("Enable gradual layer-by-layer reduction of the brim around the prime tower. "
"This creates a chamfered/tapered effect, reducing material usage while "
"maintaining first layer adhesion.");
def->mode = comAdvanced;
def->set_default_value(new ConfigOptionBool(true));
def = this->add("prime_tower_brim_chamfer_max_width", coFloat);
def->label = L("Max chamfer width");
def->tooltip = L("Maximum width of the chamfer zone measured from the tower perimeter. "
"The brim will reduce within this distance. Larger values create a more "
"gradual taper but take more layers to complete.");
def->sidetext = "mm"; // milimeters, don't need translation
def->mode = comAdvanced;
def->min = 0.;
def->set_default_value(new ConfigOptionFloat(4.0));
def = this->add("wipe_tower_cone_angle", coFloat);
def->label = L("Stabilization cone apex angle");
def->tooltip = L("Angle at the apex of the cone that is used to stabilize the wipe tower. "

View File

@@ -1386,6 +1386,8 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_per_color_wipe))
((ConfigOptionFloat, wipe_tower_rotation_angle))
((ConfigOptionFloat, prime_tower_brim_width))
((ConfigOptionBool, prime_tower_brim_chamfer))
((ConfigOptionFloat, prime_tower_brim_chamfer_max_width))
((ConfigOptionFloat, wipe_tower_bridging))
((ConfigOptionPercent, wipe_tower_extra_flow))
((ConfigOptionFloats, flush_volumes_matrix))

View File

@@ -2414,6 +2414,8 @@ void TabPrint::build()
optgroup->append_single_option_line("prime_tower_width", "multimaterial_settings_prime_tower#width");
optgroup->append_single_option_line("prime_volume", "multimaterial_settings_prime_tower");
optgroup->append_single_option_line("prime_tower_brim_width", "multimaterial_settings_prime_tower#brim-width");
optgroup->append_single_option_line("prime_tower_brim_chamfer", "multimaterial_settings_prime_tower#brim-chamfer");
optgroup->append_single_option_line("prime_tower_brim_chamfer_max_width", "multimaterial_settings_prime_tower#brim-chamfer-max-width");
optgroup->append_single_option_line("wipe_tower_rotation_angle", "multimaterial_settings_prime_tower#wipe-tower-rotation-angle");
optgroup->append_single_option_line("wipe_tower_bridging", "multimaterial_settings_prime_tower#maximal-bridging-distance");
optgroup->append_single_option_line("wipe_tower_extra_spacing", "multimaterial_settings_prime_tower#wipe-tower-purge-lines-spacing");