Wipe tower: added the stabilization cone into configuration

This commit is contained in:
Lukas Matena 2023-03-16 10:07:48 +01:00
parent 26ba74fad0
commit b20325671a
13 changed files with 43 additions and 26 deletions

View file

@ -517,6 +517,7 @@ WipeTower::WipeTower(const PrintConfig& config, const std::vector<std::vector<fl
m_wipe_tower_width(float(config.wipe_tower_width)),
m_wipe_tower_rotation_angle(float(config.wipe_tower_rotation_angle)),
m_wipe_tower_brim_width(float(config.wipe_tower_brim_width)),
m_wipe_tower_cone_angle(float(config.wipe_tower_cone_angle)),
m_extra_spacing(float(config.wipe_tower_extra_spacing/100.)),
m_y_shift(0.f),
m_z_pos(0.f),
@ -1180,9 +1181,9 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
// This block creates the stabilization cone.
// First define a lambda to draw the rectangle with stabilization.
auto supported_rectangle = [this, &writer, spacing](const box_coordinates& wt_box, double feedrate, bool infill_cone) -> Polygon {
const auto [R, support_scale] = get_wipe_tower_cone_base(m_wipe_tower_width, m_wipe_tower_height, m_wipe_tower_depth);
const auto [R, support_scale] = get_wipe_tower_cone_base(m_wipe_tower_width, m_wipe_tower_height, m_wipe_tower_depth, m_wipe_tower_cone_angle);
double r = std::tan(Geometry::deg2rad(15.)) * (m_wipe_tower_height - m_layer_info->z);
double r = std::tan(Geometry::deg2rad(m_wipe_tower_cone_angle/2.f)) * (m_wipe_tower_height - m_layer_info->z);
Vec2f center = (wt_box.lu + wt_box.rd) / 2.;
double w = wt_box.lu.y() - wt_box.ld.y();
enum Type {
@ -1320,10 +1321,9 @@ WipeTower::ToolChangeResult WipeTower::finish_layer()
}
// Static method to get the radius and x-scaling of the stabilizing cone base.
std::pair<double, double> WipeTower::get_wipe_tower_cone_base(double width, double height, double depth)
std::pair<double, double> WipeTower::get_wipe_tower_cone_base(double width, double height, double depth, double angle_deg)
{
const double angle_deg = 15.;
double R = std::tan(Geometry::deg2rad(angle_deg)) * height;
double R = std::tan(Geometry::deg2rad(angle_deg/2.)) * height;
double fake_width = 0.66 * width;
double diag = std::hypot(fake_width / 2., depth / 2.);
double support_scale = 1.;

View file

@ -23,7 +23,7 @@ class WipeTower
public:
static const std::string never_skip_tag() { return "_GCODE_WIPE_TOWER_NEVER_SKIP_TAG"; }
static std::pair<double, double> get_wipe_tower_cone_base(double width, double height, double depth);
static std::pair<double, double> get_wipe_tower_cone_base(double width, double height, double depth, double angle_deg);
struct Extrusion
{
@ -257,6 +257,7 @@ private:
float m_wipe_tower_width; // Width of the wipe tower.
float m_wipe_tower_depth = 0.f; // Depth of the wipe tower
float m_wipe_tower_height = 0.f;
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
float m_wipe_tower_rotation_angle = 0.f; // Wipe tower rotation angle in degrees (with respect to x axis)

View file

@ -460,7 +460,7 @@ static std::vector<std::string> s_Preset_print_options {
"perimeter_extrusion_width", "external_perimeter_extrusion_width", "infill_extrusion_width", "solid_infill_extrusion_width",
"top_infill_extrusion_width", "support_material_extrusion_width", "infill_overlap", "infill_anchor", "infill_anchor_max", "bridge_flow_ratio",
"elefant_foot_compensation", "xy_size_compensation", "threads", "resolution", "gcode_resolution", "wipe_tower", "wipe_tower_x", "wipe_tower_y",
"wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"wipe_tower_width", "wipe_tower_cone_angle", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_bridging", "single_extruder_multi_material_priming", "mmu_segmented_region_max_width",
"wipe_tower_no_sparse_layers", "wipe_tower_extra_spacing", "compatible_printers", "compatible_printers_condition", "inherits",
"perimeter_generator", "wall_transition_length", "wall_transition_filter_deviation", "wall_transition_angle",
"wall_distribution_count", "min_feature_size", "min_bead_width"

View file

@ -205,6 +205,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|| opt_key == "wipe_tower"
|| opt_key == "wipe_tower_width"
|| opt_key == "wipe_tower_brim_width"
|| opt_key == "wipe_tower_cone_angle"
|| opt_key == "wipe_tower_bridging"
|| opt_key == "wipe_tower_extra_spacing"
|| opt_key == "wipe_tower_no_sparse_layers"
@ -1150,7 +1151,7 @@ std::vector<Point> Print::first_layer_wipe_tower_corners() const
// Now the stabilization cone.
Vec2d center = (pts[0] + pts[2])/2.;
const auto [cone_R, cone_x_scale] = WipeTower::get_wipe_tower_cone_base(m_config.wipe_tower_width, m_wipe_tower_data.height, m_wipe_tower_data.depth);
const auto [cone_R, cone_x_scale] = WipeTower::get_wipe_tower_cone_base(m_config.wipe_tower_width, m_wipe_tower_data.height, m_wipe_tower_data.depth, m_config.wipe_tower_cone_angle);
double r = cone_R + m_wipe_tower_data.brim_width;
for (double alpha = 0.; alpha<2*M_PI; alpha += M_PI/20.)
pts.emplace_back(center + r*Vec2d(std::cos(alpha)/cone_x_scale, std::sin(alpha)));

View file

@ -3150,6 +3150,16 @@ void PrintConfigDef::init_fff_params()
def->min = 0.;
def->set_default_value(new ConfigOptionFloat(2.));
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. "
"Larger angle means wider base.");
def->sidetext = L("°");
def->mode = comAdvanced;
def->min = 0.;
def->max = 90.;
def->set_default_value(new ConfigOptionFloat(0.));
def = this->add("wipe_tower_extra_spacing", coPercent);
def->label = L("Wipe tower purge lines spacing");
def->tooltip = L("Spacing of purge lines on the wipe tower.");

View file

@ -823,6 +823,7 @@ PRINT_CONFIG_CLASS_DERIVED_DEFINE(
((ConfigOptionFloat, wipe_tower_per_color_wipe))
((ConfigOptionFloat, wipe_tower_rotation_angle))
((ConfigOptionFloat, wipe_tower_brim_width))
((ConfigOptionFloat, wipe_tower_cone_angle))
((ConfigOptionPercent, wipe_tower_extra_spacing))
((ConfigOptionFloat, wipe_tower_bridging))
((ConfigOptionFloats, wiping_volumes_matrix))

View file

@ -480,11 +480,11 @@ int GLVolumeCollection::load_object_volume(
#if ENABLE_OPENGL_ES
int GLVolumeCollection::load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height,
float pos_x, float pos_y, float width, float depth, float height, float cone_angle,
float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh)
#else
int GLVolumeCollection::load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height,
float pos_x, float pos_y, float width, float depth, float height, float cone_angle,
float rotation_angle, bool size_unknown, float brim_width)
#endif // ENABLE_OPENGL_ES
{
@ -545,16 +545,18 @@ int GLVolumeCollection::load_wipe_tower_preview(
mesh.merge(brim_mesh);
// Now the stabilization cone and its base.
const auto [R, scale_x] = WipeTower::get_wipe_tower_cone_base(width, height, depth);
TriangleMesh cone_mesh(its_make_cone(R, height));
cone_mesh.scale(Vec3f(1.f/scale_x, 1.f, 1.f));
const auto [R, scale_x] = WipeTower::get_wipe_tower_cone_base(width, height, depth, cone_angle);
if (R > 0.) {
TriangleMesh cone_mesh(its_make_cone(R, height));
cone_mesh.scale(Vec3f(1.f/scale_x, 1.f, 1.f));
TriangleMesh disk_mesh(its_make_cylinder(R, brim_height));
disk_mesh.scale(Vec3f(1. / scale_x, 1., 1.)); // Now it matches the base, which may be elliptic.
disk_mesh.scale(Vec3f(1.f + scale_x*brim_width/R, 1.f + brim_width/R, 1.f)); // Scale so the brim is not deformed.
cone_mesh.merge(disk_mesh);
cone_mesh.translate(width / 2., depth / 2., 0.);
mesh.merge(cone_mesh);
TriangleMesh disk_mesh(its_make_cylinder(R, brim_height));
disk_mesh.scale(Vec3f(1. / scale_x, 1., 1.)); // Now it matches the base, which may be elliptic.
disk_mesh.scale(Vec3f(1.f + scale_x*brim_width/R, 1.f + brim_width/R, 1.f)); // Scale so the brim is not deformed.
cone_mesh.merge(disk_mesh);
cone_mesh.translate(width / 2., depth / 2., 0.);
mesh.merge(cone_mesh);
}
volumes.emplace_back(new GLVolume(color));

View file

@ -424,10 +424,10 @@ public:
#if ENABLE_OPENGL_ES
int load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
float pos_x, float pos_y, float width, float depth, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
#else
int load_wipe_tower_preview(
float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width);
float pos_x, float pos_y, float width, float depth, float height, float cone_angle, float rotation_angle, bool size_unknown, float brim_width);
#endif // ENABLE_OPENGL_ES
GLVolume* new_toolpath_volume(const ColorRGBA& rgba);

View file

@ -319,7 +319,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config)
toggle_field("standby_temperature_delta", have_ooze_prevention);
bool have_wipe_tower = config->opt_bool("wipe_tower");
for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width",
for (auto el : { "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle",
"wipe_tower_extra_spacing", "wipe_tower_bridging", "wipe_tower_no_sparse_layers", "single_extruder_multi_material_priming" })
toggle_field(el, have_wipe_tower);

View file

@ -2253,7 +2253,7 @@ void GCodeViewer::load_shells(const Print& print)
const WipeTowerData& wipe_tower_data = print.wipe_tower_data(extruders_count);
const float depth = wipe_tower_data.depth;
const float brim_width = wipe_tower_data.brim_width;
m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_rotation_angle,
m_shells.volumes.load_wipe_tower_preview(config.wipe_tower_x, config.wipe_tower_y, config.wipe_tower_width, depth, max_z, config.wipe_tower_cone_angle, config.wipe_tower_rotation_angle,
!print.is_step_done(psWipeTower), brim_width);
}
}

View file

@ -2035,17 +2035,18 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
const float w = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_width"))->value;
const float a = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_rotation_angle"))->value;
const float bw = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_brim_width"))->value;
const float ca = dynamic_cast<const ConfigOptionFloat*>(m_config->option("wipe_tower_cone_angle"))->value;
const Print *print = m_process->fff_print();
const float depth = print->wipe_tower_data(extruders_count).depth;
#if ENABLE_OPENGL_ES
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower),
x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw, &m_wipe_tower_mesh);
#else
int volume_idx_wipe_tower_new = m_volumes.load_wipe_tower_preview(
x, y, w, depth, (float)height, a, !print->is_step_done(psWipeTower),
x, y, w, depth, (float)height, ca, a, !print->is_step_done(psWipeTower),
bw);
#endif // ENABLE_OPENGL_ES
if (volume_idx_wipe_tower_old != -1)

View file

@ -2016,7 +2016,7 @@ Plater::priv::priv(Plater *q, MainFrame *main_frame)
, config(Slic3r::DynamicPrintConfig::new_from_defaults_keys({
"bed_shape", "bed_custom_texture", "bed_custom_model", "complete_objects", "duplicate_distance", "extruder_clearance_radius", "skirts", "skirt_distance",
"brim_width", "brim_separation", "brim_type", "variable_layer_height", "nozzle_diameter", "single_extruder_multi_material",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_extra_spacing",
"wipe_tower", "wipe_tower_x", "wipe_tower_y", "wipe_tower_width", "wipe_tower_rotation_angle", "wipe_tower_brim_width", "wipe_tower_cone_angle", "wipe_tower_extra_spacing",
"extruder_colour", "filament_colour", "material_colour", "max_print_height", "printer_model", "printer_technology",
// These values are necessary to construct SlicingParameters by the Canvas3D variable layer height editor.
"layer_height", "first_layer_height", "min_layer_height", "max_layer_height",

View file

@ -1602,6 +1602,7 @@ void TabPrint::build()
optgroup->append_single_option_line("wipe_tower_rotation_angle");
optgroup->append_single_option_line("wipe_tower_brim_width");
optgroup->append_single_option_line("wipe_tower_bridging");
optgroup->append_single_option_line("wipe_tower_cone_angle");
optgroup->append_single_option_line("wipe_tower_extra_spacing");
optgroup->append_single_option_line("wipe_tower_no_sparse_layers");
optgroup->append_single_option_line("single_extruder_multi_material_priming");