diff --git a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp index 738f066..dee2a91 100644 --- a/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp +++ b/src/libnest2d/include/libnest2d/placers/nfpplacer.hpp @@ -184,6 +184,11 @@ template class EdgeCache { contour_.full_distance += length(contour_.emap.back()); contour_.distances.emplace_back(contour_.full_distance); } + if (*sl::cbegin(sh)!=*sl::rcbegin(sh)) { + contour_.emap.emplace_back(*std::prev(endit), *sl::cbegin(sh)); + contour_.full_distance += length(contour_.emap.back()); + contour_.distances.emplace_back(contour_.full_distance); + } } for(auto& h : shapelike::holes(sh)) { // For the holes @@ -199,6 +204,11 @@ template class EdgeCache { hc.full_distance += length(hc.emap.back()); hc.distances.emplace_back(hc.full_distance); } + if (*sl::cbegin(h) != *sl::rcbegin(h)) { + hc.emap.emplace_back(*std::prev(endit), *sl::cbegin(h)); + hc.full_distance += length(hc.emap.back()); + hc.distances.emplace_back(hc.full_distance); + } holes_.emplace_back(std::move(hc)); } diff --git a/src/libslic3r/AppConfig.cpp b/src/libslic3r/AppConfig.cpp index 1dccdac..2704791 100644 --- a/src/libslic3r/AppConfig.cpp +++ b/src/libslic3r/AppConfig.cpp @@ -178,6 +178,8 @@ void AppConfig::set_defaults() set_bool("enable_lod", true); if (get("enable_opengl_multi_instance").empty()) set_bool("enable_opengl_multi_instance", true); + if (get("import_single_svg_and_split").empty()) + set_bool("import_single_svg_and_split", true); if (get("user_bed_type").empty()) set_bool("user_bed_type", true); if (get("grabber_size_factor").empty()) @@ -401,6 +403,9 @@ void AppConfig::set_defaults() if (get("angle_defletion").empty()) { set("angle_defletion", "0.5"); } + if (get("is_split_compound").empty()) { + set_bool("is_split_compound", false); + } // 10 if (get("machine_list_net").empty()) diff --git a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp index 5963b29..05685ec 100644 --- a/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp +++ b/src/libslic3r/CSGMesh/ModelToCSGMesh.hpp @@ -19,7 +19,7 @@ enum ModelParts { }; template -bool model_to_csgmesh(const ModelObject &mo, +bool model_to_csgmesh(const std::vector & volumes, const Transform3d &trafo, // Applies to all exported parts OutIt out, // Output iterator // values of ModelParts OR-ed @@ -32,7 +32,7 @@ bool model_to_csgmesh(const ModelObject &mo, bool do_splits = parts_to_include & mpartsDoSplits; bool has_splitable_volume = false; - for (const ModelVolume *vol : mo.volumes) { + for (const ModelVolume *vol : volumes) { if (vol && vol->mesh_ptr() && ((do_positives && vol->is_model_part()) || (do_negatives && vol->is_negative_volume()))) { diff --git a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp index a9a48b4..7e861cd 100644 --- a/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp +++ b/src/libslic3r/CSGMesh/PerformCSGMeshBooleans.hpp @@ -4,6 +4,8 @@ #include #include +#include + #include "CSGMesh.hpp" #include "libslic3r/Execution/ExecutionTBB.hpp" diff --git a/src/libslic3r/ExtrusionEntity.cpp b/src/libslic3r/ExtrusionEntity.cpp index c679e7b..4dc516c 100644 --- a/src/libslic3r/ExtrusionEntity.cpp +++ b/src/libslic3r/ExtrusionEntity.cpp @@ -621,6 +621,7 @@ std::string ExtrusionEntity::role_to_string(ExtrusionRole role) case erWipeTower : return L("Prime tower"); case erCustom : return L("Custom"); case erMixed : return L("Multiple"); + case erFlush : return L("Flush"); default : assert(false); } return ""; @@ -664,6 +665,8 @@ ExtrusionRole ExtrusionEntity::string_to_role(const std::string_view role) return erCustom; else if (role == L("Multiple")) return erMixed; + else if (role == L("Flush")) + return erFlush; else return erNone; } diff --git a/src/libslic3r/ExtrusionEntity.hpp b/src/libslic3r/ExtrusionEntity.hpp index 1838839..54999d1 100644 --- a/src/libslic3r/ExtrusionEntity.hpp +++ b/src/libslic3r/ExtrusionEntity.hpp @@ -36,6 +36,7 @@ enum ExtrusionRole : uint8_t { erSupportTransition, erWipeTower, erCustom, + erFlush, // Extrusion role for a collection with multiple extrusion roles. erMixed, erCount diff --git a/src/libslic3r/Format/STEP.cpp b/src/libslic3r/Format/STEP.cpp index 810fd99..fe7b932 100644 --- a/src/libslic3r/Format/STEP.cpp +++ b/src/libslic3r/Format/STEP.cpp @@ -165,16 +165,21 @@ int StepPreProcessor::preNum(const unsigned char byte) { return num; } -static void getNamedSolids(const TopLoc_Location& location, const std::string& prefix, - unsigned int& id, const Handle(XCAFDoc_ShapeTool) shapeTool, - const TDF_Label label, std::vector& namedSolids) { +static void getNamedSolids(const TopLoc_Location& location, + const std::string& prefix, + unsigned int& id, + const Handle(XCAFDoc_ShapeTool) shapeTool, + const TDF_Label label, + std::vector& namedSolids, + bool isSplitCompound = false) { TDF_Label referredLabel{label}; if (shapeTool->IsReference(label)) shapeTool->GetReferredShape(label, referredLabel); std::string name; Handle(TDataStd_Name) shapeName; - if (referredLabel.FindAttribute(TDataStd_Name::GetID(), shapeName)) + if (referredLabel.FindAttribute(TDataStd_Name::GetID(), shapeName) || + label.FindAttribute(TDataStd_Name::GetID(), shapeName)) name = TCollection_AsciiString(shapeName->Get()).ToCString(); if (name == "" || !StepPreProcessor::isUtf8(name)) @@ -185,7 +190,7 @@ static void getNamedSolids(const TopLoc_Location& location, const std::string& p TDF_LabelSequence components; if (shapeTool->GetComponents(referredLabel, components)) { for (Standard_Integer compIndex = 1; compIndex <= components.Length(); ++compIndex) { - getNamedSolids(localLocation, fullName, id, shapeTool, components.Value(compIndex), namedSolids); + getNamedSolids(localLocation, fullName, id, shapeTool, components.Value(compIndex), namedSolids, isSplitCompound); } } else { TopoDS_Shape shape; @@ -196,11 +201,19 @@ static void getNamedSolids(const TopLoc_Location& location, const std::string& p int i = 0; switch (shape_type) { case TopAbs_COMPOUND: + if (!isSplitCompound) { + namedSolids.emplace_back(TopoDS::Compound(transform.Shape()), fullName); + break; + } case TopAbs_COMPSOLID: - for (explorer.Init(transform.Shape(), TopAbs_SOLID); explorer.More(); explorer.Next()) { - i++; - const TopoDS_Shape& currentShape = explorer.Current(); - namedSolids.emplace_back(TopoDS::Solid(currentShape), fullName + "-SOLID-" + std::to_string(i)); + if (!isSplitCompound) { + namedSolids.emplace_back(TopoDS::CompSolid(transform.Shape()), fullName); + } else { + for (explorer.Init(transform.Shape(), TopAbs_SOLID); explorer.More(); explorer.Next()) { + i++; + const TopoDS_Shape& currentShape = explorer.Current(); + namedSolids.emplace_back(TopoDS::Solid(currentShape), fullName + "-SOLID-" + std::to_string(i)); + } } break; case TopAbs_SOLID: @@ -215,6 +228,7 @@ static void getNamedSolids(const TopLoc_Location& location, const std::string& p bool load_step(const char *path, Model *model, bool& is_cancel, double linear_defletion/*=0.003*/, double angle_defletion/*= 0.5*/, + bool isSplitCompound, ImportStepProgressFn stepFn, StepIsUtf8Fn isUtf8Fn, long& mesh_face_num) { bool cb_cancel = false; @@ -263,7 +277,7 @@ bool load_step(const char *path, Model *model, bool& is_cancel, return false; } } - getNamedSolids(TopLoc_Location{}, "", id, shapeTool, topLevelShapes.Value(iLabel), namedSolids); + getNamedSolids(TopLoc_Location{}, "", id, shapeTool, topLevelShapes.Value(iLabel), namedSolids, isSplitCompound); } std::vector stl; diff --git a/src/libslic3r/Format/STEP.hpp b/src/libslic3r/Format/STEP.hpp index 0b86ad4..227a387 100644 --- a/src/libslic3r/Format/STEP.hpp +++ b/src/libslic3r/Format/STEP.hpp @@ -42,6 +42,7 @@ extern bool load_step(const char *path, Model *model, bool& is_cancel, double linear_defletion = 0.003, double angle_defletion = 0.5, + bool isSplitCompound = false, ImportStepProgressFn proFn = nullptr, StepIsUtf8Fn isUtf8Fn = nullptr, long& mesh_face_num = *(new long(-1))); diff --git a/src/libslic3r/Format/qds_3mf.cpp b/src/libslic3r/Format/qds_3mf.cpp index 09c3272..7f6475b 100644 --- a/src/libslic3r/Format/qds_3mf.cpp +++ b/src/libslic3r/Format/qds_3mf.cpp @@ -230,6 +230,7 @@ static constexpr const char* SLICE_HEADER_ITEM_TAG = "header_item"; static constexpr const char* TEXT_INFO_TAG = "text_info"; static constexpr const char* TEXT_ATTR = "text"; static constexpr const char* FONT_NAME_ATTR = "font_name"; +static constexpr const char *FONT_VERSION_ATTR = "font_version"; static constexpr const char* FONT_INDEX_ATTR = "font_index"; static constexpr const char* FONT_SIZE_ATTR = "font_size"; static constexpr const char* THICKNESS_ATTR = "thickness"; @@ -337,6 +338,7 @@ static constexpr const char* SOURCE_IN_METERS = "source_in_meters"; static constexpr const char* MESH_SHARED_KEY = "mesh_shared"; +static constexpr const char *MESH_STAT_FACE_COUNT = "face_count"; static constexpr const char* MESH_STAT_EDGES_FIXED = "edges_fixed"; static constexpr const char* MESH_STAT_DEGENERATED_FACETS = "degenerate_facets"; static constexpr const char* MESH_STAT_FACETS_REMOVED = "facets_removed"; @@ -367,7 +369,8 @@ static constexpr const char *FONT_STYLE_ATTR = "style"; static constexpr const char *FONT_WEIGHT_ATTR = "weight"; // Store / load of EmbossShape -static constexpr const char *SHAPE_TAG = "slic3rpe:shape"; +static constexpr const char *OLD_SHAPE_TAG = "slic3rpe:shape"; +static constexpr const char *SHAPE_TAG = "BambuStudioShape"; static constexpr const char *SHAPE_SCALE_ATTR = "scale"; static constexpr const char *UNHEALED_ATTR = "unhealed"; static constexpr const char *SVG_FILE_PATH_ATTR = "filepath"; @@ -3253,6 +3256,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) res = _handle_start_assemble_item(attributes, num_attributes); else if (::strcmp(TEXT_INFO_TAG, name) == 0) res = _handle_start_text_info_item(attributes, num_attributes); + else if (::strcmp(OLD_SHAPE_TAG, name) == 0) + res = _handle_start_shape_configuration(attributes, num_attributes); else if (::strcmp(SHAPE_TAG, name) == 0) res = _handle_start_shape_configuration(attributes, num_attributes); if (!res) @@ -4408,6 +4413,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) TextInfo text_info; text_info.m_text = xml_unescape(qds_get_attribute_value_string(attributes, num_attributes, TEXT_ATTR)); text_info.m_font_name = qds_get_attribute_value_string(attributes, num_attributes, FONT_NAME_ATTR); + text_info.m_font_version = qds_get_attribute_value_string(attributes, num_attributes, FONT_VERSION_ATTR); text_info.m_curr_font_idx = qds_get_attribute_value_int(attributes, num_attributes, FONT_INDEX_ATTR); @@ -4656,8 +4662,10 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) if (triangle_mesh.volume() < 0) triangle_mesh.flip_triangles(); - volume = object.add_volume(std::move(triangle_mesh)); - + bool is_text = !volume_data->text_info.m_text.empty(); + bool modify_to_center_geometry = is_text ? false : true;//text do not modify_to_center_geometry + volume = object.add_volume(std::move(triangle_mesh), ModelVolumeType::MODEL_PART, modify_to_center_geometry); + if (shared_mesh_id != -1) //for some cases the shared mesh is in other plate and not loaded in cli slicing //we need to use the first one in the same plate instead @@ -7317,6 +7325,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) stream << TEXT_ATTR << "=\"" << xml_escape(text_info.m_text) << "\" "; stream << FONT_NAME_ATTR << "=\"" << text_info.m_font_name << "\" "; + stream << FONT_VERSION_ATTR << "=\"" << text_info.m_font_version << "\" "; stream << FONT_INDEX_ATTR << "=\"" << text_info.m_curr_font_idx << "\" "; @@ -7375,6 +7384,8 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) stream << " <" << METADATA_TAG << " " << KEY_ATTR << "=\"" << key << "\" " << VALUE_ATTR << "=\"" << obj->config.opt_serialize(key) << "\"/>\n"; } + stream << " <" << METADATA_TAG << " " << MESH_STAT_FACE_COUNT << "=\"" << obj_metadata.second.object->facets_count() << "\"/>\n"; + for (const ModelVolume* volume : obj_metadata.second.object->volumes) { if (volume != nullptr) { const VolumeToObjectIDMap& objectIDs = obj_metadata.second.volumes_objectID; @@ -7451,6 +7462,7 @@ void PlateData::parse_filament_info(GCodeProcessorResult *result) // stores mesh's statistics const RepairedMeshErrors& stats = volume->mesh().stats().repaired_errors; stream << " <" << MESH_STAT_TAG << " "; + stream << MESH_STAT_FACE_COUNT << "=\"" << volume->mesh().facets_count() << "\" "; stream << MESH_STAT_EDGES_FIXED << "=\"" << stats.edges_fixed << "\" "; stream << MESH_STAT_DEGENERATED_FACETS << "=\"" << stats.degenerate_facets << "\" "; stream << MESH_STAT_FACETS_REMOVED << "=\"" << stats.facets_removed << "\" "; @@ -8637,7 +8649,7 @@ bool to_xml(std::stringstream &stream, const EmbossShape::SvgFile &svg, const Mo void to_xml(std::stringstream &stream, const EmbossShape &es, const ModelVolume &volume, mz_zip_archive &archive) { - stream << " <" << SHAPE_TAG << " "; + stream << " <" << SHAPE_TAG << " "; if (es.svg_file.has_value()) if (!to_xml(stream, *es.svg_file, volume, archive)) BOOST_LOG_TRIVIAL(warning) << "Can't write svg file defiden embossed shape into 3mf"; diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index 43a57a9..aa5dbf0 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -2389,6 +2389,7 @@ void GCode::_do_export(Print& print, GCodeOutputStream &file, ThumbnailsGenerato m_writer.extruders(), // Modifies print.m_print_statistics));*/ + print.m_print_statistics.initial_tool = initial_extruder_id; bool activate_air_filtration = false; for (const auto& extruder : m_writer.extruders()) @@ -4765,7 +4766,7 @@ ExtrusionPaths GCode::set_speed_transition(ExtrusionPaths &paths) void GCode::smooth_speed_discontinuity_area(ExtrusionPaths &paths) { - if (paths.size() <= 1) + if (paths.size() <= 1 || this->config().smooth_coefficient == 0) return; //step 1 merge same speed path diff --git a/src/libslic3r/GCode/ConflictChecker.cpp b/src/libslic3r/GCode/ConflictChecker.cpp index acf6b71..1c0c7f3 100644 --- a/src/libslic3r/GCode/ConflictChecker.cpp +++ b/src/libslic3r/GCode/ConflictChecker.cpp @@ -122,7 +122,9 @@ float LinesBucketQueue::getCurrBottomZ() } for (LinesBucket *bp : lowests) { + float prevZ = bp->curBottomZ(); bp->raise(); + if (bp->curBottomZ() == prevZ) continue; if (bp->valid()) { line_bucket_ptr_queue.push(bp); } } return layerBottomZ; diff --git a/src/libslic3r/GCode/GCodeProcessor.cpp b/src/libslic3r/GCode/GCodeProcessor.cpp index 715c9fd..156a4a2 100644 --- a/src/libslic3r/GCode/GCodeProcessor.cpp +++ b/src/libslic3r/GCode/GCodeProcessor.cpp @@ -225,12 +225,12 @@ void GCodeProcessor::TimeMachine::reset() prepare_time = 0.0f; } -void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time) +void GCodeProcessor::TimeMachine::simulate_st_synchronize(float additional_time, ExtrusionRole target_role) { if (!enabled) return; - calculate_time(0, additional_time); + calculate_time(0, additional_time,target_role); } static void planner_forward_pass_kernel(GCodeProcessor::TimeBlock& prev, GCodeProcessor::TimeBlock& curr) @@ -303,7 +303,7 @@ static void recalculate_trapezoids(std::vector& block } } -void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, float additional_time) +void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, float additional_time, ExtrusionRole target_role) { if (!enabled || blocks.size() < 2) return; @@ -322,11 +322,16 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa recalculate_trapezoids(blocks); size_t n_blocks_process = blocks.size() - keep_last_n_blocks; + bool found_target_block = false; for (size_t i = 0; i < n_blocks_process; ++i) { const TimeBlock& block = blocks[i]; float block_time = block.time(); - if (i == 0) + + bool is_valid_block = target_role == ExtrusionRole::erNone || target_role == block.role || i == n_blocks_process - 1; + if (!found_target_block && is_valid_block) { block_time += additional_time; + found_target_block = true; + } time += block_time; gcode_time.cache += block_time; @@ -345,7 +350,11 @@ void GCodeProcessor::TimeMachine::calculate_time(size_t keep_last_n_blocks, floa //QDS if (block.flags.prepare_stage) prepare_time += block_time; - g1_times_cache.push_back({ block.g1_line_id, time }); + + if(!g1_times_cache.empty() && g1_times_cache.back().id == block.g1_line_id) + g1_times_cache.back().elapsed_time = time; + else + g1_times_cache.push_back({ block.g1_line_id, time }); // update times for remaining time to printer stop placeholders auto it_stop_time = std::lower_bound(stop_times.begin(), stop_times.end(), block.g1_line_id, [](const StopTime& t, unsigned int value) { return t.g1_line_id < value; }); @@ -872,6 +881,7 @@ void GCodeProcessor::UsedFilaments::process_support_cache(GCodeProcessor* proces void GCodeProcessor::UsedFilaments::update_flush_per_filament(size_t extrude_id, float flush_volume) { if (flush_volume != 0.f) { + role_cache += flush_volume; if (flush_per_filament.find(extrude_id) != flush_per_filament.end()) flush_per_filament[extrude_id] += flush_volume; else @@ -1611,7 +1621,7 @@ void GCodeProcessor::finalize(bool post_process) for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { TimeMachine& machine = m_time_processor.machines[i]; TimeMachine::CustomGCodeTime& gcode_time = machine.gcode_time; - machine.calculate_time(); + machine.calculate_time(0, 0, ExtrusionRole::erNone); if (gcode_time.needed && gcode_time.cache != 0.0f) gcode_time.times.push_back({ CustomGCode::ColorChange, gcode_time.cache }); } @@ -2193,6 +2203,7 @@ bool GCodeProcessor::get_last_z_from_gcode(const std::string& gcode_str, double& void GCodeProcessor::process_tags(const std::string_view comment, bool producers_enabled) { + static ExtrusionRole prev_role; // producers tags if (producers_enabled && process_producers_tags(comment)) return; @@ -2231,12 +2242,15 @@ void GCodeProcessor::process_tags(const std::string_view comment, bool producers //QDS: flush start tag if (boost::starts_with(comment, GCodeProcessor::Flush_Start_Tag)) { + prev_role = m_extrusion_role; + set_extrusion_role(erFlush); m_flushing = true; return; } //QDS: flush end tag if (boost::starts_with(comment, GCodeProcessor::Flush_End_Tag)) { + set_extrusion_role(prev_role); m_flushing = false; return; } @@ -3210,8 +3224,9 @@ void GCodeProcessor::process_G1(const GCodeReader::GCodeLine& line) blocks.push_back(block); - if (blocks.size() > TimeProcessor::Planner::refresh_threshold) - machine.calculate_time(TimeProcessor::Planner::queue_size); + if (blocks.size() > TimeProcessor::Planner::refresh_threshold) { + machine.calculate_time(TimeProcessor::Planner::queue_size, 0, erNone); + } } if (m_seams_detector.is_active()) { @@ -3655,8 +3670,9 @@ void GCodeProcessor::process_G2_G3(const GCodeReader::GCodeLine& line) blocks.push_back(block); - if (blocks.size() > TimeProcessor::Planner::refresh_threshold) - machine.calculate_time(TimeProcessor::Planner::queue_size); + if (blocks.size() > TimeProcessor::Planner::refresh_threshold) { + machine.calculate_time(TimeProcessor::Planner::queue_size, 0, erNone); + } } //QDS: seam detector @@ -4259,11 +4275,29 @@ void GCodeProcessor::process_T(const std::string_view command) float extra_time = get_filament_unload_time(static_cast(m_last_extruder_id)); m_time_processor.extruder_unloaded = false; extra_time += get_filament_load_time(static_cast(m_extruder_id)); - simulate_st_synchronize(extra_time); - } + // store tool change move + store_move_vertex(EMoveType::Tool_change); + // construct a new time block to handle filament change + for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { + TimeMachine& machine = m_time_processor.machines[i]; + if (!machine.enabled) + continue; + TimeBlock block; + block.role = erFlush; + block.move_type = EMoveType::Tool_change; + block.layer_id = std::max(1, m_layer_id); + block.g1_line_id = m_g1_line_id; + block.flags.prepare_stage = m_processing_start_custom_gcode; + block.distance = 0; + block.calculate_trapezoid(); - // store tool change move - store_move_vertex(EMoveType::Tool_change); + // when do st_sync, we will clear all of the blocks without keeping last n blocks, so we can directly add the new block into the blocks + machine.blocks.push_back(block); + } + + simulate_st_synchronize(extra_time, erFlush); + + } } } } @@ -4470,7 +4504,7 @@ void GCodeProcessor::process_custom_gcode_time(CustomGCode::Type code) gcode_time.needed = true; //FIXME this simulates st_synchronize! is it correct? // The estimated time may be longer than the real print time. - machine.simulate_st_synchronize(); + machine.simulate_st_synchronize(0, erNone); if (gcode_time.cache != 0.0f) { gcode_time.times.push_back({ code, gcode_time.cache }); gcode_time.cache = 0.0f; @@ -4492,10 +4526,14 @@ void GCodeProcessor::process_filaments(CustomGCode::Type code) } } -void GCodeProcessor::simulate_st_synchronize(float additional_time) +void GCodeProcessor::simulate_st_synchronize(float additional_time, ExtrusionRole target_role) { for (size_t i = 0; i < static_cast(PrintEstimatedStatistics::ETimeMode::Count); ++i) { - m_time_processor.machines[i].simulate_st_synchronize(additional_time); + TimeMachine& machine = m_time_processor.machines[i]; + if (!machine.enabled) + continue; + + machine.simulate_st_synchronize(additional_time, target_role); } } diff --git a/src/libslic3r/GCode/GCodeProcessor.hpp b/src/libslic3r/GCode/GCodeProcessor.hpp index ff5aac9..35a7dd0 100644 --- a/src/libslic3r/GCode/GCodeProcessor.hpp +++ b/src/libslic3r/GCode/GCodeProcessor.hpp @@ -460,9 +460,26 @@ namespace Slic3r { void reset(); - // Simulates firmware st_synchronize() call - void simulate_st_synchronize(float additional_time = 0.0f); - void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f); + /** + * @brief Simulates firmware st_synchronize() call + * + * Adding additional time to the specified extrusion role's time block. + * + * @param additional_time Addtional time to calculate + * @param target_role Target extrusion role for addtional time.Default is none,means any role is ok. + */ + void simulate_st_synchronize(float additional_time = 0.0f, ExtrusionRole target_role = ExtrusionRole::erNone); + + /** + * @brief Calculates the time for all blocks + * + * Computes the time for all blocks. + * + * @param keep_last_n_blocks The number of last blocks to retain during calculation (default is 0). + * @param additional_time Additional time to calculate. + * @param target_role Target extrusion role for addtional time.Default is none, means any role is ok. + */ + void calculate_time(size_t keep_last_n_blocks = 0, float additional_time = 0.0f, ExtrusionRole target_role = ExtrusionRole::erNone); }; struct UsedFilaments // filaments per ColorChange @@ -967,7 +984,7 @@ namespace Slic3r { void process_filaments(CustomGCode::Type code); // Simulates firmware st_synchronize() call - void simulate_st_synchronize(float additional_time = 0.0f); + void simulate_st_synchronize(float additional_time = 0.0f, ExtrusionRole target_role =ExtrusionRole::erNone); void update_estimated_times_stats(); //QDS: diff --git a/src/libslic3r/GCode/ToolOrdering.cpp b/src/libslic3r/GCode/ToolOrdering.cpp index ce9951a..a8830be 100644 --- a/src/libslic3r/GCode/ToolOrdering.cpp +++ b/src/libslic3r/GCode/ToolOrdering.cpp @@ -986,7 +986,7 @@ void ToolOrdering::assign_custom_gcodes(const Print& print) bool pause_or_custom_gcode = !color_change && !tool_change; bool apply_color_change = !ignore_tool_and_color_changes && // If it is color change, it will actually be useful as the exturder above will print. - // BBS + // QDS (color_change ? mode == CustomGCode::SingleExtruder || (item.extruder <= int(num_filaments) && extruder_printing_above[unsigned(item.extruder - 1)]) : diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 9fba666..93fa586 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -447,6 +447,16 @@ const Vec3d &Transformation::get_rotation() const return m_temp_rotation; } +const Vec3d &Transformation::get_rotation_by_quaternion() const +{ + Matrix3d rotation_matrix = m_matrix.matrix().block(0, 0, 3, 3); + Eigen::Quaterniond quaternion(rotation_matrix); + quaternion.normalize(); + m_temp_rotation = quaternion.matrix().eulerAngles(2, 1, 0); + std::swap(m_temp_rotation(0), m_temp_rotation(2)); + return m_temp_rotation; +} + Transform3d Transformation::get_rotation_matrix() const { return extract_rotation_matrix(m_matrix); } void Transformation::set_rotation(const Vec3d &rotation) diff --git a/src/libslic3r/Geometry.hpp b/src/libslic3r/Geometry.hpp index 7ed9388..265bdfd 100644 --- a/src/libslic3r/Geometry.hpp +++ b/src/libslic3r/Geometry.hpp @@ -395,6 +395,7 @@ public: void set_offset(Axis axis, double offset) { m_matrix.translation()[axis] = offset; } const Vec3d &get_rotation() const; + const Vec3d &get_rotation_by_quaternion() const; double get_rotation(Axis axis) const { return get_rotation()[axis]; } Transform3d get_rotation_matrix() const; diff --git a/src/libslic3r/Model.cpp b/src/libslic3r/Model.cpp index 621aea8..39bae64 100644 --- a/src/libslic3r/Model.cpp +++ b/src/libslic3r/Model.cpp @@ -188,9 +188,10 @@ Model Model::read_from_step(const std::string& LoadStrategy options, ImportStepProgressFn stepFn, StepIsUtf8Fn stepIsUtf8Fn, - std::function step_mesh_fn, + std::function step_mesh_fn, double linear_defletion, - double angle_defletion) + double angle_defletion, + bool is_split_compound) { Model model; bool result = false; @@ -199,12 +200,12 @@ Model Model::read_from_step(const std::string& Step step_file(input_file); step_file.load(); if (step_mesh_fn) { - if (step_mesh_fn(step_file, linear_defletion, angle_defletion) == -1) { + if (step_mesh_fn(step_file, linear_defletion, angle_defletion, is_split_compound) == -1) { Model empty_model; return empty_model; } } - result = load_step(input_file.c_str(), &model, is_cb_cancel, linear_defletion, angle_defletion, stepFn, stepIsUtf8Fn); + result = load_step(input_file.c_str(), &model, is_cb_cancel, linear_defletion, angle_defletion, is_split_compound, stepFn, stepIsUtf8Fn); if (is_cb_cancel) { Model empty_model; return empty_model; @@ -3243,10 +3244,10 @@ std::string ModelVolume::type_to_string(const ModelVolumeType t) // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. // This is useful to assign different materials to different volumes of an object. -size_t ModelVolume::split(unsigned int max_extruders) +size_t ModelVolume::split(unsigned int max_extruders, float scale_det) { std::vector> ships; - std::vector meshes = this->mesh().split_and_save_relationship(ships); + std::vector meshes = this->mesh().split_and_save_relationship(ships, scale_det); if (meshes.size() <= 1) return 1; if (meshes.size() != ships.size()) diff --git a/src/libslic3r/Model.hpp b/src/libslic3r/Model.hpp index 6d41f38..1ad2d2d 100644 --- a/src/libslic3r/Model.hpp +++ b/src/libslic3r/Model.hpp @@ -389,6 +389,7 @@ public: CutConnectors cut_connectors; CutObjectBase cut_id; + std::vector const_volumes() const {return std::vector(volumes.begin(), volumes.end());} Model* get_model() { return m_model; } const Model* get_model() const { return m_model; } // QDS: production extension @@ -816,6 +817,7 @@ struct RaycastResult struct TextInfo { std::string m_font_name; + std::string m_font_version; float m_font_size = 16.f; int m_curr_font_idx = 0; bool m_bold = true; @@ -831,8 +833,9 @@ struct TextInfo RaycastResult m_rr; template void serialize(Archive &ar) { - ar(m_font_name, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_embeded_depth, m_rotate_angle, m_text_gap, m_is_surface_text, m_keep_horizontal, m_text, m_rr); - } + ar(m_font_name, m_font_version, m_font_size, m_curr_font_idx, m_bold, m_italic, m_thickness, m_embeded_depth, m_rotate_angle, m_text_gap, m_is_surface_text, + m_keep_horizontal, m_text, m_rr); + } }; // An object STL, or a modifier volume, over which a different set of parameters shall be applied. @@ -961,7 +964,7 @@ public: // Split this volume, append the result to the object owning this volume. // Return the number of volumes created from this one. // This is useful to assign different materials to different volumes of an object. - size_t split(unsigned int max_extruders); + size_t split(unsigned int max_extruders, float scale_det = 1.f); void translate(double x, double y, double z) { translate(Vec3d(x, y, z)); } void translate(const Vec3d& displacement); void scale(const Vec3d& scaling_factors); @@ -1029,7 +1032,7 @@ public: void set_text_info(const TextInfo& text_info) { m_text_info = text_info; } const TextInfo& get_text_info() const { return m_text_info; } - + bool is_text() const { return !m_text_info.m_text.empty(); } const Transform3d &get_matrix(bool dont_translate = false, bool dont_rotate = false, bool dont_scale = false, bool dont_mirror = false) const; void set_new_unique_id() { ObjectBase::set_new_unique_id(); @@ -1592,9 +1595,10 @@ public: LoadStrategy options, ImportStepProgressFn stepFn, StepIsUtf8Fn stepIsUtf8Fn, - std::function step_mesh_fn, + std::function step_mesh_fn, double linear_defletion, - double angle_defletion); + double angle_defletion, + bool is_split_compound); //QDS: add part plate related logic diff --git a/src/libslic3r/PresetBundle.cpp b/src/libslic3r/PresetBundle.cpp index f4e45ac..b009a63 100644 --- a/src/libslic3r/PresetBundle.cpp +++ b/src/libslic3r/PresetBundle.cpp @@ -1921,6 +1921,11 @@ std::set PresetBundle::get_vendors() std::set PresetBundle::get_printer_names_by_printer_type_and_nozzle(const std::string &printer_type, std::string nozzle_diameter_str) { std::set printer_names; + + /* unknown or empty printer type */ + if (printer_type.empty()) + return printer_names; + if ("0.0" == nozzle_diameter_str || nozzle_diameter_str.empty()) { nozzle_diameter_str = "0.4"; } diff --git a/src/libslic3r/Print.cpp b/src/libslic3r/Print.cpp index c7f187b..6f48295 100644 --- a/src/libslic3r/Print.cpp +++ b/src/libslic3r/Print.cpp @@ -2566,6 +2566,7 @@ DynamicConfig PrintStatistics::config() const config.set_key_value("total_weight", new ConfigOptionFloat(this->total_weight)); config.set_key_value("total_wipe_tower_cost", new ConfigOptionFloat(this->total_wipe_tower_cost)); config.set_key_value("total_wipe_tower_filament", new ConfigOptionFloat(this->total_wipe_tower_filament)); + config.set_key_value("initial_tool", new ConfigOptionInt(static_cast(this->initial_tool))); return config; } @@ -2575,7 +2576,7 @@ DynamicConfig PrintStatistics::placeholders() for (const std::string &key : { "print_time", "normal_print_time", "silent_print_time", "used_filament", "extruded_volume", "total_cost", "total_weight", - "total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"}) + "intial_tool", "total_toolchanges", "total_wipe_tower_cost", "total_wipe_tower_filament"}) config.set_key_value(key, new ConfigOptionString(std::string("{") + key + "}")); return config; } diff --git a/src/libslic3r/Print.hpp b/src/libslic3r/Print.hpp index 3c4f052..eb472c4 100644 --- a/src/libslic3r/Print.hpp +++ b/src/libslic3r/Print.hpp @@ -656,6 +656,7 @@ struct PrintStatistics double total_weight; double total_wipe_tower_cost; double total_wipe_tower_filament; + unsigned int initial_tool; std::map filament_stats; // Config with the filled in print statistics. @@ -673,6 +674,7 @@ struct PrintStatistics total_weight = 0.; total_wipe_tower_cost = 0.; total_wipe_tower_filament = 0.; + initial_tool = 0; filament_stats.clear(); } }; diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index 293e2e3..8b9ac57 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -663,7 +663,7 @@ void PrintConfigDef::init_fff_params() def->label = L("Initial layer"); def->full_label = L("Initial layer bed temperature"); def->tooltip = L("Bed temperature of the initial layer. " - "Value 0 means the filament does not support to print on the QIDI Cool Plate SuperTack"); + "Value 0 means the filament does not support to print on the Cool Plate"); def->sidetext = "°C"; def->min = 0; def->max = 120; @@ -1226,8 +1226,9 @@ void PrintConfigDef::init_fff_params() def = this->add("smooth_coefficient", coFloat); def->label = L("Smooth coefficient"); def->category = L("Quality"); - def->tooltip = L("The smaller the number, the longer the speed transition path."); + def->tooltip = L("The smaller the number, the longer the speed transition path. 0 means not apply."); def->mode = comAdvanced; + def->min = 0; def->set_default_value(new ConfigOptionFloat(80)); def = this->add("internal_bridge_support_thickness", coFloat); @@ -3122,7 +3123,7 @@ void PrintConfigDef::init_fff_params() def = this->add("role_base_wipe_speed", coBool); def->label = L("Role-based wipe speed"); - def->tooltip = L("The wipe speed is determined by speed of current extrusion role. " "e.g if a wip action is executed immediately following an outer wall extrusion, the speed of the outer wall extrusion will be utilized for the wipe action."); + def->tooltip = L("The wipe speed is determined by speed of current extrusion role. " "e.g if a wipe action is executed immediately following an outer wall extrusion, the speed of the outer wall extrusion will be utilized for the wipe action."); def->mode = comAdvanced; def->set_default_value(new ConfigOptionBool(true)); @@ -4942,7 +4943,7 @@ void PrintConfigDef::handle_legacy(t_config_option_key &opt_key, std::string &va #endif /* HAS_PRESSURE_EQUALIZER */ // QDS , "support_sharp_tails","support_remove_small_overhangs", "support_with_sheath", - "tree_support_branch_diameter_angle", "tree_support_collision_resolution", "tree_support_with_infill", + "tree_support_collision_resolution", "tree_support_with_infill", "tree_support_brim_width", //1.9.5 "max_volumetric_speed", "max_print_speed", "support_closing_radius", diff --git a/src/libslic3r/Support/SupportMaterial.cpp b/src/libslic3r/Support/SupportMaterial.cpp index 22b8b37..a17f467 100644 --- a/src/libslic3r/Support/SupportMaterial.cpp +++ b/src/libslic3r/Support/SupportMaterial.cpp @@ -1457,7 +1457,6 @@ static inline ExPolygons detect_overhangs( // This is done to increase size of the supporting columns below, as they are calculated by // propagating these contact surfaces downwards. diff_polygons = diff(intersection(expand(diff_polygons, lower_layer_offset, SUPPORT_SURFACES_OFFSET_PARAMETERS), layerm_polygons), lower_layer_polygons); - if (xy_expansion != 0) { diff_polygons = expand(diff_polygons, xy_expansion, SUPPORT_SURFACES_OFFSET_PARAMETERS); } } //FIXME add user defined filtering here based on minimal area or minimum radius or whatever. @@ -1509,6 +1508,8 @@ static inline ExPolygons detect_overhangs( if (diff_polygons.empty() || offset(diff_polygons, -0.1 * fw).empty()) continue; + if (xy_expansion != 0) { diff_polygons = expand(diff_polygons, xy_expansion, SUPPORT_SURFACES_OFFSET_PARAMETERS); } + polygons_append(overhang_polygons, diff_polygons); } // for each layer.region } diff --git a/src/libslic3r/Support/SupportParameters.hpp b/src/libslic3r/Support/SupportParameters.hpp index dd95f1a..2f1750c 100644 --- a/src/libslic3r/Support/SupportParameters.hpp +++ b/src/libslic3r/Support/SupportParameters.hpp @@ -171,6 +171,12 @@ struct SupportParameters { std::numeric_limits::max(); support_style = object_config.support_style; + if (support_style != smsDefault) { + if ((support_style == smsSnug || support_style == smsGrid) && is_tree(object_config.support_type)) support_style = smsDefault; + if ((support_style == smsTreeSlim || support_style == smsTreeStrong || support_style == smsTreeHybrid || support_style == smsTreeOrganic) && + !is_tree(object_config.support_type)) + support_style = smsDefault; + } if (support_style == smsDefault) { if (is_tree(object_config.support_type)) { // organic support doesn't work with variable layer heights (including adaptive layer height and height range modifier, see #4313) diff --git a/src/libslic3r/Support/TreeModelVolumes.cpp b/src/libslic3r/Support/TreeModelVolumes.cpp index 3024047..f87d694 100644 --- a/src/libslic3r/Support/TreeModelVolumes.cpp +++ b/src/libslic3r/Support/TreeModelVolumes.cpp @@ -33,7 +33,7 @@ using namespace std::literals; // or warning // had to use a define beacuse the macro processing inside macro BOOST_LOG_TRIVIAL() -#define error_level_not_in_cache error +#define error_level_not_in_cache debug //FIXME Machine border is currently ignored. static Polygons calculateMachineBorderCollision(Polygon machine_border) diff --git a/src/libslic3r/Support/TreeSupport.cpp b/src/libslic3r/Support/TreeSupport.cpp index fd01208..9570620 100644 --- a/src/libslic3r/Support/TreeSupport.cpp +++ b/src/libslic3r/Support/TreeSupport.cpp @@ -1,4 +1,3 @@ -#include #include #include @@ -219,6 +218,7 @@ static void draw_contours_and_nodes_to_svg // draw layer nodes svg.draw(layer_pts, "green", coord_t(scale_(0.1))); + for (SupportNode *node : layer_nodes) { svg.draw({node->overhang}, "green", 0.5); } // lower layer points layer_pts.clear(); @@ -227,13 +227,13 @@ static void draw_contours_and_nodes_to_svg } svg.draw(layer_pts, "black", coord_t(scale_(0.1))); - // higher layer points - layer_pts.clear(); - for (SupportNode* node : layer_nodes) { - if(node->parent) - layer_pts.push_back(node->parent->position); - } - svg.draw(layer_pts, "blue", coord_t(scale_(0.1))); + //// higher layer points + //layer_pts.clear(); + //for (SupportNode* node : layer_nodes) { + // if(node->parent) + // layer_pts.push_back(node->parent->position); + //} + //svg.draw(layer_pts, "blue", coord_t(scale_(0.1))); } static void draw_layer_mst @@ -1645,6 +1645,8 @@ void TreeSupport::move_bounds_to_contact_nodes(std::vectorsupport_type.value)) return; + if (m_support_params.support_style == smsTreeOrganic) { generate_tree_support_3D(*m_object, this, this->throw_on_cancel); return; @@ -2076,8 +2078,7 @@ void TreeSupport::draw_circles() area = offset_ex({ node.overhang }, scale_(m_ts_data->m_xy_distance)); } area = diff_clipped(area, get_collision(node.is_sharp_tail && node.distance_to_top <= 0)); - if (node.type == ePolygon) - area_poly = area; + if (node.type == ePolygon) append(area_poly, area); } else { Polygon circle(branch_circle); @@ -2108,6 +2109,12 @@ void TreeSupport::draw_circles() if(!tmp.empty()) circle = tmp[0]; } + area = avoid_object_remove_extra_small_parts(ExPolygon(circle), get_collision(node.is_sharp_tail && node.distance_to_top <= 0)); + // area = diff_clipped({ ExPolygon(circle) }, get_collision(node.is_sharp_tail && node.distance_to_top <= 0)); + + if (!area.empty()) has_circle_node = true; + if (node.need_extra_wall) need_extra_wall = true; + // merge overhang to get a smoother interface surface // Do not merge when buildplate_only is on, because some underneath nodes may have been deleted. if (top_interface_layers > 0 && node.support_roof_layers_below > 0 && !on_buildplate_only && !node.is_sharp_tail) { @@ -2119,14 +2126,6 @@ void TreeSupport::draw_circles() } append(area, overhang_expanded); } - - area = avoid_object_remove_extra_small_parts(ExPolygon(circle), get_collision(node.is_sharp_tail && node.distance_to_top <= 0)); - //area = diff_clipped({ ExPolygon(circle) }, get_collision(node.is_sharp_tail && node.distance_to_top <= 0)); - - if (!area.empty()) - has_circle_node = true; - if(node.need_extra_wall) - need_extra_wall = true; } if (obj_layer_nr>0 && node.distance_to_top < 0) @@ -2203,22 +2202,22 @@ void TreeSupport::draw_circles() } auto &area_groups = ts_layer->area_groups; for (auto& expoly : ts_layer->base_areas) { - if (area(expoly) < SQ(scale_(1))) continue; + //if (area(expoly) < SQ(scale_(1))) continue; area_groups.emplace_back(&expoly, SupportLayer::BaseType, max_layers_above_base); area_groups.back().need_infill = overlaps({ expoly }, area_poly); area_groups.back().need_extra_wall = need_extra_wall && !area_groups.back().need_infill; } for (auto& expoly : ts_layer->roof_areas) { - if (area(expoly) < SQ(scale_(1))) continue; + //if (area(expoly) < SQ(scale_(1))) continue; area_groups.emplace_back(&expoly, SupportLayer::RoofType, max_layers_above_roof); area_groups.back().interface_id = interface_id; } for (auto &expoly : ts_layer->floor_areas) { - if (area(expoly) < SQ(scale_(1))) continue; + //if (area(expoly) < SQ(scale_(1))) continue; area_groups.emplace_back(&expoly, SupportLayer::FloorType, 10000); } for (auto &expoly : ts_layer->roof_1st_layer) { - if (area(expoly) < SQ(scale_(1))) continue; + //if (area(expoly) < SQ(scale_(1))) continue; area_groups.emplace_back(&expoly, SupportLayer::Roof1stLayer, max_layers_above_roof1); } @@ -2900,7 +2899,7 @@ void TreeSupport::drop_nodes() } } auto next_collision = get_collision(0, obj_layer_nr_next); - const bool to_buildplate = !is_inside_ex(next_collision, next_layer_vertex); + const bool to_buildplate = !is_inside_ex(m_ts_data->m_layer_outlines[obj_layer_nr_next], next_layer_vertex); SupportNode * next_node = m_ts_data->create_node(next_layer_vertex, node.distance_to_top + 1, obj_layer_nr_next, node.support_roof_layers_below - 1, to_buildplate, p_node, print_z_next, height_next); // don't increase radius if next node will collide partially with the object (STUDIO-7883) @@ -3259,9 +3258,11 @@ std::vector TreeSupport::plan_layer_heights() for (int layer_nr = 0; layer_nr < contact_nodes.size(); layer_nr++) { if (contact_nodes[layer_nr].empty()) continue; SupportNode *node1 = contact_nodes[layer_nr].front(); - auto it = z_heights.lower_bound(node1->print_z + EPSILON); - if (it == z_heights.end()) it = std::prev(it); - int layer_nr2 = std::distance(z_heights.begin(), it); + auto it = std::min_element(layer_heights.begin(), layer_heights.end(), [node1](const LayerHeightData &l1, const LayerHeightData &l2) { + return std::abs(l1.print_z - node1->print_z) < std::abs(l2.print_z - node1->print_z); + }); + if (it == layer_heights.end()) it = std::prev(it); + int layer_nr2 = std::distance(layer_heights.begin(), it); contact_nodes2[layer_nr2].insert(contact_nodes2[layer_nr2].end(), contact_nodes[layer_nr].begin(), contact_nodes[layer_nr].end()); } contact_nodes = contact_nodes2; @@ -3285,7 +3286,7 @@ std::vector TreeSupport::plan_layer_heights() if (accum_height > node1->height - EPSILON) break; } } - BOOST_LOG_TRIVIAL(debug) << format("plan_layer_heights adjust node's height %d %.2f: (%.3f,%d)->(%.3f,%.3f,%d)", layer_nr, node1->print_z, + BOOST_LOG_TRIVIAL(debug) << format("plan_layer_heights adjust node's height print_z[%d]=%.2f: (%.3f,%d)->(%.3f,%.3f,%d)", layer_nr, node1->print_z, node1->height, node1->distance_to_top, new_height, accum_height, -num_layers); for (SupportNode *node : contact_nodes[layer_nr]) { node->height = new_height; @@ -3503,6 +3504,7 @@ void TreeSupport::generate_contact_points() if (!curr_nodes.empty()) nonempty_layers++; for (auto node : curr_nodes) { all_nodes.emplace_back(node->position(0), node->position(1), scale_(node->print_z)); } #ifdef SUPPORT_TREE_DEBUG_TO_SVG + if (!curr_nodes.empty()) draw_contours_and_nodes_to_svg(debug_out_path("init_contact_points_%.2f.svg", bottom_z), layer->loverhangs,layer->lslices_extrudable, m_ts_data->m_layer_outlines_below[layer_nr], contact_nodes[layer_nr], contact_nodes[layer_nr - 1], { "overhang","lslices","outlines_below"}); #endif diff --git a/src/libslic3r/Support/TreeSupport3D.cpp b/src/libslic3r/Support/TreeSupport3D.cpp index df9c869..9f3aeff 100644 --- a/src/libslic3r/Support/TreeSupport3D.cpp +++ b/src/libslic3r/Support/TreeSupport3D.cpp @@ -792,7 +792,7 @@ static std::optional> polyline_sample_next_point_at_dis if (distance == 0) return do_final_difference ? diff(ret, collision_trimmed()) : union_(ret); if (safe_step_size < 0 || last_step_offset_without_check < 0) { - BOOST_LOG_TRIVIAL(error) << "Offset increase got invalid parameter!"; + BOOST_LOG_TRIVIAL(warning) << "Offset increase got invalid parameter!"; tree_supports_show_error("Negative offset distance... How did you manage this ?"sv, true); return do_final_difference ? diff(ret, collision_trimmed()) : union_(ret); } @@ -1686,7 +1686,7 @@ static Point move_inside_if_outside(const Polygons &polygons, Point from, int di )); check_layer_data = current_elem.to_buildplate ? to_bp_data : to_model_data; if (area(check_layer_data) < tiny_area_threshold) { - BOOST_LOG_TRIVIAL(error) << "Lost area by doing catch up from " << ceil_radius_before << " to radius " << + BOOST_LOG_TRIVIAL(debug) << "Lost area by doing catch up from " << ceil_radius_before << " to radius " << volumes.ceilRadius(support_element_collision_radius(config, current_elem), settings.use_min_distance); tree_supports_show_error("Area lost catching up radius. May not cause visible malformation."sv, true); } @@ -1983,7 +1983,7 @@ static void increase_areas_one_layer( << "Trying to keep area by moving faster than intended: Success"; break; } else if (!settings.no_error) - BOOST_LOG_TRIVIAL(error) << "Trying to keep area by moving faster than intended: FAILURE! WRONG BRANCHES LIKLY!"; + BOOST_LOG_TRIVIAL(warning) << "Trying to keep area by moving faster than intended: FAILURE! WRONG BRANCHES LIKLY!"; } if (add) { @@ -2447,7 +2447,7 @@ void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupportSett return true; if (elem.areas.to_bp_areas.empty() && elem.areas.to_model_areas.empty()) { if (area(elem.areas.influence_areas) < tiny_area_threshold) { - BOOST_LOG_TRIVIAL(error) << "Insert Error of Influence area bypass on layer " << layer_idx - 1; + BOOST_LOG_TRIVIAL(warning) << "Insert Error of Influence area bypass on layer " << layer_idx - 1; tree_supports_show_error("Insert error of area after bypassing merge.\n"sv, true); } // Move the area to output. @@ -2480,7 +2480,7 @@ void create_layer_pathing(const TreeModelVolumes &volumes, const TreeSupportSett if (! elem.areas.influence_areas.empty()) { Polygons new_area = safe_union(elem.areas.influence_areas); if (area(new_area) < tiny_area_threshold) { - BOOST_LOG_TRIVIAL(error) << "Insert Error of Influence area on layer " << layer_idx - 1 << ". Origin of " << elem.parents.size() << " areas. Was to bp " << elem.state.to_buildplate; + BOOST_LOG_TRIVIAL(warning) << "Insert Error of Influence area on layer " << layer_idx - 1 << ". Origin of " << elem.parents.size() << " areas. Was to bp " << elem.state.to_buildplate; tree_supports_show_error("Insert error of area after merge.\n"sv, true); } this_layer.emplace_back(elem.state, std::move(elem.parents), std::move(new_area)); @@ -2509,7 +2509,7 @@ static void set_points_on_areas(const SupportElement &elem, SupportElements *lay // Based on the branch center point of the current layer, the point on the next (further up) layer is calculated. if (! elem.state.result_on_layer_is_set()) { - BOOST_LOG_TRIVIAL(error) << "Uninitialized support element"; + BOOST_LOG_TRIVIAL(warning) << "Uninitialized support element"; tree_supports_show_error("Uninitialized support element. A branch may be missing.\n"sv, true); return; } @@ -2677,7 +2677,8 @@ void create_nodes_from_area( if (! elem.state.result_on_layer_is_set()) { if (elem.state.to_buildplate || (elem.state.distance_to_top < config.min_dtt_to_model && ! elem.state.supports_roof)) { if (elem.state.to_buildplate) { - BOOST_LOG_TRIVIAL(error) << "Uninitialized Influence area targeting " << elem.state.target_position.x() << "," << elem.state.target_position.y() << ") " + BOOST_LOG_TRIVIAL(warning) << "Uninitialized Influence area targeting " << elem.state.target_position.x() << "," << elem.state.target_position.y() + << ") " "at target_height: " << elem.state.target_height << " layer: " << layer_idx; tree_supports_show_error("Uninitialized support element! A branch could be missing or exist partially."sv, true); } @@ -4213,7 +4214,6 @@ static void generate_support_areas(Print &print, TreeSupport* tree_support, cons // organic support default pattern is none. if (config.support_pattern == smpDefault) { config.support_pattern = smpNone; - support_params.support_density = 0; } diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index d695952..469aca1 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -386,8 +386,8 @@ bool TriangleMesh::is_splittable() const { return its_is_splittable(this->its); } - -std::vector TriangleMesh::split() const +const float MIN_MESH_VOLUME = 1e-2f; +std::vector TriangleMesh::split(float scale_det) const { std::vector itss = its_split(this->its); std::vector out; @@ -395,7 +395,7 @@ std::vector TriangleMesh::split() const for (indexed_triangle_set &m : itss) { // The TriangleMesh constructor shall fill in the mesh statistics including volume. TriangleMesh temp_triangle_mesh(std::move(m)); - if (abs(temp_triangle_mesh.volume()< 0.01)) {//0.01mm^3 + if (abs(temp_triangle_mesh.volume() * scale_det) < MIN_MESH_VOLUME) { continue; } if (temp_triangle_mesh.volume() < 0) {// Some source mesh parts may be incorrectly oriented. Correct them. @@ -406,7 +406,8 @@ std::vector TriangleMesh::split() const return out; } -std::vector TriangleMesh::split_and_save_relationship(std::vector> &result) const { +std::vector TriangleMesh::split_and_save_relationship(std::vector> &result, float scale_det) const +{ auto itss_and_ships = its_split_and_save_relationship<>(this->its); std::vector out; out.reserve(itss_and_ships.itses.size()); @@ -415,7 +416,7 @@ std::vector TriangleMesh::split_and_save_relationship(std::vector< for (indexed_triangle_set &m : itss_and_ships.itses) { // The TriangleMesh constructor shall fill in the mesh statistics including volume. TriangleMesh temp_triangle_mesh(std::move(m)); - if (abs(temp_triangle_mesh.volume() < 0.01)) { // 0.01mm^3 + if (abs(temp_triangle_mesh.volume() * scale_det) < MIN_MESH_VOLUME) { index++; continue; } diff --git a/src/libslic3r/TriangleMesh.hpp b/src/libslic3r/TriangleMesh.hpp index 4b1a7a0..cdb4cf9 100644 --- a/src/libslic3r/TriangleMesh.hpp +++ b/src/libslic3r/TriangleMesh.hpp @@ -118,8 +118,8 @@ public: void flip_triangles(); void align_to_origin(); void rotate(double angle, Point* center); - std::vector split() const; - std::vector split_and_save_relationship(std::vector> &result) const; + std::vector split(float scale_det = 1.f) const; + std::vector split_and_save_relationship(std::vector> &result, float scale_det = 1.f) const; void merge(const TriangleMesh &mesh); ExPolygons horizontal_projection() const; // 2D convex hull of a 3D mesh projected into the Z=0 plane.