ENH: add wrapping detection
jira: STUDIO-13192 Change-Id: I0fb5692b18cdb3b7af624a831dcfb0f635b165f0 (cherry picked from commit 89a8b6ea5e34340cba3750416ce3100dcc39f5c2) (cherry picked from commit 50bc8c10a7b4ddc0b2dfe9cbab438b9d307b7fc0)
This commit is contained in:
@@ -532,7 +532,7 @@ static int load_key_values_from_json(const std::string &file, std::map<std::stri
|
||||
}
|
||||
|
||||
static std::set<std::string> gcodes_key_set = {"filament_end_gcode", "filament_start_gcode", "change_filament_gcode", "layer_change_gcode", "machine_end_gcode", "machine_pause_gcode", "machine_start_gcode",
|
||||
"template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode"};
|
||||
"template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode"};
|
||||
|
||||
static void load_default_gcodes_to_config(DynamicPrintConfig& config, Preset::Type type)
|
||||
{
|
||||
@@ -569,6 +569,9 @@ static void load_default_gcodes_to_config(DynamicPrintConfig& config, Preset::Ty
|
||||
|
||||
ConfigOptionString* timeplase_gcode_opt = config.option<ConfigOptionString>("time_lapse_gcode", true);
|
||||
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__<< ", time_lapse_gcode: "<<timeplase_gcode_opt->value;
|
||||
|
||||
ConfigOptionString *wrapping_detection_gcode_opt = config.option<ConfigOptionString>("wrapping_detection_gcode", true);
|
||||
BOOST_LOG_TRIVIAL(trace) << __FUNCTION__ << ", wrapping_detection_gcode: " << wrapping_detection_gcode_opt->value;
|
||||
}
|
||||
else if (type == Preset::TYPE_FILAMENT)
|
||||
{
|
||||
@@ -3631,7 +3634,10 @@ int CLI::run(int argc, char **argv)
|
||||
ConfigOptionFloats* volume_option = print_config.option<ConfigOptionFloats>("filament_prime_volume", true);
|
||||
std::vector<double> wipe_volume = volume_option->values;
|
||||
|
||||
Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, get_max_element(wipe_volume), new_extruder_count, filaments_cnt);
|
||||
const ConfigOptionBool * wrapping_detection = print_config.option<ConfigOptionBool>("enable_wrapping_detection");
|
||||
bool enable_wrapping = (wrapping_detection != nullptr) && wrapping_detection->value;
|
||||
|
||||
Vec3d wipe_tower_size = plate->estimate_wipe_tower_size(print_config, plate_obj_size_info.wipe_width, get_max_element(wipe_volume), new_extruder_count, filaments_cnt, false, enable_wrapping);
|
||||
plate_obj_size_info.wipe_width = wipe_tower_size(0);
|
||||
plate_obj_size_info.wipe_depth = wipe_tower_size(1);
|
||||
|
||||
@@ -4771,7 +4777,10 @@ int CLI::run(int argc, char **argv)
|
||||
|
||||
//float depth = v * (filaments_cnt - 1) / (layer_height * w);
|
||||
|
||||
Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, get_max_element(v), new_extruder_count, filaments_cnt);
|
||||
const ConfigOptionBool *wrapping_detection = m_print_config.option<ConfigOptionBool>("enable_wrapping_detection");
|
||||
bool enable_wrapping = (wrapping_detection != nullptr) && wrapping_detection->value;
|
||||
|
||||
Vec3d wipe_tower_size = cur_plate->estimate_wipe_tower_size(m_print_config, w, get_max_element(v), new_extruder_count, filaments_cnt, false, enable_wrapping);
|
||||
Vec3d plate_origin = cur_plate->get_origin();
|
||||
int plate_width, plate_depth, plate_height;
|
||||
partplate_list.get_plate_size(plate_width, plate_depth, plate_height);
|
||||
|
||||
@@ -1322,7 +1322,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
wipe_tower_z = m_last_wipe_tower_print_z + m_tool_changes[m_layer_idx].front().layer_height;
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
if ((m_enable_timelapse_print || m_enable_wrapping_detection) && m_is_first_print) {
|
||||
gcode += append_tcr(gcodegen, m_tool_changes[m_layer_idx][0], m_tool_changes[m_layer_idx][0].new_tool, wipe_tower_z);
|
||||
m_tool_change_idx++;
|
||||
m_is_first_print = false;
|
||||
@@ -1353,7 +1353,7 @@ static std::vector<Vec2d> get_path_of_change_filament(const Print& print)
|
||||
ignore_sparse = (m_tool_changes[m_layer_idx].size() == 1 && m_tool_changes[m_layer_idx].front().initial_tool == m_tool_changes[m_layer_idx].front().new_tool);
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && m_is_first_print) {
|
||||
if ((m_enable_timelapse_print || m_enable_wrapping_detection) && m_is_first_print) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1752,6 +1752,7 @@ namespace DoExport {
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Before layer change G-code")), config.before_layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Layer change G-code")), config.layer_change_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Timelapse G-code")), config.time_lapse_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Timelapse G-code")), config.wrapping_detection_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Change filament G-code")), config.change_filament_gcode.value);
|
||||
if (ret.size() < MAX_TAGS_COUNT) check(_(L("Printing by object G-code")), config.printing_by_object_gcode.value);
|
||||
//if (ret.size() < MAX_TAGS_COUNT) check(_(L("Color Change G-code")), config.color_change_gcode.value);
|
||||
@@ -3015,7 +3016,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato
|
||||
// Prusa Multi-Material wipe tower.
|
||||
if (has_wipe_tower && ! layers_to_print.empty()) {
|
||||
m_wipe_tower.reset(new WipeTowerIntegration(print.config(), print.get_plate_index(), print.get_plate_origin(), *print.wipe_tower_data().priming.get(),
|
||||
print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get()));
|
||||
print.wipe_tower_data().tool_changes, *print.wipe_tower_data().final_purge.get(), print.get_slice_used_filaments(false)));
|
||||
m_wipe_tower->set_wipe_tower_depth(print.get_wipe_tower_depth());
|
||||
m_wipe_tower->set_wipe_tower_bbx(print.get_wipe_tower_bbx());
|
||||
m_wipe_tower->set_rib_offset(print.get_rib_offset());
|
||||
@@ -4688,6 +4689,30 @@ LayerResult GCode::process_layer(
|
||||
if (m_wipe_tower)
|
||||
m_wipe_tower->set_is_first_print(true);
|
||||
|
||||
auto insert_wrapping_detection_gcode = [this, &print, &print_z, &most_used_extruder]() -> std::string {
|
||||
std::string wrapping_gcode;
|
||||
if (print.config().enable_wrapping_detection && !print.config().wrapping_detection_gcode.value.empty()) {
|
||||
DynamicConfig config;
|
||||
config.set_key_value("layer_num", new ConfigOptionInt(m_layer_index));
|
||||
config.set_key_value("layer_z", new ConfigOptionFloat(print_z));
|
||||
config.set_key_value("max_layer_z", new ConfigOptionFloat(m_max_layer_z));
|
||||
config.set_key_value("most_used_physical_extruder_id", new ConfigOptionInt(m_config.physical_extruder_map.get_at(most_used_extruder)));
|
||||
config.set_key_value("curr_physical_extruder_id", new ConfigOptionInt(m_config.physical_extruder_map.get_at(m_writer.filament()->extruder_id())));
|
||||
wrapping_gcode = this->placeholder_parser_process("wrapping_detection_gcode", print.config().wrapping_detection_gcode.value, m_writer.filament()->id(), &config) +"\n";
|
||||
}
|
||||
m_writer.set_current_position_clear(false);
|
||||
|
||||
double temp_z_after_tool_change;
|
||||
if (GCodeProcessor::get_last_z_from_gcode(wrapping_gcode, temp_z_after_tool_change)) {
|
||||
Vec3d pos = m_writer.get_position();
|
||||
pos(2) = temp_z_after_tool_change;
|
||||
m_writer.set_position(pos);
|
||||
}
|
||||
return wrapping_gcode;
|
||||
};
|
||||
|
||||
bool has_insert_wrapping_detection_gcode = false;
|
||||
|
||||
// Extrude the skirt, brim, support, perimeters, infill ordered by the extruders.
|
||||
for (unsigned int extruder_id : layer_tools.extruders)
|
||||
{
|
||||
@@ -4714,6 +4739,12 @@ LayerResult GCode::process_layer(
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!has_insert_wrapping_detection_gcode) {
|
||||
gcode += this->retract(false, false, auto_lift_type);
|
||||
gcode += insert_wrapping_detection_gcode();
|
||||
has_insert_wrapping_detection_gcode = true;
|
||||
}
|
||||
gcode_toolchange = m_wipe_tower->tool_change(*this, extruder_id, extruder_id == layer_tools.extruders.back());
|
||||
}
|
||||
} else {
|
||||
@@ -4726,6 +4757,13 @@ LayerResult GCode::process_layer(
|
||||
gcode += insert_timelapse_gcode();
|
||||
has_insert_timelapse_gcode = true;
|
||||
}
|
||||
|
||||
if (!has_insert_wrapping_detection_gcode) {
|
||||
gcode += this->retract(false, false, auto_lift_type);
|
||||
gcode += insert_wrapping_detection_gcode();
|
||||
has_insert_wrapping_detection_gcode = true;
|
||||
}
|
||||
|
||||
gcode_toolchange = this->set_extruder(extruder_id, print_z);
|
||||
}
|
||||
if (!gcode_toolchange.empty()) {
|
||||
|
||||
@@ -81,7 +81,8 @@ public:
|
||||
const Vec3d plate_origin,
|
||||
const std::vector<WipeTower::ToolChangeResult> &priming,
|
||||
const std::vector<std::vector<WipeTower::ToolChangeResult>> &tool_changes,
|
||||
const WipeTower::ToolChangeResult &final_purge) :
|
||||
const WipeTower::ToolChangeResult &final_purge,
|
||||
const std::vector<unsigned int> &slice_used_filaments) :
|
||||
m_left(/*float(print_config.wipe_tower_x.value)*/ 0.f),
|
||||
m_right(float(/*print_config.wipe_tower_x.value +*/ print_config.prime_tower_width.value)),
|
||||
m_wipe_tower_pos(float(print_config.wipe_tower_x.get_at(plate_idx)), float(print_config.wipe_tower_y.get_at(plate_idx))),
|
||||
@@ -94,6 +95,7 @@ public:
|
||||
m_plate_origin(plate_origin),
|
||||
m_single_extruder_multi_material(print_config.single_extruder_multi_material),
|
||||
m_enable_timelapse_print(print_config.timelapse_type.value == TimelapseType::tlSmooth),
|
||||
m_enable_wrapping_detection(print_config.enable_wrapping_detection && (slice_used_filaments.size() <= 1)),
|
||||
m_is_first_print(true),
|
||||
m_print_config(&print_config)
|
||||
{
|
||||
@@ -147,6 +149,7 @@ private:
|
||||
Vec3d m_plate_origin;
|
||||
bool m_single_extruder_multi_material;
|
||||
bool m_enable_timelapse_print;
|
||||
bool m_enable_wrapping_detection;
|
||||
bool m_is_first_print;
|
||||
const PrintConfig * m_print_config;
|
||||
float m_wipe_tower_depth;
|
||||
|
||||
@@ -780,9 +780,18 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||
for (int i = int(m_layer_tools.size()) - 2; i >= 0; -- i)
|
||||
m_layer_tools[i].wipe_tower_partitions = std::max(m_layer_tools[i + 1].wipe_tower_partitions, m_layer_tools[i].wipe_tower_partitions);
|
||||
|
||||
|
||||
int wrapping_layer_nums = config.wrapping_detection_layers;
|
||||
for (size_t i = 0; i < wrapping_layer_nums; ++i) {
|
||||
if (i >= m_layer_tools.size())
|
||||
break;
|
||||
LayerTools < = m_layer_tools[i];
|
||||
lt.has_wipe_tower = config.enable_wrapping_detection;
|
||||
}
|
||||
|
||||
//FIXME this is a hack to get the ball rolling.
|
||||
for (LayerTools < : m_layer_tools)
|
||||
lt.has_wipe_tower = (lt.has_object && (config.timelapse_type == TimelapseType::tlSmooth || lt.wipe_tower_partitions > 0))
|
||||
lt.has_wipe_tower |= (lt.has_object && (config.timelapse_type == TimelapseType::tlSmooth || lt.wipe_tower_partitions > 0))
|
||||
|| lt.print_z < object_bottom_z + EPSILON;
|
||||
|
||||
// Test for a raft, insert additional wipe tower layer to fill in the raft separation gap.
|
||||
@@ -840,7 +849,8 @@ void ToolOrdering::fill_wipe_tower_partitions(const PrintConfig &config, coordf_
|
||||
double last_wipe_tower_print_z = lt_next.print_z;
|
||||
while (++j < m_layer_tools.size()-1 && !m_layer_tools[j].has_wipe_tower)
|
||||
if (m_layer_tools[j+1].print_z - last_wipe_tower_print_z > max_layer_height + EPSILON) {
|
||||
m_layer_tools[j].has_wipe_tower = true;
|
||||
if (!config.enable_wrapping_detection)
|
||||
m_layer_tools[j].has_wipe_tower = true;
|
||||
last_wipe_tower_print_z = m_layer_tools[j].print_z;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -428,7 +428,7 @@ static Polylines remove_points_from_polygon(const Polygon &polygon, const std::v
|
||||
for (auto &p : tmp_poly) points.push_back(unscale(p).cast<float>());
|
||||
points.pop_back();
|
||||
}
|
||||
|
||||
|
||||
for (int i = 0; i < skip_points.size(); i++) {
|
||||
for (int j = 0; j < points.size(); j++) {
|
||||
Vec2f& p1 = points[j];
|
||||
@@ -1315,6 +1315,9 @@ WipeTower::ToolChangeResult WipeTower::construct_block_tcr(WipeTowerWriter &writ
|
||||
return result;
|
||||
}
|
||||
|
||||
// BBS
|
||||
const double wrapping_wipe_tower_depth = 10;
|
||||
|
||||
// BBS
|
||||
const std::map<float, float> WipeTower::min_depth_per_height = {
|
||||
{5.f,5.f}, {100.f, 20.f}, {250.f, 40.f}, {350.f, 60.f}
|
||||
@@ -1479,7 +1482,7 @@ TriangleMesh WipeTower::its_make_rib_brim(const Polygon& brim, float layer_heigh
|
||||
}
|
||||
|
||||
|
||||
WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origin, size_t initial_tool, const float wipe_tower_height) :
|
||||
WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origin, size_t initial_tool, const float wipe_tower_height, const std::vector<unsigned int>& slice_used_filaments) :
|
||||
m_semm(config.single_extruder_multi_material.value),
|
||||
m_wipe_tower_pos(config.wipe_tower_x.get_at(plate_idx), config.wipe_tower_y.get_at(plate_idx)),
|
||||
m_wipe_tower_width(float(config.prime_tower_width)),
|
||||
@@ -1497,6 +1500,9 @@ WipeTower::WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origi
|
||||
m_current_tool(initial_tool),
|
||||
//wipe_volumes(flush_matrix)
|
||||
m_enable_timelapse_print(config.timelapse_type.value == TimelapseType::tlSmooth),
|
||||
m_enable_wrapping_detection(config.enable_wrapping_detection),
|
||||
m_wrapping_detection_layers(config.wrapping_detection_layers.value),
|
||||
m_slice_used_filaments(slice_used_filaments.size()),
|
||||
m_filaments_change_length(config.filament_change_length.values),
|
||||
m_is_multi_extruder(config.nozzle_diameter.size() > 1),
|
||||
m_use_gap_wall(config.prime_tower_skip_points.value),
|
||||
@@ -2524,6 +2530,9 @@ void WipeTower::plan_tower()
|
||||
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(m_wipe_tower_height);
|
||||
|
||||
{
|
||||
if (m_enable_wrapping_detection && max_depth < EPSILON)
|
||||
max_depth = wrapping_wipe_tower_depth;
|
||||
|
||||
if (m_enable_timelapse_print && max_depth < EPSILON)
|
||||
max_depth = min_wipe_tower_depth;
|
||||
|
||||
@@ -2575,6 +2584,9 @@ void WipeTower::plan_tower()
|
||||
for (int layer_index = int(m_plan.size()) - 1; layer_index >= 0; --layer_index)
|
||||
{
|
||||
float this_layer_depth = std::max(m_plan[layer_index].depth, m_plan[layer_index].toolchanges_depth());
|
||||
if (m_enable_wrapping_detection && (layer_index < m_wrapping_detection_layers) && this_layer_depth < EPSILON)
|
||||
this_layer_depth = wrapping_wipe_tower_depth;
|
||||
|
||||
if (m_enable_timelapse_print && this_layer_depth < EPSILON)
|
||||
this_layer_depth = min_wipe_tower_depth;
|
||||
|
||||
@@ -2593,6 +2605,14 @@ void WipeTower::plan_tower()
|
||||
max_depth_for_all = m_plan[0].depth;
|
||||
}
|
||||
|
||||
if (m_enable_wrapping_detection) {
|
||||
for (int i = m_wrapping_detection_layers - 1; i >= 0; i--) {
|
||||
if (m_plan.size() <= m_wrapping_detection_layers && (m_plan[i].depth < wrapping_wipe_tower_depth)) {
|
||||
m_plan[i].depth = wrapping_wipe_tower_depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print) {
|
||||
for (int i = int(m_plan.size()) - 1; i >= 0; i--) {
|
||||
m_plan[i].depth = max_depth_for_all;
|
||||
@@ -3556,7 +3576,7 @@ void WipeTower::update_all_layer_depth(float wipe_tower_depth)
|
||||
if (m_wipe_tower_depth > 0)
|
||||
m_wipe_tower_depth += start_offset;
|
||||
|
||||
if (m_enable_timelapse_print) {
|
||||
if (m_enable_wrapping_detection || m_enable_timelapse_print) {
|
||||
if (is_approx(m_wipe_tower_depth, 0.f))
|
||||
m_wipe_tower_depth = wipe_tower_depth;
|
||||
for (WipeTowerInfo &plan_info : m_plan) {
|
||||
@@ -3700,6 +3720,13 @@ void WipeTower::plan_tower_new()
|
||||
|
||||
// only for get m_extra_spacing
|
||||
{
|
||||
if (m_enable_wrapping_detection && max_depth < EPSILON) {
|
||||
max_depth = wrapping_wipe_tower_depth;
|
||||
if (m_use_rib_wall) {
|
||||
m_wipe_tower_width = max_depth;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && max_depth < EPSILON) {
|
||||
max_depth = min_wipe_tower_depth;
|
||||
if (m_use_rib_wall) { m_wipe_tower_width = max_depth; }
|
||||
@@ -3877,6 +3904,7 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
};
|
||||
int wall_idx = get_wall_filament_for_this_layer();
|
||||
|
||||
bool only_generate_wall = m_enable_timelapse_print || (m_enable_wrapping_detection && m_slice_used_filaments <= 1);
|
||||
// this layer has no tool_change
|
||||
if (wall_idx == -1) {
|
||||
bool need_insert_solid_infill = false;
|
||||
@@ -3890,10 +3918,10 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
if (need_insert_solid_infill) {
|
||||
wall_idx = m_current_tool;
|
||||
} else {
|
||||
if (m_enable_timelapse_print) {
|
||||
if (only_generate_wall) {
|
||||
timelapse_wall = only_generate_out_wall(true);
|
||||
}
|
||||
finish_layer_tcr = finish_layer_new(m_enable_timelapse_print ? false : true, layer.extruder_fill);
|
||||
finish_layer_tcr = finish_layer_new(only_generate_wall ? false : true, layer.extruder_fill);
|
||||
std::for_each(m_wipe_tower_blocks.begin(), m_wipe_tower_blocks.end(), [this](WipeTowerBlock &block) {
|
||||
block.finish_depth[this->m_cur_layer_id] = block.start_depth;
|
||||
});
|
||||
@@ -3903,13 +3931,13 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
// generate tool change
|
||||
bool insert_wall = false;
|
||||
int insert_finish_layer_idx = -1;
|
||||
if (wall_idx != -1 && m_enable_timelapse_print) {
|
||||
if (wall_idx != -1 && only_generate_wall) {
|
||||
timelapse_wall = only_generate_out_wall(true);
|
||||
}
|
||||
for (int i = 0; i < int(layer.tool_changes.size()); ++i) {
|
||||
ToolChangeResult wall_gcode;
|
||||
if (i == 0 && (layer.tool_changes[i].old_tool == wall_idx)) {
|
||||
finish_layer_tcr = finish_layer_new(m_enable_timelapse_print ? false : true, false, false);
|
||||
finish_layer_tcr = finish_layer_new(only_generate_wall ? false : true, false, false);
|
||||
}
|
||||
const auto * block = get_block_by_category(m_filpar[layer.tool_changes[i].new_tool].category, false);
|
||||
int id = std::find_if(m_wipe_tower_blocks.begin(), m_wipe_tower_blocks.end(), [&](const WipeTowerBlock &b) { return &b == block; }) - m_wipe_tower_blocks.begin();
|
||||
@@ -3924,7 +3952,7 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
|
||||
}
|
||||
else if (layer.tool_changes[i].new_tool == wall_idx) {
|
||||
finish_layer_tcr = finish_layer_new(m_enable_timelapse_print ? false : true, false, false);
|
||||
finish_layer_tcr = finish_layer_new(only_generate_wall ? false : true, false, false);
|
||||
insert_finish_layer_idx = i;
|
||||
}
|
||||
}
|
||||
@@ -3933,7 +3961,7 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
// insert finish block
|
||||
if (wall_idx != -1) {
|
||||
if (layer.tool_changes.empty()) {
|
||||
finish_layer_tcr = finish_layer_new(m_enable_timelapse_print ? false : true, false, false);
|
||||
finish_layer_tcr = finish_layer_new(only_generate_wall ? false : true, false, false);
|
||||
}
|
||||
|
||||
for (WipeTowerBlock& block : m_wipe_tower_blocks) {
|
||||
@@ -4016,7 +4044,7 @@ void WipeTower::generate_new(std::vector<std::vector<WipeTower::ToolChangeResult
|
||||
layer_result[insert_finish_layer_idx] = merge_tcr(layer_result[insert_finish_layer_idx], finish_layer_tcr);
|
||||
}
|
||||
|
||||
if (m_enable_timelapse_print && !timelapse_wall.gcode.empty()) {
|
||||
if (only_generate_wall && !timelapse_wall.gcode.empty()) {
|
||||
layer_result.insert(layer_result.begin(), std::move(timelapse_wall));
|
||||
}
|
||||
result.emplace_back(std::move(layer_result));
|
||||
@@ -4161,7 +4189,7 @@ WipeTower::ToolChangeResult WipeTower::only_generate_out_wall(bool is_new_mode)
|
||||
// BBS
|
||||
|
||||
float wipe_tower_depth = m_layer_info->depth + m_perimeter_width;
|
||||
if (is_new_mode && m_enable_timelapse_print)
|
||||
if (is_new_mode && (m_enable_timelapse_print || m_enable_wrapping_detection))
|
||||
wipe_tower_depth = m_wipe_tower_depth;
|
||||
box_coordinates wt_box(Vec2f(0.f, (m_current_shape == SHAPE_REVERSED ? m_layer_info->toolchanges_depth() : 0.f)), m_wipe_tower_width, wipe_tower_depth);
|
||||
wt_box = align_perimeter(wt_box);
|
||||
|
||||
@@ -175,7 +175,7 @@ public:
|
||||
// width -- width of wipe tower in mm ( default 60 mm - leave as it is )
|
||||
// wipe_area -- space available for one toolchange in mm
|
||||
// BBS: add partplate logic
|
||||
WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origin, size_t initial_tool, const float wipe_tower_height);
|
||||
WipeTower(const PrintConfig& config, int plate_idx, Vec3d plate_origin, size_t initial_tool, const float wipe_tower_height, const std::vector<unsigned int>& slice_used_filaments);
|
||||
|
||||
|
||||
// Set the extruder properties.
|
||||
@@ -405,6 +405,9 @@ private:
|
||||
return m_filpar[0].filament_area; // all extruders are assumed to have the same filament diameter at this point
|
||||
}
|
||||
|
||||
int m_slice_used_filaments = 0;
|
||||
int m_wrapping_detection_layers = 0;
|
||||
bool m_enable_wrapping_detection = false;
|
||||
bool m_enable_timelapse_print = false;
|
||||
bool m_semm = true; // Are we using a single extruder multimaterial printer?
|
||||
bool m_purge_in_prime_tower = false; // Do we purge in the prime tower?
|
||||
|
||||
@@ -75,4 +75,33 @@ int get_index_for_extruder_parameter(const DynamicPrintConfig &config, const std
|
||||
return variant_index;
|
||||
}
|
||||
|
||||
std::vector<Vec2d> get_wrapping_detection_area(const std::vector<Vec2d> &wrapping_detection_path, double avoidance_radius)
|
||||
{
|
||||
if (wrapping_detection_path.empty())
|
||||
return std::vector<Vec2d>();
|
||||
|
||||
double min_x = wrapping_detection_path[0](0);
|
||||
double max_x = wrapping_detection_path[0](0);
|
||||
double min_y = wrapping_detection_path[0](1);
|
||||
double max_y = wrapping_detection_path[0](1);
|
||||
|
||||
for (const Vec2d& pt : wrapping_detection_path) {
|
||||
if (pt(0) < min_x)
|
||||
min_x = pt(0);
|
||||
if (pt(0) > max_x)
|
||||
max_x = pt(0);
|
||||
if (pt(1) < min_y)
|
||||
min_y = pt(1);
|
||||
if (pt(1) > max_y)
|
||||
max_y = pt(1);
|
||||
}
|
||||
|
||||
min_x = min_x - avoidance_radius;
|
||||
min_y = min_y - avoidance_radius;
|
||||
max_x = max_x + avoidance_radius;
|
||||
max_y = max_y + avoidance_radius;
|
||||
|
||||
return {{min_x, min_y}, {max_x, min_y}, {max_x, max_y}, {min_x, max_y}};
|
||||
}
|
||||
|
||||
}; // namespace Slic3r
|
||||
|
||||
@@ -11,6 +11,8 @@ std::vector<LayerPrintSequence> get_other_layers_print_sequence(int sequence_num
|
||||
void get_other_layers_print_sequence(const std::vector<LayerPrintSequence> &customize_sequences, int &sequence_nums, std::vector<int> &sequence);
|
||||
|
||||
extern int get_index_for_extruder_parameter(const DynamicPrintConfig &config, const std::string &opt_key, int cur_extruder_id, ExtruderType extruder_type, NozzleVolumeType nozzle_volume_type);
|
||||
|
||||
extern std::vector<Vec2d> get_wrapping_detection_area(const std::vector<Vec2d> &wrapping_detection_path, double avoidance_radius);
|
||||
} // namespace Slic3r
|
||||
|
||||
#endif // slic3r_Parameter_Utils_hpp_
|
||||
|
||||
@@ -997,13 +997,13 @@ static std::vector<std::string> s_Preset_printer_options {
|
||||
"printer_technology",
|
||||
"printable_area", "extruder_printable_area", "bed_exclude_area","bed_custom_texture", "bed_custom_model", "gcode_flavor",
|
||||
"fan_kickstart", "fan_speedup_time", "fan_speedup_overhangs",
|
||||
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"single_extruder_multi_material", "manual_filament_change", "machine_start_gcode", "machine_end_gcode", "before_layer_change_gcode", "printing_by_object_gcode", "layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode", "change_filament_gcode", "change_extrusion_role_gcode",
|
||||
"printer_model", "printer_variant", "printer_extruder_id", "printer_extruder_variant", "extruder_variant_list", "default_nozzle_volume_type",
|
||||
"printable_height", "extruder_printable_height", "extruder_clearance_radius", "extruder_clearance_height_to_lid", "extruder_clearance_height_to_rod",
|
||||
"nozzle_height", "master_extruder_id",
|
||||
"default_print_profile", "inherits",
|
||||
"silent_mode",
|
||||
"scan_first_layer", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"scan_first_layer", "enable_wrapping_detection", "wrapping_detection_layers", "wrapping_detection_path", "machine_load_filament_time", "machine_unload_filament_time", "machine_tool_change_time", "time_cost", "machine_pause_gcode", "template_custom_gcode",
|
||||
"nozzle_type", "nozzle_hrc","auxiliary_fan", "nozzle_volume","upward_compatible_machine", "z_hop_types", "travel_slope", "retract_lift_enforce","support_chamber_temp_control","support_air_filtration","printer_structure",
|
||||
"best_object_pos", "head_wrap_detect_zone",
|
||||
"host_type", "print_host", "printhost_apikey", "bbl_use_printhost",
|
||||
|
||||
@@ -1076,7 +1076,7 @@ void PresetBundle::update_system_preset_setting_ids(std::map<std::string, std::m
|
||||
|
||||
//BBS: validate printers from previous project
|
||||
static std::set<std::string> gcodes_key_set = {"filament_end_gcode", "filament_start_gcode", "change_filament_gcode", "layer_change_gcode", "machine_end_gcode", "machine_pause_gcode", "machine_start_gcode",
|
||||
"template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode"};
|
||||
"template_custom_gcode", "printing_by_object_gcode", "before_layer_change_gcode", "time_lapse_gcode", "wrapping_detection_gcode"};
|
||||
int PresetBundle::validate_presets(const std::string &file_name, DynamicPrintConfig& config, std::set<std::string>& different_gcodes)
|
||||
{
|
||||
bool validated = false;
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
#include "nlohmann/json.hpp"
|
||||
|
||||
#include "GCode/ConflictChecker.hpp"
|
||||
#include "ParameterUtils.hpp"
|
||||
|
||||
#include <codecvt>
|
||||
|
||||
@@ -136,6 +137,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
"inner_wall_acceleration",
|
||||
"initial_layer_acceleration",
|
||||
"top_surface_acceleration",
|
||||
"enable_wrapping_detection",
|
||||
"bridge_acceleration",
|
||||
"travel_acceleration",
|
||||
"sparse_infill_acceleration",
|
||||
@@ -150,6 +152,7 @@ bool Print::invalidate_state_by_config_options(const ConfigOptionResolver & /* n
|
||||
"gcode_add_line_number",
|
||||
"layer_change_gcode",
|
||||
"time_lapse_gcode",
|
||||
"wrapping_detection_gcode",
|
||||
"fan_min_speed",
|
||||
"fan_max_speed",
|
||||
"printable_height",
|
||||
@@ -919,6 +922,13 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
||||
std::for_each(exclude_polys.begin(), exclude_polys.end(),
|
||||
[&print_origin](Polygon& p) { p.translate(scale_(print_origin.x()), scale_(print_origin.y())); });
|
||||
|
||||
Pointfs wrapping_detection_area = get_wrapping_detection_area(print_config.wrapping_detection_path.values, print_config.extruder_clearance_radius.value / 2);
|
||||
Polygon wrapping_poly;
|
||||
for (size_t i = 0; i < wrapping_detection_area.size(); ++i) {
|
||||
auto pt = wrapping_detection_area[i];
|
||||
wrapping_poly.points.emplace_back(scale_(pt.x() + print_origin.x()), scale_(pt.y() + print_origin.y()));
|
||||
}
|
||||
|
||||
std::map<const PrintInstance*, Polygon> map_model_object_to_convex_hull;
|
||||
// sequential_print_horizontal_clearance_valid
|
||||
Polygons convex_hulls_other;
|
||||
@@ -959,6 +969,11 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
||||
warning->object = inst->model_instance->get_object();
|
||||
}*/
|
||||
}
|
||||
|
||||
if (!intersection(wrapping_poly, convex_hull).empty()) {
|
||||
return {inst->model_instance->get_object()->name + L(" is too close to wrapping detection area, there may be collisions when printing.") + "\n",
|
||||
inst->model_instance->get_object()};
|
||||
}
|
||||
convex_hulls_other.emplace_back(convex_hull);
|
||||
}
|
||||
|
||||
@@ -991,7 +1006,9 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
||||
convex_hulls_temp.push_back(wipe_tower_convex_hull);
|
||||
} else {
|
||||
//here, wipe_tower_polygon is not always convex.
|
||||
Polygon wipe_tower_polygon = print.wipe_tower_data().wipe_tower_mesh_data->bottom;
|
||||
Polygon wipe_tower_polygon;
|
||||
if (print.wipe_tower_data().wipe_tower_mesh_data)
|
||||
wipe_tower_polygon = print.wipe_tower_data().wipe_tower_mesh_data->bottom;
|
||||
wipe_tower_polygon.translate(Point(scale_(x), scale_(y)));
|
||||
convex_hulls_temp.push_back(wipe_tower_polygon);
|
||||
}
|
||||
@@ -1007,7 +1024,9 @@ static StringObjectException layered_print_cleareance_valid(const Print &print,
|
||||
}*/
|
||||
return {L("Prime Tower") + L(" is too close to exclusion area, and collisions will be caused.\n")};
|
||||
}
|
||||
|
||||
if (!intersection({wrapping_poly}, convex_hulls_temp).empty()) {
|
||||
return {L("Prime Tower") + L(" is too close to wrapping detection area, and collisions will be caused.\n")};
|
||||
}
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -1141,10 +1160,13 @@ StringObjectException Print::validate(StringObjectException *warning, Polygons*
|
||||
}
|
||||
}
|
||||
|
||||
if (m_config.print_sequence == PrintSequence::ByObject) {
|
||||
if (m_config.print_sequence == PrintSequence::ByObject && m_objects.size() > 1) {
|
||||
if (m_config.timelapse_type == TimelapseType::tlSmooth)
|
||||
return {L("Smooth mode of timelapse is not supported when \"by object\" sequence is enabled.")};
|
||||
|
||||
if (m_config.enable_wrapping_detection)
|
||||
return {L("Wrapping detection is not supported when \"by object\" sequence is enabled.")};
|
||||
|
||||
//BBS: refine seq-print validation logic
|
||||
auto ret = sequential_print_clearance_valid(*this, collison_polygons, height_polygons);
|
||||
if (!ret.string.empty()) {
|
||||
@@ -2890,6 +2912,9 @@ size_t Print::get_extruder_id(unsigned int filament_id) const
|
||||
bool Print::has_wipe_tower() const
|
||||
{
|
||||
if (m_config.enable_prime_tower.value == true) {
|
||||
if (m_config.enable_wrapping_detection.value)
|
||||
return true;
|
||||
|
||||
if (enable_timelapse_print())
|
||||
return true;
|
||||
|
||||
@@ -3016,7 +3041,7 @@ void Print::_make_wipe_tower()
|
||||
if (!bUseWipeTower2) {
|
||||
// in BBL machine, wipe tower is only use to prime extruder. So just use a global wipe volume.
|
||||
WipeTower wipe_tower(m_config, m_plate_index, m_origin, m_wipe_tower_data.tool_ordering.first_extruder(),
|
||||
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z);
|
||||
m_wipe_tower_data.tool_ordering.empty() ? 0.f : m_wipe_tower_data.tool_ordering.back().print_z, m_wipe_tower_data.tool_ordering.all_extruders());
|
||||
wipe_tower.set_has_tpu_filament(this->has_tpu_filament());
|
||||
wipe_tower.set_filament_map(this->get_filament_maps());
|
||||
// Set the extruder & material properties at the wipe tower object.
|
||||
@@ -3087,7 +3112,7 @@ void Print::_make_wipe_tower()
|
||||
layer_tools.wiping_extrusions().ensure_perimeters_infills_order(*this);
|
||||
|
||||
// if enable timelapse, slice all layer
|
||||
if (enable_timelapse_print()) {
|
||||
if (m_config.enable_wrapping_detection || enable_timelapse_print()) {
|
||||
if (layer_tools.wipe_tower_partitions == 0) wipe_tower.set_last_layer_extruder_fill(false);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -3562,6 +3562,26 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionFloatOrPercent(100., true));
|
||||
|
||||
// BBS
|
||||
def = this->add("enable_wrapping_detection", coBool);
|
||||
def->label = L("Enable wrapping detection");
|
||||
def->tooltip = L("Enable wrapping detection");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionBool(false));
|
||||
|
||||
def = this->add("wrapping_detection_layers", coInt);
|
||||
def->label = L("Wrapping detection layers");
|
||||
def->tooltip = L("Wrapping detection layers.");
|
||||
def->min = 0;
|
||||
def->mode = comDevelop;
|
||||
def->set_default_value(new ConfigOptionInt(20));
|
||||
|
||||
def = this->add("wrapping_detection_path", coPoints);
|
||||
def->label = L("Wrapping detection position");
|
||||
def->tooltip = L("Wrapping detection position.");
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionPoints{Vec2d(197.5, 326), Vec2d(207.5, 326)});
|
||||
|
||||
def = this->add("sparse_infill_filament", coInt);
|
||||
def->gui_type = ConfigOptionDef::GUIType::i_enum_open;
|
||||
def->label = L("Infill");
|
||||
@@ -3813,6 +3833,14 @@ void PrintConfigDef::init_fff_params()
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString());
|
||||
|
||||
def = this->add("wrapping_detection_gcode", coString);
|
||||
def->label = L("Wrapping detection G-code");
|
||||
def->multiline = true;
|
||||
def->full_width = true;
|
||||
def->height = 5;
|
||||
def->mode = comAdvanced;
|
||||
def->set_default_value(new ConfigOptionString(""));
|
||||
|
||||
def = this->add("silent_mode", coBool);
|
||||
def->label = L("Supports silent mode");
|
||||
def->tooltip = L("Whether the machine supports silent mode in which machine use lower acceleration to print.");
|
||||
@@ -7738,7 +7766,11 @@ t_config_option_keys DynamicPrintConfig::normalize_fdm_2(int num_objects, int us
|
||||
|
||||
ConfigOptionEnum<TimelapseType>* timelapse_opt = this->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool is_smooth_timelapse = timelapse_opt != nullptr && timelapse_opt->value == TimelapseType::tlSmooth;
|
||||
if (!is_smooth_timelapse && (used_filaments == 1 || (ps_opt->value == PrintSequence::ByObject && num_objects > 1))) {
|
||||
|
||||
ConfigOptionBool *enable_wrapping_opt = this->option<ConfigOptionBool>("enable_wrapping_detection");
|
||||
bool enable_wrapping = enable_wrapping_opt != nullptr && enable_wrapping_opt->value;
|
||||
|
||||
if (!is_smooth_timelapse && !enable_wrapping && (used_filaments == 1 || (ps_opt->value == PrintSequence::ByObject && num_objects > 1))) {
|
||||
if (ept_opt->value) {
|
||||
ept_opt->value = false;
|
||||
changed_keys.push_back("enable_prime_tower");
|
||||
|
||||
@@ -1257,6 +1257,9 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionIntsNullable, filament_flush_temp))
|
||||
// BBS
|
||||
((ConfigOptionBool, scan_first_layer))
|
||||
((ConfigOptionBool, enable_wrapping_detection))
|
||||
((ConfigOptionInt, wrapping_detection_layers))
|
||||
((ConfigOptionPoints, wrapping_detection_path))
|
||||
((ConfigOptionPoints, thumbnail_size))
|
||||
// ((ConfigOptionBool, spaghetti_detector))
|
||||
((ConfigOptionBool, gcode_add_line_number))
|
||||
@@ -1266,6 +1269,7 @@ PRINT_CONFIG_CLASS_DEFINE(
|
||||
((ConfigOptionFloat, time_cost))
|
||||
((ConfigOptionString, layer_change_gcode))
|
||||
((ConfigOptionString, time_lapse_gcode))
|
||||
((ConfigOptionString, wrapping_detection_gcode))
|
||||
|
||||
((ConfigOptionFloat, max_volumetric_extrusion_rate_slope))
|
||||
((ConfigOptionFloat, max_volumetric_extrusion_rate_slope_segment_length))
|
||||
|
||||
@@ -5639,7 +5639,7 @@ int MachineObject::parse_json(std::string tunnel, std::string payload, bool key_
|
||||
upgrade_display_hold_count = HOLD_COUNT_MAX;
|
||||
BOOST_LOG_TRIVIAL(info) << "ack of upgrade_confirm";
|
||||
}
|
||||
|
||||
|
||||
if (j["upgrade"].contains("err_code")) {
|
||||
if (j["upgrade"]["err_code"].is_number()) {
|
||||
add_command_error_code_dlg(j["upgrade"]["err_code"].get<int>());
|
||||
@@ -7110,7 +7110,7 @@ void MachineObject::add_command_error_code_dlg(int command_err)
|
||||
if (!token.expired()) { m_command_error_code_dlgs.erase((GUI::DeviceErrorDialog*)event.GetEventObject());}
|
||||
event.Skip();
|
||||
});
|
||||
|
||||
|
||||
device_error_dialog->show_error_code(command_err);
|
||||
m_command_error_code_dlgs.insert(device_error_dialog);
|
||||
});
|
||||
@@ -7912,6 +7912,11 @@ std::string DeviceManager::get_printer_ext_img(std::string type_str, int pos) {
|
||||
return std::string();
|
||||
}
|
||||
|
||||
bool DeviceManager::support_wrapping_detection(const std::string &type_str)
|
||||
{
|
||||
return get_value_from_config<bool>(type_str, "support_wrapping_deteciton");
|
||||
}
|
||||
|
||||
bool DeviceManager::get_printer_is_enclosed(std::string type_str) {
|
||||
return get_value_from_config<bool>(type_str, "printer_is_enclosed"); }
|
||||
|
||||
|
||||
@@ -1603,6 +1603,7 @@ public:
|
||||
static bool get_printer_is_enclosed(std::string type_str);
|
||||
static bool get_printer_can_set_nozzle(std::string type_str);// can set nozzle from studio
|
||||
static bool load_filaments_blacklist_config();
|
||||
static bool support_wrapping_detection(const std::string& type_str);
|
||||
|
||||
static string get_fan_text(const std::string& type_str, const std::string& key);
|
||||
|
||||
|
||||
@@ -2908,9 +2908,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto timelapse_type = dconfig.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
bool need_wipe_tower = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
|
||||
if (wt && (timelapse_enabled || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) {
|
||||
const DynamicPrintConfig & printer_config = wxGetApp().preset_bundle->printers.get_edited_preset().config;
|
||||
if (printer_config.has("enable_wrapping_detection")) {
|
||||
need_wipe_tower |= dynamic_cast<const ConfigOptionBool*>(printer_config.option("enable_wrapping_detection"))->value;
|
||||
}
|
||||
|
||||
if (wt && (need_wipe_tower || filaments_count > 1) && !wxGetApp().plater()->only_gcode_mode() && !wxGetApp().plater()->is_gcode_3mf()) {
|
||||
for (int plate_id = 0; plate_id < n_plates; plate_id++) {
|
||||
// If print ByObject and there is only one object in the plate, the wipe tower is allowed to be generated.
|
||||
PartPlate* part_plate = ppl.get_plate(plate_id);
|
||||
@@ -2931,14 +2936,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
|
||||
const Print* print = m_process->fff_print();
|
||||
const Print* current_print = part_plate->fff_print();
|
||||
if (!timelapse_enabled && part_plate->get_extruders(true).size() < 2) continue;
|
||||
if (!need_wipe_tower && part_plate->get_extruders(true).size() < 2) continue;
|
||||
if (part_plate->get_objects_on_this_plate().empty()) continue;
|
||||
|
||||
float brim_width = print->wipe_tower_data(filaments_count).brim_width;
|
||||
const DynamicPrintConfig &print_cfg = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
double wipe_vol = get_max_element(v);
|
||||
int nozzle_nums = wxGetApp().preset_bundle->get_printer_extruder_count();
|
||||
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums);
|
||||
Vec3d wipe_tower_size = ppl.get_plate(plate_id)->estimate_wipe_tower_size(print_cfg, w, wipe_vol, nozzle_nums, 0, false, dynamic_cast<const ConfigOptionBool*>(printer_config.option("enable_wrapping_detection"))->value);
|
||||
|
||||
{
|
||||
const float margin = WIPE_TOWER_MARGIN + brim_width;
|
||||
|
||||
@@ -1094,6 +1094,8 @@ boost::any ConfigOptionsGroup::get_config_value(const DynamicPrintConfig& config
|
||||
if (opt_key == "printable_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "wrapping_detection_path")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
@@ -1230,6 +1232,8 @@ boost::any ConfigOptionsGroup::get_config_value2(const DynamicPrintConfig& confi
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "bed_exclude_area")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else if (opt_key == "wrapping_detection_path")
|
||||
ret = get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
else
|
||||
ret = config.option<ConfigOptionPoints>(opt_key)->get_at(idx);
|
||||
break;
|
||||
|
||||
@@ -1905,7 +1905,7 @@ bool PartPlate::check_compatible_of_nozzle_and_filament(const DynamicPrintConfig
|
||||
return wipe_tower_size;
|
||||
}*/
|
||||
|
||||
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects) const
|
||||
Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count, int plate_extruder_size, bool use_global_objects, bool enable_wrapping_detection) const
|
||||
{
|
||||
Vec3d wipe_tower_size;
|
||||
double layer_height = 0.08f; // hard code layer height
|
||||
@@ -1935,7 +1935,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
wipe_tower_size(2) = max_height;
|
||||
//const DynamicPrintConfig &dconfig = wxGetApp().preset_bundle->prints.get_edited_preset().config;
|
||||
auto timelapse_type = config.option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false;
|
||||
bool need_wipe_tower = (timelapse_type ? (timelapse_type->value == TimelapseType::tlSmooth) : false) | enable_wrapping_detection;
|
||||
double extra_spacing = config.option("prime_tower_infill_gap")->getFloat() / 100.;
|
||||
const ConfigOptionBool* use_rib_wall_opt = config.option<ConfigOptionBool>("prime_tower_rib_wall");
|
||||
bool use_rib_wall = use_rib_wall_opt ? use_rib_wall_opt->value: true;
|
||||
@@ -1958,7 +1958,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
if (extruder_count == 2) volume += filament_change_volume * (int) (plate_extruder_size / 2);
|
||||
if (use_rib_wall) {
|
||||
depth = std::sqrt(volume / layer_height * extra_spacing);
|
||||
if (timelapse_enabled || plate_extruder_size > 1) {
|
||||
if (need_wipe_tower || plate_extruder_size > 1) {
|
||||
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
|
||||
depth = std::max((double) min_wipe_tower_depth, depth);
|
||||
depth += rib_width / std::sqrt(2) + m_print->config().prime_tower_extra_rib_length.value;
|
||||
@@ -1967,7 +1967,7 @@ Vec3d PartPlate::estimate_wipe_tower_size(const DynamicPrintConfig & config, con
|
||||
}
|
||||
else {
|
||||
depth = volume/ (layer_height * w) *extra_spacing;
|
||||
if (timelapse_enabled || depth > EPSILON) {
|
||||
if (need_wipe_tower || depth > EPSILON) {
|
||||
float min_wipe_tower_depth = WipeTower::get_limit_depth_by_height(max_height);
|
||||
depth = std::max((double)min_wipe_tower_depth, depth);
|
||||
}
|
||||
@@ -1986,7 +1986,9 @@ arrangement::ArrangePolygon PartPlate::estimate_wipe_tower_polygon(const Dynamic
|
||||
//float a = dynamic_cast<const ConfigOptionFloat*>(config.option("wipe_tower_rotation_angle"))->value;
|
||||
std::vector<double> v = dynamic_cast<const ConfigOptionFloats*>(config.option("filament_prime_volume"))->values;
|
||||
float tower_brim_width = dynamic_cast<const ConfigOptionFloat*>(config.option("prime_tower_brim_width"))->value;
|
||||
wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects);
|
||||
const ConfigOptionBool * wrapping_opt = dynamic_cast<const ConfigOptionBool *>(config.option("enable_wrapping_detection"));
|
||||
bool enable_wrapping = (wrapping_opt != nullptr) && wrapping_opt->value;
|
||||
wt_size = estimate_wipe_tower_size(config, w, get_max_element(v), extruder_count, plate_extruder_size, use_global_objects, enable_wrapping);
|
||||
int plate_width=m_width, plate_depth=m_depth;
|
||||
float depth = wt_size(1);
|
||||
float margin = WIPE_TOWER_MARGIN + tower_brim_width, wp_brim_width = 0.f;
|
||||
|
||||
@@ -322,7 +322,7 @@ public:
|
||||
|
||||
Vec3d get_origin() { return m_origin; }
|
||||
//Vec3d calculate_wipe_tower_size(const DynamicPrintConfig &config, const double w, const double wipe_volume, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
Vec3d estimate_wipe_tower_size(const DynamicPrintConfig & config, const double w, const double wipe_volume, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false, bool enable_wrapping_detection = false) const;
|
||||
arrangement::ArrangePolygon estimate_wipe_tower_polygon(const DynamicPrintConfig & config, int plate_index, Vec3d& wt_pos, Vec3d& wt_size, int extruder_count = 1, int plate_extruder_size = 0, bool use_global_objects = false) const;
|
||||
bool check_objects_empty_and_gcode3mf(std::vector<int> &result) const;
|
||||
// get used filaments from config, 1 based idx
|
||||
|
||||
@@ -956,7 +956,8 @@ void Tab::init_options_list()
|
||||
|
||||
for (const std::string& opt_key : m_config->keys())
|
||||
{
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails") {
|
||||
if (opt_key == "printable_area" || opt_key == "bed_exclude_area" || opt_key == "compatible_prints" || opt_key == "compatible_printers" || opt_key == "thumbnails"
|
||||
|| opt_key == "wrapping_detection_path") {
|
||||
m_options_list.emplace(opt_key, m_opt_status_value);
|
||||
continue;
|
||||
}
|
||||
@@ -1569,13 +1570,31 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
if (opt_key == "enable_prime_tower") {
|
||||
auto timelapse_type = m_config->option<ConfigOptionEnum<TimelapseType>>("timelapse_type");
|
||||
bool timelapse_enabled = timelapse_type->value == TimelapseType::tlSmooth;
|
||||
if (!boost::any_cast<bool>(value) && timelapse_enabled) {
|
||||
MessageDialog dlg(wxGetApp().plater(), _L("A prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
if (!boost::any_cast<bool>(value)) {
|
||||
bool set_enable_prime_tower = false;
|
||||
if (timelapse_enabled) {
|
||||
MessageDialog
|
||||
dlg(wxGetApp().plater(),
|
||||
_L("A prime tower is required for smooth timelapse. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
set_enable_prime_tower = true;
|
||||
}
|
||||
}
|
||||
bool enable_wrapping = m_preset_bundle->printers.get_edited_preset().config.option<ConfigOptionBool>("enable_wrapping_detection")->value;
|
||||
if (enable_wrapping && !set_enable_prime_tower) {
|
||||
MessageDialog dlg(wxGetApp().plater(),
|
||||
_L("A prime tower is required for wrapping detection. There may be flaws on the model without prime tower. Are you sure you want to disable prime tower?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_prime_tower", new ConfigOptionBool(true));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
set_enable_prime_tower = true;
|
||||
}
|
||||
}
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
@@ -1593,6 +1612,23 @@ void Tab::on_value_change(const std::string& opt_key, const boost::any& value)
|
||||
update_wiping_button_visibility();
|
||||
}
|
||||
|
||||
if (opt_key == "enable_wrapping_detection") {
|
||||
bool wipe_tower_enabled = m_preset_bundle->prints.get_edited_preset().config.option<ConfigOptionBool>("enable_prime_tower")->value;
|
||||
if (boost::any_cast<bool>(value) && !wipe_tower_enabled) {
|
||||
MessageDialog dlg(wxGetApp().plater(),
|
||||
_L("Prime tower is required for wrapping detection. There may be flaws on the model without prime tower. Do you still want to enable wrapping detection?"),
|
||||
_L("Warning"), wxICON_WARNING | wxYES | wxNO);
|
||||
if (dlg.ShowModal() == wxID_NO) {
|
||||
DynamicPrintConfig new_conf = *m_config;
|
||||
new_conf.set_key_value("enable_wrapping_detection", new ConfigOptionBool(false));
|
||||
m_config_manipulation.apply(m_config, &new_conf);
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
} else {
|
||||
wxGetApp().plater()->update();
|
||||
}
|
||||
}
|
||||
|
||||
if (opt_key == "precise_z_height") {
|
||||
bool wipe_tower_enabled = m_config->option<ConfigOptionBool>("enable_prime_tower")->value;
|
||||
if (boost::any_cast<bool>(value) && wipe_tower_enabled) {
|
||||
@@ -4162,6 +4198,9 @@ void TabPrinter::build_fff()
|
||||
optgroup->append_single_option_line("pellet_modded_printer", "pellet-flow-coefficient");
|
||||
optgroup->append_single_option_line("bbl_use_printhost");
|
||||
optgroup->append_single_option_line("scan_first_layer");
|
||||
optgroup->append_single_option_line("enable_wrapping_detection");
|
||||
optgroup->append_single_option_line("wrapping_detection_layers");
|
||||
//optgroup->append_single_option_line("wrapping_detection_path");
|
||||
optgroup->append_single_option_line("disable_m73");
|
||||
option = optgroup->get_option("thumbnails");
|
||||
option.opt.full_width = true;
|
||||
@@ -4306,6 +4345,17 @@ void TabPrinter::build_fff()
|
||||
option.opt.height = gcode_field_height;//150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Wrapping Detection G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, optgroup](const t_config_option_key &opt_key, const boost::any &value) {
|
||||
validate_custom_gcode_cb(this, optgroup, opt_key, value);
|
||||
};
|
||||
optgroup->edit_custom_gcode = edit_custom_gcode_fn;
|
||||
option = optgroup->get_option("wrapping_detection_gcode");
|
||||
option.opt.full_width = true;
|
||||
option.opt.is_code = true;
|
||||
option.opt.height = gcode_field_height; // 150;
|
||||
optgroup->append_single_option_line(option);
|
||||
|
||||
optgroup = page->new_optgroup(L("Change filament G-code"), L"param_gcode", 0);
|
||||
optgroup->m_on_change = [this, &optgroup_title = optgroup->title](const t_config_option_key& opt_key, const boost::any& value) {
|
||||
validate_custom_gcode_cb(this, optgroup_title, opt_key, value);
|
||||
@@ -4975,6 +5025,16 @@ void TabPrinter::toggle_options()
|
||||
// SoftFever: hide non-BBL settings
|
||||
for (auto el : {"use_firmware_retraction", "use_relative_e_distances", "support_multi_bed_types", "pellet_modded_printer", "bed_mesh_max", "bed_mesh_min", "bed_mesh_probe_distance", "adaptive_bed_mesh_margin", "thumbnails"})
|
||||
toggle_line(el, !is_BBL_printer);
|
||||
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
std::string printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
toggle_line("enable_wrapping_detection", DeviceManager::support_wrapping_detection(printer_type));
|
||||
}
|
||||
|
||||
if (m_active_page->title() == L("Machine G-code")) {
|
||||
PresetBundle *preset_bundle = wxGetApp().preset_bundle;
|
||||
std::string printer_type = preset_bundle->printers.get_edited_preset().get_printer_type(preset_bundle);
|
||||
toggle_line("wrapping_detection_gcode", DeviceManager::support_wrapping_detection(printer_type));
|
||||
}
|
||||
|
||||
if (m_active_page->title() == L("Multimaterial")) {
|
||||
|
||||
@@ -1363,6 +1363,9 @@ static wxString get_string_value(std::string opt_key, const DynamicPrintConfig&
|
||||
else if (opt_key == "head_wrap_detect_zone") {
|
||||
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
}
|
||||
else if (opt_key == "wrapping_detection_path") {
|
||||
return get_thumbnails_string(config.option<ConfigOptionPoints>(opt_key)->values);
|
||||
}
|
||||
Vec2d val = config.opt<ConfigOptionPoints>(opt_key)->get_at(opt_idx);
|
||||
return from_u8((boost::format("[%1%]") % ConfigOptionPoint(val).serialize()).str());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user