From f518d6804a9de69deef81c20cd22005a4bbd0cd4 Mon Sep 17 00:00:00 2001 From: "lane.wei" Date: Wed, 23 Oct 2024 16:07:59 +0800 Subject: [PATCH] ENH: CLI: support multi-extruder slicing 1. add slicing errors for gcode in unprintable area, also for filament mapping 2. use common area for auto arrange 3. support filament_map/filament_map_mode related params 4. add logic to check the filament maps before slicing 5. uptodate support multi-extruder 6. switch new machine/filament support multi-extruder 7. process config params support transfer between mult-extruder and single-extruder 8. improve machine-limit logic support multi-extruder 9. flush-volume support multi-extruder 10. add default params to support auto mapping slicing jira: no-jira Change-Id: Ice39a365841322ddb586d39c56ff923626822528 --- src/BambuStudio.cpp | 301 +++++++++++++++++++++++++++++----- src/libslic3r/BuildVolume.cpp | 2 + src/libslic3r/PrintConfig.cpp | 287 +++++++++++++++++++++++++++++--- src/libslic3r/PrintConfig.hpp | 11 +- src/libslic3r/Utils.hpp | 2 + 5 files changed, 536 insertions(+), 67 deletions(-) diff --git a/src/BambuStudio.cpp b/src/BambuStudio.cpp index f761858e0..38383d53d 100644 --- a/src/BambuStudio.cpp +++ b/src/BambuStudio.cpp @@ -144,8 +144,10 @@ std::map cli_errors = { {CLI_OBJECT_COLLISION_IN_SEQ_PRINT, "Object conflicts were detected when using print-by-object mode. Please verify the slicing of all plates in Bambu Studio before uploading."}, {CLI_OBJECT_COLLISION_IN_LAYER_PRINT, "Object conflicts were detected. Please verify the slicing of all plates in Bambu Studio before uploading."}, {CLI_SPIRAL_MODE_INVALID_PARAMS, "Some slicing parameters cannot work with Spiral Vase mode. Please solve the issue in Bambu Studio before uploading."}, + {CLI_FILAMENT_CAN_NOT_MAP, "Some filaments cannot be mapped to correct extruders for multi-extruder Printer."}, {CLI_SLICING_ERROR, "Failed slicing the model. Please verify the slicing of all plates on Bambu Studio before uploading."}, {CLI_GCODE_PATH_CONFLICTS, " G-code conflicts detected after slicing. Please make sure the 3mf file can be successfully sliced in the latest Bambu Studio."}, + {CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, "Found G-code in unprintable area of multi-extruder printers after slicing. Please make sure the 3mf file can be successfully sliced in the latest Bambu Studio."} {CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER, "Found some filament unprintable at first layer on current Plate. Please make sure the 3mf file can be successfully sliced with the same Plate type in the latest Bambu Studio."} }; @@ -1254,22 +1256,22 @@ static void load_downward_settings_list_from_config(std::string config_file, std json downward_check_json = printer_model_json["downward_check"]; if (downward_check_json.contains(printer_name)) { downward_settings = downward_check_json[printer_name].get>(); - BOOST_LOG_TRIVIAL(info) << boost::format("got %1% downward settings of %2% in cli_config.json")%downward_settings.size() %printer_name; + BOOST_LOG_TRIVIAL(info) << boost::format("got %1% downward settings of %2% in %3%")%downward_settings.size() %printer_name %config_file; } else { - BOOST_LOG_TRIVIAL(info) << boost::format("can not find %1% in downward_check of %2% in cli_config.json")%printer_name %printer_model; + BOOST_LOG_TRIVIAL(info) << boost::format("can not find %1% in downward_check of %2% in %3%")%printer_name %printer_model %config_file; } } else { - BOOST_LOG_TRIVIAL(info) << boost::format("can not find downward_check for %1% in cli_config.json")%printer_model; + BOOST_LOG_TRIVIAL(info) << boost::format("can not find downward_check for %1% in %2%")%printer_model%config_file; } } else { - BOOST_LOG_TRIVIAL(info) << boost::format("can not find printer_model %1% in the file")%printer_model; + BOOST_LOG_TRIVIAL(info) << boost::format("can not find printer_model %1% in %2%")%printer_model%config_file; } } else { - BOOST_LOG_TRIVIAL(warning) << boost::format("can not find key printer in the file"); + BOOST_LOG_TRIVIAL(warning) << boost::format("can not find key printer in %1%")%config_file; } } catch (std::exception &err) { @@ -1317,27 +1319,24 @@ int CLI::run(int argc, char **argv) /*BOOST_LOG_TRIVIAL(info) << "begin to setup params, argc=" << argc << std::endl; for (int index=0; index < argc; index++) BOOST_LOG_TRIVIAL(info) << "index="<< index <<", arg is "<< argv[index] <setup(debug_argc, debug_argv))*/ if (!this->setup(argc, argv)) @@ -1463,15 +1462,15 @@ int CLI::run(int argc, char **argv) PlateDataPtrs plate_data_src; std::vector plate_obj_size_infos; //int arrange_option; - int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0; + int plate_to_slice = 0, filament_count = 0, duplicate_count = 0, real_duplicate_count = 0, current_extruder_count = 0, new_extruder_count = 0; bool first_file = true, is_bbl_3mf = false, need_arrange = true, has_thumbnails = false, up_config_to_date = false, normative_check = true, duplicate_single_object = false, use_first_fila_as_default = false, minimum_save = false, enable_timelapse = false; - bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false; + bool allow_rotations = true, skip_modified_gcodes = false, avoid_extrusion_cali_region = false, skip_useless_pick = false, allow_newer_file = false, current_is_multi_extruder = false, new_is_multi_extruder = false; Semver file_version; std::map orients_requirement; std::vector project_presets; - std::string new_printer_name, current_printer_name, new_process_name, current_process_name, current_printer_system_name, current_process_system_name, new_process_system_name, new_printer_system_name, printer_model_id, current_printer_model, printer_model;//, printer_inherits, print_inherits; + std::string new_printer_name, current_printer_name, new_process_name, current_process_name, current_printer_system_name, current_process_system_name, new_process_system_name, new_printer_system_name, printer_model_id, current_printer_model, printer_model, new_default_process_name; std::vector upward_compatible_printers, new_print_compatible_printers, current_print_compatible_printers, current_different_settings; - std::vector current_filaments_name, current_filaments_system_name, current_inherits_group; + std::vector current_filaments_name, current_filaments_system_name, current_inherits_group, current_extruder_variants; DynamicPrintConfig load_process_config, load_machine_config; bool new_process_config_is_system = true, new_printer_config_is_system = true; std::string pipe_name, makerlab_name, makerlab_version, different_process_setting; @@ -1716,6 +1715,19 @@ int CLI::run(int argc, char **argv) current_process_name = config.option("print_settings_id")->value; current_printer_model = config.option("printer_model", true)->value; current_filaments_name = config.option("filament_settings_id")->values; + current_extruder_count = config.option("nozzle_diameter")->values.size(); + current_is_multi_extruder = current_extruder_count > 1; + if (current_is_multi_extruder) { + auto opt_extruder_type = dynamic_cast(config.option("extruder_type")); + auto opt_nozzle_volume_type = dynamic_cast(config.option("nozzle_volume_type")); + current_extruder_variants.resize(current_extruder_count, ""); + for (int e_index = 0; e_index < current_extruder_count; e_index++) + { + ExtruderType extruder_type = (ExtruderType)(opt_extruder_type->get_at(e_index)); + NozzleVolumeType nozzle_volume_type = (NozzleVolumeType)(opt_nozzle_volume_type->get_at(e_index)); + current_extruder_variants[e_index] = get_extruder_variant_string(extruder_type, nozzle_volume_type); + } + } BOOST_LOG_TRIVIAL(info) << boost::format("current_printer_name %1%, current_process_name %2%")%current_printer_name %current_process_name; ConfigOptionStrings* option_strings = config.option("inherits_group"); @@ -2053,6 +2065,9 @@ int CLI::run(int argc, char **argv) } } } + //new_default_process_name + if (config.option("default_print_profile")) + new_default_process_name = config.option("default_print_profile")->value; //printer_inherits = config.option("inherits", true)->value; load_machine_config = std::move(config); @@ -2610,7 +2625,8 @@ int CLI::run(int argc, char **argv) } if (!process_compatible && !new_printer_name.empty() && !current_printer_name.empty() && (new_printer_name != current_printer_name)) { //set all printer to compatible - process_compatible = true; + if (new_process_name.empty()) + process_compatible = true; machine_switch = true; BOOST_LOG_TRIVIAL(info) << boost::format("switch to new printers, set to compatible"); if (upward_compatible_printers.size() > 0) { @@ -2860,6 +2876,8 @@ int CLI::run(int argc, char **argv) flush_and_exit(ret); } } + new_extruder_count = m_print_config.option("nozzle_diameter")->values.size(); + new_is_multi_extruder = new_extruder_count > 1; //set the process settings into print config std::vector& print_compatible_printers = m_print_config.option("print_compatible_printers", true)->values; @@ -2901,7 +2919,7 @@ int CLI::run(int argc, char **argv) int ret; - load_default_gcodes_to_config(load_machine_config, Preset::TYPE_PRINT); + load_default_gcodes_to_config(load_process_config, Preset::TYPE_PRINT); if (new_process_name.empty()) { int diff_keys_size = different_keys_set.size(); ret = update_full_config(m_print_config, load_process_config, different_keys_set, false, skip_modified_gcodes); @@ -2946,11 +2964,70 @@ int CLI::run(int argc, char **argv) if (need_insert) different_settings[0] = old_setting + ";compatible_printers"; } + + //add multi-extruder related logic + if (new_process_name.empty() && (current_is_multi_extruder != new_is_multi_extruder)) { + if (new_default_process_name.empty()) { + BOOST_LOG_TRIVIAL(error) << boost::format("machine_switch: default process configis null, should not happen, new_printer_name %1%")%new_printer_name; + record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + else { + std::string default_path = resources_dir() + "/profiles/BBL/process_full/"; + std::string file_path = default_path + new_default_process_name + ".json"; + DynamicPrintConfig config; + std::string config_type, config_name, filament_id, config_from, downward_printer; + int ret = load_config_file(file_path, config, config_type, config_name, filament_id, config_from); + if (ret) { + record_exit_reson(outfile_dir, ret, 0, cli_errors[ret], sliced_info); + flush_and_exit(ret); + } + if ((config_type != "process") || (config_from != "system")) { + BOOST_LOG_TRIVIAL(error) << boost::format("found invalid config type %1% or from %2% in file %3% when downward_check")%config_type %config_from %file_path; + record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + BOOST_LOG_TRIVIAL(info) << boost::format("machine_switch: loaded default process config %1%, from %2%")%config_name %file_path ; + + if (!current_is_multi_extruder && new_is_multi_extruder) { + //single -> multiple + ret = m_print_config.update_values_from_single_to_multi(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant"); + } + else if (current_is_multi_extruder && !new_is_multi_extruder) { + //multiple -> single + ret = m_print_config.update_values_from_multi_to_single(config, print_options_with_variant, "print_extruder_id", "print_extruder_variant", current_extruder_variants); + } + + if (ret) { + BOOST_LOG_TRIVIAL(error) << boost::format("current_is_multi_extruder %1% new_is_multi_extruder %2%, update_values failed") % current_is_multi_extruder % new_is_multi_extruder; + record_exit_reson(outfile_dir, CLI_CONFIG_FILE_ERROR, 0, cli_errors[CLI_CONFIG_FILE_ERROR], sliced_info); + flush_and_exit(CLI_CONFIG_FILE_ERROR); + } + } + } } //set the filament settings into print config if ((load_filament_count > 0) || (up_config_to_date)) { + std::vector filament_variant_count(filament_count, 1); + std::vector old_start_index(filament_count, 0); + std::vector old_variant_count(filament_count, 1); + if (current_is_multi_extruder) { + std::vector& old_self_indice = m_print_config.option("filament_self_index", true)->values; + int old_self_indice_size = old_self_indice.size(); + int k = -1, current_filament = 0; + for (size_t i = 0; i < old_self_indice_size; i++) { + if (old_self_indice[i] > current_filament) { + current_filament = old_self_indice[i]; + old_start_index[++k] = i; + old_variant_count[k] = 1; + } + else { + old_variant_count[k] = old_variant_count[k] + 1; + } + } + } for (int index = 0; index < load_filaments_config.size(); index++) { DynamicPrintConfig& config = load_filaments_config[index]; int filament_index = load_filaments_index[index]; @@ -3056,7 +3133,25 @@ int CLI::run(int argc, char **argv) } ConfigOptionVectorBase* opt_vec_dst = static_cast(opt); const ConfigOptionVectorBase* opt_vec_src = static_cast(source_opt); - opt_vec_dst->set_at(opt_vec_src, filament_index-1, 0); + if (new_is_multi_extruder && (filament_options_with_variant.find(opt_key) != filament_options_with_variant.end())) { + if (load_filament_count > 0) { + if (filament_index == 1) + opt_vec_dst->set(opt_vec_src); + else + opt_vec_dst->append(opt_vec_src); + + if (opt_key == "filament_extruder_variant") + filament_variant_count[filament_index - 1] = opt_vec_src->size(); + } + else { + //only update + for (size_t i = 0; i < old_variant_count[filament_index-1]; i++) { + opt_vec_dst->set_at(opt_vec_src, old_start_index[filament_index - 1] + i, i); + } + } + } + else + opt_vec_dst->set_at(opt_vec_src, filament_index-1, 0); } } @@ -3070,6 +3165,18 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("filament %1% new different key size %2%, different_settings %3%")%filament_index %different_keys_set.size() %different_settings[filament_index]; } } + + if ((load_filament_count > 0) && m_print_config.option("filament_extruder_variant")) { + std::vector& filament_self_indice = m_print_config.option("filament_self_index", true)->values; + int index_size = m_print_config.option("filament_extruder_variant")->size(); + filament_self_indice.resize(index_size, 1); + int k = 0; + for (size_t i = 0; i < filament_count; i++) { + for (size_t j = 0; j < filament_variant_count[i]; j++) { + filament_self_indice[k++] = i + 1; + } + } + } } //compute the flush volume @@ -3082,7 +3189,7 @@ int CLI::run(int argc, char **argv) std::vector& project_filament_colors = project_filament_colors_option->values; project_filament_colors.resize(filament_count, "#FFFFFF"); } - if (project_filament_colors_option && (selected_filament_colors_option || !m_print_config.option("flush_volumes_matrix"))) + if (project_filament_colors_option && (selected_filament_colors_option || !m_print_config.option("flush_volumes_matrix") || (new_extruder_count != current_extruder_count))) { std::vector selected_filament_colors; if (selected_filament_colors_option) { @@ -3160,21 +3267,15 @@ int CLI::run(int argc, char **argv) BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix before computing: %1%") % m_print_config.option("flush_volumes_matrix")->serialize(); } - size_t nozzle_nums = 1; - auto opt_nozzle_diameters = m_print_config.option("nozzle_diameter"); - if (opt_nozzle_diameters != nullptr) { - nozzle_nums = opt_nozzle_diameters->values.size(); - } - std::vector &flush_vol_matrix = m_print_config.option("flush_volumes_matrix", true)->values; - flush_vol_matrix.resize(project_filament_count * project_filament_count * nozzle_nums, 0.f); + flush_vol_matrix.resize(project_filament_count * project_filament_count * new_extruder_count, 0.f); // set multiplier to 1? std::vector& flush_multipliers = m_print_config.option("flush_multiplier", true)->values; - flush_multipliers.resize(nozzle_nums, 1.f); + flush_multipliers.resize(new_extruder_count, 1.f); - for (size_t nozzle_id = 0; nozzle_id < nozzle_nums; ++nozzle_id) { - std::vector flush_vol_mtx = get_flush_volumes_matrix(flush_vol_matrix, nozzle_id, nozzle_nums); + for (size_t nozzle_id = 0; nozzle_id < new_extruder_count; ++nozzle_id) { + std::vector flush_vol_mtx = get_flush_volumes_matrix(flush_vol_matrix, nozzle_id, new_extruder_count); for (int from_idx = 0; from_idx < project_filament_count; from_idx++) { const std::string &from_color = project_filament_colors[from_idx]; unsigned char from_rgb[4] = {}; @@ -3202,7 +3303,7 @@ int CLI::run(int argc, char **argv) flush_vol_mtx[project_filament_count * from_idx + to_idx] = flushing_volume; } } - set_flush_volumes_matrix(flush_vol_matrix, flush_vol_mtx, nozzle_id, nozzle_nums); + set_flush_volumes_matrix(flush_vol_matrix, flush_vol_mtx, nozzle_id, new_extruder_count); } } BOOST_LOG_TRIVIAL(info) << boost::format("flush_volumes_matrix after computed: %1%")%m_print_config.option("flush_volumes_matrix")->serialize(); @@ -3630,7 +3731,7 @@ int CLI::run(int argc, char **argv) if (downward_settings.size() == 0) { //parse from internal std::string cli_config_file = resources_dir() + "/profiles/BBL/cli_config.json"; - load_downward_settings_list_from_config(cli_config_file, current_printer_name, current_printer_model, downward_settings); + load_downward_settings_list_from_config(cli_config_file, current_printer_system_name, current_printer_model, downward_settings); use_default = true; default_path = resources_dir() + "/profiles/BBL/machine_full/"; } @@ -5341,6 +5442,7 @@ int CLI::run(int argc, char **argv) long long triangle_count = 0; int printable_instances = 0; int skipped_count = 0; + std::vector> unprintable_filament_ids(new_extruder_count, std::set()); for (ModelObject* model_object : model.objects) for (ModelInstance *i : model_object->instances) { @@ -5384,6 +5486,7 @@ int CLI::run(int argc, char **argv) } else if (i->print_volume_state == ModelInstancePVS_Inside) { + const Transform3d& inst_matrix = i->get_transformation().get_matrix(); for (const ModelVolume* vol : model_object->volumes) { if (vol->is_model_part()) { @@ -5396,6 +5499,21 @@ int CLI::run(int argc, char **argv) record_exit_reson(outfile_dir, CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT, index+1, cli_errors[CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT], sliced_info); flush_and_exit(CLI_TRIANGLE_COUNT_EXCEEDS_LIMIT); } + + if (new_extruder_count > 1) { + BoundingBoxf3 bbox = vol->get_convex_hull().transformed_bounding_box(inst_matrix * vol->get_matrix()); + std::vector inside_extruders; + BuildVolume::ObjectState state = build_volume.check_volume_bbox_state_with_extruder_areas(bbox, inside_extruders); + if (state == BuildVolume::ObjectState::Limited) { + for (size_t i = 0; i < inside_extruders.size(); ++i) { + if (!inside_extruders[i]) { + std::vector filaments = vol->get_extruders(); + unprintable_filament_ids[i].insert(filaments.begin(), filaments.end()); + } + } + } + + } } } } @@ -5410,6 +5528,69 @@ int CLI::run(int argc, char **argv) flush_and_exit(CLI_NO_SUITABLE_OBJECTS_AFTER_SKIP); } + if (new_extruder_count > 1) { + std::vector> unprintable_filament_vec; + for (const std::set& filamnt_ids : unprintable_filament_ids) { + unprintable_filament_vec.emplace_back(std::vector(filamnt_ids.begin(), filamnt_ids.end())); + } + + FilamentMapMode mode; + if (m_extra_config.option>("filament_map_mode")) + mode = m_extra_config.option>("filament_map_mode")->value; + else + mode = part_plate->get_filament_map_mode(); + if (mode == FilamentMapMode::fmmAuto) { + part_plate->set_unprintable_filament_ids(unprintable_filament_vec); + std::vector conflict_filament_vector; + for (int index = 0; index < new_extruder_count; index++) + { + if (!unprintable_filament_vec[index].empty()) + { + std::sort(unprintable_filament_vec[index].begin(), unprintable_filament_vec[index].end()); + if (index == 0) + conflict_filament_vector = unprintable_filament_vec[index]; + else + { + std::vector result_filaments; + //result_filaments.reserve(conflict_filaments.size()); + std::set_intersection(conflict_filament_vector.begin(), conflict_filament_vector.end(), unprintable_filament_vec[index].begin(), + unprintable_filament_vec[index].end(), insert_iterator>(result_filaments, result_filaments.begin())); + conflict_filament_vector = result_filaments; + } + } + else + { + conflict_filament_vector.clear(); + break; + } + } + //check whether has filament can not map + if (!conflict_filament_vector.empty()) + { + BOOST_LOG_TRIVIAL(error) << boost::format("plate %1% : some filaments can not be mapped under auto mode for multi extruder printer ")% (index + 1); + record_exit_reson(outfile_dir, CLI_FILAMENT_CAN_NOT_MAP, index + 1, cli_errors[CLI_FILAMENT_CAN_NOT_MAP], sliced_info); + flush_and_exit(CLI_FILAMENT_CAN_NOT_MAP); + } + } + else { + std::vector filament_maps; + if (m_extra_config.option("filament_map")) + filament_maps = m_extra_config.option("filament_map")->values; + else + filament_maps = part_plate->get_filament_maps(); + for (int index = 0; index < filament_maps.size(); index++) + { + int filament_extruder = filament_maps[index]; + if (unprintable_filament_ids[filament_extruder - 1].find(index + 1) != unprintable_filament_ids[filament_extruder - 1].end()) + { + BOOST_LOG_TRIVIAL(error) << boost::format("plate %1% : some filaments can not be mapped under auto mode for multi extruder printer ") % (index + 1); + record_exit_reson(outfile_dir, CLI_FILAMENT_CAN_NOT_MAP, index + 1, cli_errors[CLI_FILAMENT_CAN_NOT_MAP], sliced_info); + flush_and_exit(CLI_FILAMENT_CAN_NOT_MAP); + } + } + } + } + plate_triangle_counts[index] = triangle_count; plate_object_count[index] = printable_instances; BOOST_LOG_TRIVIAL(info) << "plate "<< index+1<< ": load cached data success, go on."; @@ -5421,6 +5602,35 @@ int CLI::run(int argc, char **argv) DynamicPrintConfig new_print_config = m_print_config; new_print_config.apply(*part_plate->config()); new_print_config.apply(m_extra_config, true); + if (new_extruder_count > 1) { + FilamentMapMode map_mode = fmmAuto; + if (new_print_config.option>("filament_map_mode")) + map_mode = new_print_config.option>("filament_map_mode")->value; + + if (map_mode == fmmAuto) { + //set default params for auto map + std::vector extruder_ams_count(new_extruder_count, ""); + std::vector> extruder_filament_info(new_extruder_count, std::vector()); + int color_count = 0; + for (int e_index = 0; e_index < new_extruder_count; e_index++) + { + extruder_ams_count[e_index] = "1#0|4#1"; + for (int color_index = 0; color_index < 4; color_index++) + { + DynamicPrintConfig temp_config; + std::vector temp_colors(1, "#FFFFFFFF"); + if (filament_color) { + temp_colors[0] = colors[color_count % colors.size()]; + } + temp_config.option("filament_colour", true)->values = temp_colors; + extruder_filament_info[e_index].push_back(std::move(temp_config)); + color_count++; + } + } + new_print_config.option("extruder_ams_count", true)->values = extruder_ams_count; + print_fff->set_extruder_filament_info(extruder_filament_info); + } + } print->apply(model, new_print_config); BOOST_LOG_TRIVIAL(info) << boost::format("set no_check to %1%:")%no_check; print->set_no_check_flag(no_check);//BBS @@ -5638,6 +5848,13 @@ int CLI::run(int argc, char **argv) slice_time[TIME_USING_CACHE] = slice_time[TIME_USING_CACHE] + ((long long)Slic3r::Utils::get_current_milliseconds_time_utc() - temp_time); BOOST_LOG_TRIVIAL(info) << "export_gcode finished: time_using_cache update to " << slice_time[TIME_USING_CACHE] << " secs."; + if (gcode_result && gcode_result->gcode_check_result.error_code) { + //found gcode error + BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found gcode in unprintable area of multi extruder printers!" << std::endl; + record_exit_reson(outfile_dir, CLI_GCODE_PATH_IN_UNPRINTABLE_AREA, index + 1, cli_errors[CLI_GCODE_PATH_IN_UNPRINTABLE_AREA], sliced_info); + flush_and_exit(CLI_GCODE_PATH_IN_UNPRINTABLE_AREA); + } + if (gcode_result && gcode_result->filament_printable_reuslt.has_value()) { //found gcode error BOOST_LOG_TRIVIAL(error) << "plate " << index + 1 << ": found some filament unprintable on current bed- "<< gcode_result->filament_printable_reuslt.plate_name << std::endl; diff --git a/src/libslic3r/BuildVolume.cpp b/src/libslic3r/BuildVolume.cpp index 56c3582af..e582c5007 100644 --- a/src/libslic3r/BuildVolume.cpp +++ b/src/libslic3r/BuildVolume.cpp @@ -147,6 +147,8 @@ BuildVolume::BuildVolume(const std::vector &printable_area, const double extruder_volume.bboxf = m_bboxf; extruder_volume.circle = m_circle; } + //always ignore z + extruder_volume.bboxf.min.z() = -std::numeric_limits::max(); m_extruder_volumes.push_back(std::move(extruder_volume)); } diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index febdc9f5d..b8437d9b0 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -3201,7 +3201,6 @@ void PrintConfigDef::init_fff_params() def->label = "Extruder ams count"; def->tooltip = "Ams counts of per extruder"; def->set_default_value(new ConfigOptionStrings { }); - def->cli = ConfigOptionDef::nocli; def = this->add("printer_extruder_id", coInts); def->label = "Printer extruder id"; @@ -5204,12 +5203,12 @@ std::set print_options_with_variant = { "initial_layer_infill_speed", "outer_wall_speed", "inner_wall_speed", - "small_perimeter_speed", + "small_perimeter_speed", //coFloatsOrPercents "small_perimeter_threshold", "sparse_infill_speed", "internal_solid_infill_speed", "top_surface_speed", - "enable_overhang_speed", + "enable_overhang_speed", //coBools "overhang_1_4_speed", "overhang_2_4_speed", "overhang_3_4_speed", @@ -5224,10 +5223,10 @@ std::set print_options_with_variant = { "initial_layer_acceleration", "outer_wall_acceleration", "inner_wall_acceleration", - "sparse_infill_acceleration", + "sparse_infill_acceleration", //coFloatsOrPercents "top_surface_acceleration", - "print_extruder_id", - "print_extruder_variant" + "print_extruder_id", //coInts + "print_extruder_variant" //coStrings }; std::set filament_options_with_variant = { @@ -5780,6 +5779,210 @@ int DynamicPrintConfig::get_index_for_extruder(int extruder_or_filament_id, std: return ret; } +//only used for cli +//update values in single extruder process config to values in multi-extruder process +//limit the new values +int DynamicPrintConfig::update_values_from_single_to_multi(DynamicPrintConfig& multi_config, std::set& key_set, std::string id_name, std::string variant_name) +{ + auto print_variant_opt = dynamic_cast(multi_config.option(variant_name)); + if (!print_variant_opt) { + BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % variant_name; + return -1; + } + int variant_count = print_variant_opt->size(); + + const ConfigDef *config_def = this->def(); + if (!config_def) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define")%__LINE__; + return -1; + } + for (auto& key: key_set) + { + const ConfigOptionDef *optdef = config_def->get(key); + if (!optdef) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%")%__LINE__%key; + continue; + } + switch (optdef->type) { + case coStrings: + { + ConfigOptionStrings * opt = this->option(key); + ConfigOptionStrings * src_opt = multi_config.option(key); + + opt->values = src_opt->values; + break; + } + case coInts: + { + ConfigOptionInts * opt = this->option(key); + ConfigOptionInts * src_opt = multi_config.option(key); + + opt->values = src_opt->values; + break; + } + case coFloats: + { + ConfigOptionFloats * opt = this->option(key); + ConfigOptionFloats * src_opt = multi_config.option(key); + + assert(variant_count == src_opt->size()); + opt->resize(variant_count, opt); + + for (int index = 0; index < variant_count; index++) + { + if (opt->values[index] > src_opt->values[index]) + opt->values[index] = src_opt->values[index]; + } + break; + } + case coFloatsOrPercents: + { + ConfigOptionFloatsOrPercents * opt = this->option(key); + ConfigOptionFloatsOrPercents * src_opt = multi_config.option(key); + + assert(variant_count == src_opt->size()); + opt->resize(variant_count, opt); + + for (int index = 0; index < variant_count; index++) + { + if (opt->values[index].value > src_opt->values[index].value) + opt->values[index] = src_opt->values[index]; + } + break; + } + case coBools: + { + ConfigOptionBools * opt = this->option(key); + ConfigOptionBools * src_opt = multi_config.option(key); + + assert(variant_count == src_opt->size()); + opt->resize(variant_count, opt); + + break; + } + default: + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%")%__LINE__%key; + break; + } + } + + return 0; +} + +int DynamicPrintConfig::update_values_from_multi_to_single(DynamicPrintConfig& single_config, std::set& key_set, std::string id_name, std::string variant_name, std::vector& extruder_variants) +{ + int extruder_count = extruder_variants.size(); + std::vector extruder_index(extruder_count, -1); + + auto print_variant_opt = dynamic_cast(this->option(variant_name)); + if (!print_variant_opt) { + BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % variant_name; + return -1; + } + int variant_count = print_variant_opt->size(); + + auto print_id_opt = dynamic_cast(this->option(id_name)); + if (!print_id_opt) { + BOOST_LOG_TRIVIAL(error) << boost::format("%1%:%2%, can not get %3% from config")%__FUNCTION__ %__LINE__ % id_name; + return -1; + } + + for (int i = 0; i < extruder_count; i++) + { + for (int j = 0; j < variant_count; j++) + { + if ((i+1 == print_id_opt->values[j]) && (extruder_variants[i] == print_variant_opt->values[j])) { + extruder_index[i] = j; + break; + } + } + } + + const ConfigDef* config_def = this->def(); + if (!config_def) { + BOOST_LOG_TRIVIAL(error) << __FUNCTION__ << boost::format(", Line %1%: can not find config define") % __LINE__; + return -1; + } + for (auto& key : key_set) + { + const ConfigOptionDef* optdef = config_def->get(key); + if (!optdef) { + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: can not find opt define for %2%") % __LINE__ % key; + continue; + } + switch (optdef->type) { + case coStrings: + { + ConfigOptionStrings* opt = this->option(key); + ConfigOptionStrings* src_opt = single_config.option(key); + + assert(variant_count == opt->size()); + opt->values = src_opt->values; + break; + } + case coInts: + { + ConfigOptionInts* opt = this->option(key); + ConfigOptionInts* src_opt = single_config.option(key); + + assert(variant_count == opt->size()); + opt->values = src_opt->values; + break; + } + case coFloats: + { + ConfigOptionFloats* opt = this->option(key); + ConfigOptionFloats* src_opt = single_config.option(key); + std::vector old_values = opt->values; + + assert(variant_count == opt->size()); + opt->values = src_opt->values; + + for (int i = 0; i < extruder_count; i++) + { + assert(extruder_index[i] != -1); + if (old_values[extruder_index[i]] < opt->values[0]) + opt->values[0] = old_values[extruder_index[i]]; + } + break; + } + case coFloatsOrPercents: + { + ConfigOptionFloatsOrPercents* opt = this->option(key); + ConfigOptionFloatsOrPercents* src_opt = single_config.option(key); + + std::vector old_values = opt->values; + + assert(variant_count == opt->size()); + opt->values = src_opt->values; + + for (int i = 0; i < extruder_count; i++) + { + assert(extruder_index[i] != -1); + if (old_values[extruder_index[i]].value < opt->values[0].value) + opt->values[0] = old_values[extruder_index[i]]; + } + break; + } + case coBools: + { + ConfigOptionBools* opt = this->option(key); + ConfigOptionBools* src_opt = single_config.option(key); + + assert(variant_count == opt->size()); + opt->values = src_opt->values; + + break; + } + default: + BOOST_LOG_TRIVIAL(warning) << __FUNCTION__ << boost::format(", Line %1%: unsupported option type for %2%") % __LINE__ % key; + break; + } + } + + return 0; +} + std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name, unsigned int stride, unsigned int extruder_id) { int extruder_count; @@ -5851,7 +6054,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5865,7 +6068,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5879,7 +6082,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5893,7 +6096,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5907,7 +6110,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5921,7 +6124,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5935,7 +6138,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP new_values.resize(extruder_count * stride); for (int e_index = 0; e_index < extruder_count; e_index++) { - for (int i = 0; i < stride; i++) + for (unsigned int i = 0; i < stride; i++) new_values[e_index*stride + i] = opt->get_at(variant_index[e_index]*stride + i); } opt->values = new_values; @@ -5953,7 +6156,7 @@ std::vector DynamicPrintConfig::update_values_to_printer_extruders(DynamicP void DynamicPrintConfig::update_values_to_printer_extruders_for_multiple_filaments(DynamicPrintConfig& printer_config, std::set& key_set, std::string id_name, std::string variant_name) { - int extruder_count, filament_count; + int extruder_count; bool different_extruder = printer_config.support_different_extruders(extruder_count); if ((extruder_count > 1) || different_extruder) { @@ -7019,9 +7222,26 @@ static Points to_points(const std::vector &dpts) return pts; } -Points get_bed_shape(const DynamicPrintConfig &config) +static Polygon get_shared_poly(const std::vector& extruder_polys) { - const auto *bed_shape_opt = config.opt("printable_area"); + Polygon result; + for (int index = 0; index < extruder_polys.size(); index++) + { + const Pointfs& extruder_area = extruder_polys[index]; + if (index == 0) + result.points = to_points(extruder_area); + else { + Polygon extruer_poly; + extruer_poly.points = to_points(extruder_area); + Polygons result_polygon = intersection(extruer_poly, result); + result = result_polygon[0]; + } + } + return result; +} +Points get_bed_shape(const DynamicPrintConfig &config, bool use_share) +{ + const ConfigOptionPoints *bed_shape_opt = config.opt("printable_area"); if (!bed_shape_opt) { // Here, it is certain that the bed shape is missing, so an infinite one @@ -7032,20 +7252,45 @@ Points get_bed_shape(const DynamicPrintConfig &config) return {}; } - return to_points(bed_shape_opt->values); + Polygon bed_poly; + if (use_share) { + const ConfigOptionPointsGroups *extruder_area_opt = config.opt("extruder_printable_area"); + if (extruder_area_opt && (extruder_area_opt->size() > 0)) { + const std::vector& extruder_areas = extruder_area_opt->values; + bed_poly = get_shared_poly(extruder_areas); + } + else + bed_poly.points = to_points(bed_shape_opt->values); + } + else + bed_poly.points = to_points(bed_shape_opt->values); + + return bed_poly.points; } -Points get_bed_shape(const PrintConfig &cfg) +Points get_bed_shape(const PrintConfig &cfg, bool use_share) { - return to_points(cfg.printable_area.values); + Polygon bed_poly; + if (use_share) { + const std::vector& extruder_areas = cfg.extruder_printable_area.values; + if (extruder_areas.size() > 0) { + bed_poly = get_shared_poly(extruder_areas); + } + else + bed_poly.points = to_points(cfg.printable_area.values); + } + else + bed_poly.points = to_points(cfg.printable_area.values); + + return bed_poly.points; } Points get_bed_shape(const SLAPrinterConfig &cfg) { return to_points(cfg.printable_area.values); } -Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg) +Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg, bool use_share) { Polygon bed_poly; - bed_poly.points = get_bed_shape(cfg); + bed_poly.points = get_bed_shape(cfg, use_share); Points excluse_area_points = to_points(cfg.bed_exclude_area.values); Polygons exclude_polys; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index ec6a02f7b..cbd0c2eda 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -509,6 +509,9 @@ public: std::set& key_set1, std::set& key_set2); void update_diff_values_to_child_config(DynamicPrintConfig& new_config, std::string extruder_id_name, std::string extruder_variant_name, std::set& key_set1, std::set& key_set2); + int update_values_from_single_to_multi(DynamicPrintConfig& multi_config, std::set& key_set, std::string id_name, std::string variant_name); + int update_values_from_multi_to_single(DynamicPrintConfig& single_config, std::set& key_set, std::string id_name, std::string variant_name, std::vector& extruder_variants); + }; extern std::set printer_extruder_options; extern std::set print_options_with_variant; @@ -833,7 +836,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionPercent, wipe_speed)) ((ConfigOptionBool, role_base_wipe_speed)) ((ConfigOptionBool, precise_z_height)) // BBS - + ((ConfigOptionBool, interlocking_beam)) ((ConfigOptionFloat,interlocking_beam_width)) ((ConfigOptionFloat,interlocking_orientation)) @@ -1482,10 +1485,10 @@ private: static PrintAndCLIConfigDef s_def; }; -Points get_bed_shape(const DynamicPrintConfig &cfg); -Points get_bed_shape(const PrintConfig &cfg); +Points get_bed_shape(const DynamicPrintConfig &cfg, bool use_share = true); +Points get_bed_shape(const PrintConfig &cfg, bool use_share = false); Points get_bed_shape(const SLAPrinterConfig &cfg); -Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg); +Slic3r::Polygon get_bed_shape_with_excluded_area(const PrintConfig& cfg, bool use_share = false); bool has_skirt(const DynamicPrintConfig& cfg); float get_real_skirt_dist(const DynamicPrintConfig& cfg); diff --git a/src/libslic3r/Utils.hpp b/src/libslic3r/Utils.hpp index 711cff864..55794aad3 100644 --- a/src/libslic3r/Utils.hpp +++ b/src/libslic3r/Utils.hpp @@ -60,9 +60,11 @@ #define CLI_OBJECT_COLLISION_IN_SEQ_PRINT -63 #define CLI_OBJECT_COLLISION_IN_LAYER_PRINT -64 #define CLI_SPIRAL_MODE_INVALID_PARAMS -65 +#define CLI_FILAMENT_CAN_NOT_MAP -66 #define CLI_SLICING_ERROR -100 #define CLI_GCODE_PATH_CONFLICTS -101 +#define CLI_GCODE_PATH_IN_UNPRINTABLE_AREA -102 #define CLI_FILAMENT_UNPRINTABLE_ON_FIRST_LAYER -103