From 4e315bcf27a52c845351915b64ff2a00b5f551fd Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 5 Sep 2022 14:16:08 +0200 Subject: [PATCH 1/7] Follow-up of 4e188c71c30677c64d97404c36d6cc8181938644 - Betterfix for update of non selected instances when applying mirror --- src/libslic3r/Geometry.cpp | 46 +++++++++++++++++++++++++----------- src/slic3r/GUI/Selection.cpp | 3 ++- 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/src/libslic3r/Geometry.cpp b/src/libslic3r/Geometry.cpp index 13878e9ec8..621289a618 100644 --- a/src/libslic3r/Geometry.cpp +++ b/src/libslic3r/Geometry.cpp @@ -550,12 +550,16 @@ void Transformation::set_rotation(Axis axis, double rotation) Vec3d Transformation::get_scaling_factor() const { const Transform3d scale = extract_scale(m_matrix); - return { scale(0, 0), scale(1, 1), scale(2, 2) }; + return { std::abs(scale(0, 0)), std::abs(scale(1, 1)), std::abs(scale(2, 2)) }; } Transform3d Transformation::get_scaling_factor_matrix() const { - return extract_scale(m_matrix); + Transform3d scale = extract_scale(m_matrix); + scale(0, 0) = std::abs(scale(0, 0)); + scale(1, 1) = std::abs(scale(1, 1)); + scale(2, 2) = std::abs(scale(2, 2)); + return scale; } #endif // ENABLE_WORLD_COORDINATE @@ -577,6 +581,8 @@ void Transformation::set_scaling_factor(const Vec3d& scaling_factor) void Transformation::set_scaling_factor(Axis axis, double scaling_factor) { #if ENABLE_WORLD_COORDINATE + assert(scaling_factor > 0.0); + auto [rotation, scale] = extract_rotation_scale(m_matrix); scale(axis, axis) = scaling_factor; @@ -600,8 +606,11 @@ Vec3d Transformation::get_mirror() const Transform3d Transformation::get_mirror_matrix() const { - const Vec3d scale = get_scaling_factor(); - return scale_transform({ scale.x() / std::abs(scale.x()), scale.y() / std::abs(scale.y()), scale.z() / std::abs(scale.z()) }); + Transform3d scale = extract_scale(m_matrix); + scale(0, 0) = scale(0, 0) / std::abs(scale(0, 0)); + scale(1, 1) = scale(1, 1) / std::abs(scale(1, 1)); + scale(2, 2) = scale(2, 2) / std::abs(scale(2, 2)); + return scale; } #endif // ENABLE_WORLD_COORDINATE @@ -617,13 +626,17 @@ void Transformation::set_mirror(const Vec3d& mirror) copy(i) /= abs_mirror(i); } - const Vec3d curr_scale = get_scaling_factor(); - const Vec3d signs = curr_scale.cwiseProduct(copy); - set_scaling_factor({ - signs.x() < 0.0 ? std::abs(curr_scale.x()) * copy.x() : curr_scale.x(), - signs.y() < 0.0 ? std::abs(curr_scale.y()) * copy.y() : curr_scale.y(), - signs.z() < 0.0 ? std::abs(curr_scale.z()) * copy.z() : curr_scale.z() - }); + auto [rotation, scale] = extract_rotation_scale(m_matrix); + const Vec3d curr_scales = { scale(0, 0), scale(1, 1), scale(2, 2) }; + const Vec3d signs = curr_scales.cwiseProduct(copy); + + if (signs[0] < 0.0) scale(0, 0) = -scale(0, 0); + if (signs[1] < 0.0) scale(1, 1) = -scale(1, 1); + if (signs[2] < 0.0) scale(2, 2) = -scale(2, 2); + + const Vec3d offset = get_offset(); + m_matrix = rotation * scale; + m_matrix.translation() = offset; #else set_mirror(X, mirror.x()); set_mirror(Y, mirror.y()); @@ -640,9 +653,15 @@ void Transformation::set_mirror(Axis axis, double mirror) mirror /= abs_mirror; #if ENABLE_WORLD_COORDINATE - const double curr_scale = get_scaling_factor(axis); + auto [rotation, scale] = extract_rotation_scale(m_matrix); + const double curr_scale = scale(axis, axis); const double sign = curr_scale * mirror; - set_scaling_factor(axis, sign < 0.0 ? std::abs(curr_scale) * mirror : curr_scale); + + if (sign < 0.0) scale(axis, axis) = -scale(axis, axis); + + const Vec3d offset = get_offset(); + m_matrix = rotation * scale; + m_matrix.translation() = offset; #else if (m_mirror(axis) != mirror) { m_mirror(axis) = mirror; @@ -746,7 +765,6 @@ Transform3d Transformation::get_matrix_no_scaling_factor() const { Transformation copy(*this); copy.reset_scaling_factor(); - copy.reset_mirror(); return copy.get_matrix(); } #else diff --git a/src/slic3r/GUI/Selection.cpp b/src/slic3r/GUI/Selection.cpp index a2d85bf512..0b2a13040a 100644 --- a/src/slic3r/GUI/Selection.cpp +++ b/src/slic3r/GUI/Selection.cpp @@ -2981,6 +2981,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ const Geometry::Transformation& curr_inst_trafo_i = volume_i->get_instance_transformation(); const Vec3d curr_inst_rotation_i = curr_inst_trafo_i.get_rotation(); const Vec3d& curr_inst_scaling_factor_i = curr_inst_trafo_i.get_scaling_factor(); + const Vec3d& curr_inst_mirror_i = curr_inst_trafo_i.get_mirror(); const Vec3d old_inst_rotation_i = m_cache.volumes_data[i].get_instance_transform().get_rotation(); #else const Vec3d& rotation = volume_i->get_instance_rotation(); @@ -3053,7 +3054,7 @@ void Selection::synchronize_unselected_instances(SyncRotationType sync_rotation_ #if ENABLE_WORLD_COORDINATE volume_j->set_instance_transformation(Geometry::assemble_transform(new_inst_offset_j, new_inst_rotation_j, - curr_inst_scaling_factor_i)); + curr_inst_scaling_factor_i, curr_inst_mirror_i)); #else volume_j->set_instance_scaling_factor(scaling_factor); volume_j->set_instance_mirror(mirror); From 39af553c2a8b1566a06136caffa3b3385a66c624 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 2 Sep 2022 11:29:58 +0200 Subject: [PATCH 2/7] Repetier validation using 'software' value if present #7807 --- src/slic3r/Utils/Repetier.cpp | 30 +++++++++++++++++++++++------- src/slic3r/Utils/Repetier.hpp | 3 --- 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/src/slic3r/Utils/Repetier.cpp b/src/slic3r/Utils/Repetier.cpp index 57c03c5564..f9d03390f9 100644 --- a/src/slic3r/Utils/Repetier.cpp +++ b/src/slic3r/Utils/Repetier.cpp @@ -35,6 +35,24 @@ Repetier::Repetier(DynamicPrintConfig *config) : const char* Repetier::get_name() const { return "Repetier"; } + + +static bool validate_repetier(const boost::optional& name, + const boost::optional& soft) +{ + if (soft) { + // See https://github.com/prusa3d/PrusaSlicer/issues/7807: + // Repetier allows "rebranding", so the "name" value is not reliable when detecting + // server type. Newer Repetier versions send "software", which should be invariant. + return ((*soft) == "Repetier-Server"); + } else { + // If there is no "software" value, validate as we did before: + return name ? boost::starts_with(*name, "Repetier") : true; + } +} + + + bool Repetier::test(wxString &msg) const { // Since the request is performed synchronously here, @@ -62,11 +80,12 @@ bool Repetier::test(wxString &msg) const std::stringstream ss(body); pt::ptree ptree; pt::read_json(ss, ptree); - + const auto text = ptree.get_optional("name"); - res = validate_version_text(text); + const auto soft = ptree.get_optional("software"); + res = validate_repetier(text, soft); if (! res) { - msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (text ? *text : "Repetier")).str()); + msg = GUI::from_u8((boost::format(_utf8(L("Mismatched type of print host: %s"))) % (soft ? *soft : (text ? *text : "Repetier"))).str()); } } catch (const std::exception &) { @@ -154,10 +173,7 @@ bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error return res; } -bool Repetier::validate_version_text(const boost::optional &version_text) const -{ - return version_text ? boost::starts_with(*version_text, "Repetier") : true; -} + void Repetier::set_auth(Http &http) const { diff --git a/src/slic3r/Utils/Repetier.hpp b/src/slic3r/Utils/Repetier.hpp index 8646681e9f..0c2f7e5077 100644 --- a/src/slic3r/Utils/Repetier.hpp +++ b/src/slic3r/Utils/Repetier.hpp @@ -33,9 +33,6 @@ public: bool get_groups(wxArrayString &groups) const override; bool get_printers(wxArrayString &printers) const override; -protected: - virtual bool validate_version_text(const boost::optional &version_text) const; - private: std::string host; std::string apikey; From d4dde50145c281673550c94f3a0bc6df39f8fb2a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Mon, 5 Sep 2022 14:23:29 +0200 Subject: [PATCH 3/7] Repetier: enforce autostart #7807 --- src/slic3r/Utils/Repetier.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/Utils/Repetier.cpp b/src/slic3r/Utils/Repetier.cpp index f9d03390f9..17724c350c 100644 --- a/src/slic3r/Utils/Repetier.cpp +++ b/src/slic3r/Utils/Repetier.cpp @@ -148,6 +148,7 @@ bool Repetier::upload(PrintHostUpload upload_data, ProgressFn prorgess_fn, Error if(upload_data.post_action == PrintHostPostUploadAction::StartPrint) { http.form_add("name", upload_filename.string()); + http.form_add("autostart", "true"); // See https://github.com/prusa3d/PrusaSlicer/issues/7807#issuecomment-1235519371 } http.form_add("a", "upload") From 7b812a120a751dae4d5ce3eb833619d4fb57c22b Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 6 Sep 2022 10:14:27 +0200 Subject: [PATCH 4/7] Tech ENABLE_RAYCAST_PICKING_DEBUG - Show number of active raycasters in debug imgui dialog and use ImGui tables to layout the dialog --- src/slic3r/GUI/GLCanvas3D.cpp | 41 ++++++++++++++++++++----------- src/slic3r/GUI/SceneRaycaster.cpp | 27 ++++++++++++++++++++ src/slic3r/GUI/SceneRaycaster.hpp | 3 +++ 3 files changed, 57 insertions(+), 14 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index dde881e449..18fd091d0d 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -5496,28 +5496,41 @@ void GLCanvas3D::_picking_pass() } default: { break; } } + + auto add_strings_row_to_table = [&imgui](const std::string& col_1, const ImVec4& col_1_color, const std::string& col_2, const ImVec4& col_2_color) { + ImGui::TableNextRow(); + ImGui::TableSetColumnIndex(0); + imgui.text_colored(col_1_color, col_1.c_str()); + ImGui::TableSetColumnIndex(1); + imgui.text_colored(col_2_color, col_2.c_str()); + }; + char buf[1024]; if (hit.type != SceneRaycaster::EType::None) { - sprintf(buf, "Object ID: %d", hit.raycaster_id); - imgui.text(std::string(buf)); - sprintf(buf, "Type: %s", object_type.c_str()); - imgui.text(std::string(buf)); - sprintf(buf, "Position: %.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z()); - imgui.text(std::string(buf)); - sprintf(buf, "Normal: %.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z()); - imgui.text(std::string(buf)); + if (ImGui::BeginTable("Hit", 2)) { + add_strings_row_to_table("Object ID", ImGuiWrapper::COL_ORANGE_LIGHT, std::to_string(hit.raycaster_id), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + add_strings_row_to_table("Type", ImGuiWrapper::COL_ORANGE_LIGHT, object_type, ImGui::GetStyleColorVec4(ImGuiCol_Text)); + sprintf(buf, "%.3f, %.3f, %.3f", hit.position.x(), hit.position.y(), hit.position.z()); + add_strings_row_to_table("Position", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + sprintf(buf, "%.3f, %.3f, %.3f", hit.normal.x(), hit.normal.y(), hit.normal.z()); + add_strings_row_to_table("Normal", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + ImGui::EndTable(); + } } else imgui.text("NO HIT"); ImGui::Separator(); imgui.text("Registered for picking:"); - sprintf(buf, "Beds: %d", (int)m_scene_raycaster.beds_count()); - imgui.text(std::string(buf)); - sprintf(buf, "Volumes: %d", (int)m_scene_raycaster.volumes_count()); - imgui.text(std::string(buf)); - sprintf(buf, "Gizmo elements: %d", (int)m_scene_raycaster.gizmos_count()); - imgui.text(std::string(buf)); + if (ImGui::BeginTable("Raycasters", 2)) { + sprintf(buf, "%d (%d)", (int)m_scene_raycaster.beds_count(), (int)m_scene_raycaster.active_beds_count()); + add_strings_row_to_table("Beds", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + sprintf(buf, "%d (%d)", (int)m_scene_raycaster.volumes_count(), (int)m_scene_raycaster.active_volumes_count()); + add_strings_row_to_table("Volumes", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + sprintf(buf, "%d (%d)", (int)m_scene_raycaster.gizmos_count(), (int)m_scene_raycaster.active_gizmos_count()); + add_strings_row_to_table("Gizmo elements", ImGuiWrapper::COL_ORANGE_LIGHT, std::string(buf), ImGui::GetStyleColorVec4(ImGuiCol_Text)); + ImGui::EndTable(); + } imgui.end(); #endif // ENABLE_RAYCAST_PICKING_DEBUG } diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 49a59789e3..63e84558e5 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -203,6 +203,33 @@ int SceneRaycaster::base_id(EType type) return -1; } +size_t SceneRaycaster::active_beds_count() const +{ + size_t count = 0; + for (const auto& item : m_bed) { + if (item->is_active()) ++count; + } + return count; +} + +size_t SceneRaycaster::active_volumes_count() const +{ + size_t count = 0; + for (const auto& item : m_volumes) { + if (item->is_active()) ++count; + } + return count; +} + +size_t SceneRaycaster::active_gizmos_count() const +{ + size_t count = 0; + for (const auto& item : m_gizmos) { + if (item->is_active()) ++count; + } + return count; +} + int SceneRaycaster::encode_id(EType type, int id) { return base_id(type) + id; } int SceneRaycaster::decode_id(EType type, int id) { return id - base_id(type); } diff --git a/src/slic3r/GUI/SceneRaycaster.hpp b/src/slic3r/GUI/SceneRaycaster.hpp index 8993c51a98..7541badbb4 100644 --- a/src/slic3r/GUI/SceneRaycaster.hpp +++ b/src/slic3r/GUI/SceneRaycaster.hpp @@ -100,6 +100,9 @@ public: size_t beds_count() const { return m_bed.size(); } size_t volumes_count() const { return m_volumes.size(); } size_t gizmos_count() const { return m_gizmos.size(); } + size_t active_beds_count() const; + size_t active_volumes_count() const; + size_t active_gizmos_count() const; #endif // ENABLE_RAYCAST_PICKING_DEBUG private: From 2ca3e47f922ee717522404c3912f9cb2530794e2 Mon Sep 17 00:00:00 2001 From: YuSanka Date: Tue, 6 Sep 2022 11:15:50 +0200 Subject: [PATCH 5/7] "legend_*"-icons from font_icons to font_icons_large to avoid blurring --- src/slic3r/GUI/ImGuiWrapper.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/slic3r/GUI/ImGuiWrapper.cpp b/src/slic3r/GUI/ImGuiWrapper.cpp index fa6e2c9031..737a95724f 100644 --- a/src/slic3r/GUI/ImGuiWrapper.cpp +++ b/src/slic3r/GUI/ImGuiWrapper.cpp @@ -56,6 +56,9 @@ static const std::map font_icons = { {ImGui::PreferencesHoverButton, "notification_preferences_hover"}, {ImGui::SliderFloatEditBtnIcon, "edit_button" }, {ImGui::SliderFloatEditBtnPressedIcon, "edit_button_pressed" }, +}; + +static const std::map font_icons_large = { #if ENABLE_LEGEND_TOOLBAR_ICONS {ImGui::LegendTravel , "legend_travel" }, {ImGui::LegendWipe , "legend_wipe" }, @@ -70,9 +73,6 @@ static const std::map font_icons = { {ImGui::LegendShells , "legend_shells" }, {ImGui::LegendToolMarker , "legend_toolmarker" }, #endif // ENABLE_LEGEND_TOOLBAR_ICONS -}; - -static const std::map font_icons_large = { {ImGui::CloseNotifButton , "notification_close" }, {ImGui::CloseNotifHoverButton , "notification_close_hover" }, {ImGui::EjectButton , "notification_eject_sd" }, @@ -94,7 +94,6 @@ static const std::map font_icons_large = { static const std::map font_icons_extra_large = { {ImGui::ClippyMarker , "notification_clippy" }, - }; const ImVec4 ImGuiWrapper::COL_GREY_DARK = { 0.33f, 0.33f, 0.33f, 1.0f }; From 464a37110fb0cc9e447cafdb315d00ae8fc79bdc Mon Sep 17 00:00:00 2001 From: PavelMikus Date: Tue, 6 Sep 2022 11:13:33 +0200 Subject: [PATCH 6/7] Staggered inner seams --- src/libslic3r/GCode/SeamPlacer.cpp | 83 +++++++++++++++++---------- src/libslic3r/GCode/SeamPlacer.hpp | 3 +- src/libslic3r/Preset.cpp | 2 +- src/libslic3r/PrintConfig.cpp | 6 ++ src/libslic3r/PrintConfig.hpp | 1 + src/libslic3r/SupportMaterial.cpp | 3 + src/slic3r/GUI/ConfigManipulation.cpp | 2 +- src/slic3r/GUI/Tab.cpp | 1 + 8 files changed, 67 insertions(+), 34 deletions(-) diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 88d73277ce..4df95d7552 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -395,8 +395,7 @@ struct GlobalModelInfo { ; //Extract perimeter polygons of the given layer -Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition configured_seam_preference, - std::vector &corresponding_regions_out) { +Polygons extract_perimeter_polygons(const Layer *layer, std::vector &corresponding_regions_out) { Polygons polygons; for (const LayerRegion *layer_region : layer->regions()) { for (const ExtrusionEntity *ex_entity : layer_region->perimeters.entities) { @@ -411,9 +410,7 @@ Polygons extract_perimeter_polygons(const Layer *layer, const SeamPosition confi } } - if (role == ExtrusionRole::erExternalPerimeter - || (is_perimeter(role) - && configured_seam_preference == spRandom)) { //for random seam alignment, extract all perimeters + if (role == ExtrusionRole::erExternalPerimeter) { Points p; perimeter->collect_points(p); polygons.emplace_back(std::move(p)); @@ -1044,14 +1041,13 @@ public: // Parallel process and extract each perimeter polygon of the given print object. // Gather SeamCandidates of each layer into vector and build KDtree over them // Store results in the SeamPlacer variables m_seam_per_object -void SeamPlacer::gather_seam_candidates(const PrintObject *po, - const SeamPlacerImpl::GlobalModelInfo &global_model_info, const SeamPosition configured_seam_preference) { +void SeamPlacer::gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info) { using namespace SeamPlacerImpl; PrintObjectSeamData &seam_data = m_seam_per_object.emplace(po, PrintObjectSeamData { }).first->second; seam_data.layers.resize(po->layer_count()); tbb::parallel_for(tbb::blocked_range(0, po->layers().size()), - [po, configured_seam_preference, &global_model_info, &seam_data] + [po, &global_model_info, &seam_data] (tbb::blocked_range r) { for (size_t layer_idx = r.begin(); layer_idx < r.end(); ++layer_idx) { PrintObjectSeamData::LayerSeams &layer_seams = seam_data.layers[layer_idx]; @@ -1059,7 +1055,7 @@ void SeamPlacer::gather_seam_candidates(const PrintObject *po, auto unscaled_z = layer->slice_z; std::vector regions; //NOTE corresponding region ptr may be null, if the layer has zero perimeters - Polygons polygons = extract_perimeter_polygons(layer, configured_seam_preference, regions); + Polygons polygons = extract_perimeter_polygons(layer, regions); for (size_t poly_index = 0; poly_index < polygons.size(); ++poly_index) { process_perimeter_polygon(polygons[poly_index], unscaled_z, regions[poly_index], global_model_info, layer_seams); @@ -1468,7 +1464,7 @@ void SeamPlacer::init(const Print &print, std::function throw_if_can throw_if_canceled_func(); BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather_seam_candidates: start"; - gather_seam_candidates(po, global_model_info, configured_seam_preference); + gather_seam_candidates(po, global_model_info); BOOST_LOG_TRIVIAL(debug) << "SeamPlacer: gather_seam_candidates: end"; throw_if_canceled_func(); @@ -1533,7 +1529,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern const size_t layer_index = layer->id() - po->slicing_parameters().raft_layers(); const double unscaled_z = layer->slice_z; - auto get_next_loop_point = [&loop](ExtrusionLoop::ClosestPathPoint current) { + auto get_next_loop_point = [loop](ExtrusionLoop::ClosestPathPoint current) { current.segment_idx += 1; if (current.segment_idx >= loop.paths[current.path_idx].polyline.points.size()) { current.path_idx = next_idx_modulo(current.path_idx, loop.paths.size()); @@ -1556,7 +1552,7 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern size_t points_count = std::accumulate(loop.paths.begin(), loop.paths.end(), 0, [](size_t acc,const ExtrusionPath& p) { return acc + p.polyline.points.size(); }); - for (size_t _ = 0; _ < points_count; ++_) { + for (size_t i = 0; i < points_count; ++i) { Vec2f unscaled_p = unscaled(closest_point.foot_pt); closest_perimeter_point_index = find_closest_point(*layer_perimeters.points_tree.get(), to_3d(unscaled_p, float(unscaled_z))); @@ -1586,13 +1582,12 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern Point seam_point = Point::new_scale(seam_position.x(), seam_position.y()); - if (const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index]; - (po->config().seam_position == spNearest || po->config().seam_position == spAligned) && - loop.role() == ExtrusionRole::erPerimeter && //Hopefully internal perimeter - (seam_position - perimeter_point.position).squaredNorm() < 4.0f && // seam is on perimeter point - perimeter_point.local_ccw_angle < -EPSILON // In concave angles - ) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align - // the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does) + if (loop.role() == ExtrusionRole::erPerimeter) { //Hopefully inner perimeter + const SeamCandidate &perimeter_point = layer_perimeters.points[seam_index]; + ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, false); + // determine depth of the seam point. + float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm(); + float beta_angle = cos(perimeter_point.local_ccw_angle / 2.0f); size_t index_of_prev = seam_index == perimeter_point.perimeter.start_index ? perimeter_point.perimeter.end_index - 1 : @@ -1602,18 +1597,46 @@ void SeamPlacer::place_seam(const Layer *layer, ExtrusionLoop &loop, bool extern perimeter_point.perimeter.start_index : seam_index + 1; - Vec2f dir_to_middle = - ((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized() - + (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized()) - * 0.5; + if ((seam_position - perimeter_point.position).squaredNorm() < depth && // seam is on perimeter point + perimeter_point.local_ccw_angle < -EPSILON // In concave angles + ) { // In this case, we are at internal perimeter, where the external perimeter has seam in concave angle. We want to align + // the internal seam into the concave corner, and not on the perpendicular projection on the closest edge (which is what the split_at function does) + Vec2f dir_to_middle = + ((perimeter_point.position - layer_perimeters.points[index_of_prev].position).head<2>().normalized() + + (perimeter_point.position - layer_perimeters.points[index_of_next].position).head<2>().normalized()) + * 0.5; + depth = 1.4142 * depth / beta_angle; + // There are some nice geometric identities in determination of the correct depth of new seam point. + //overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed. + Vec2f final_pos = perimeter_point.position.head<2>() + depth * dir_to_middle; + projected_point = loop.get_closest_path_and_point(Point::new_scale(final_pos.x(), final_pos.y()), false); + } else { // not concave angle, in that case the nearest point is the good candidate + // but for staggering, we also need to recompute depth of the inner perimter, because in convex corners, the distance is larger than layer width + // we want the perpendicular depth, not distance to nearest point + depth = depth * beta_angle / 1.4142; + } - ExtrusionLoop::ClosestPathPoint projected_point = loop.get_closest_path_and_point(seam_point, true); - //get closest projected point, determine depth of the seam point. - float depth = (float) unscale(Point(seam_point - projected_point.foot_pt)).norm(); - float angle_factor = cos(-perimeter_point.local_ccw_angle / 2.0f); // There are some nice geometric identities in determination of the correct depth of new seam point. - //overshoot the target depth, in concave angles it will correctly snap to the corner; TODO: find out why such big overshoot is needed. - Vec2f final_pos = perimeter_point.position.head<2>() + (1.4142 * depth / angle_factor) * dir_to_middle; - seam_point = Point::new_scale(final_pos.x(), final_pos.y()); + seam_point = projected_point.foot_pt; + + //lastly, for internal perimeters, do the staggering if requested + if (po->config().staggered_inner_seams && loop.length() > 0.0) { + //fix depth, it is sometimes strongly underestimated + depth = std::max(loop.paths[projected_point.path_idx].width, depth); + + while (depth > 0.0f) { + auto next_point = get_next_loop_point(projected_point); + Vec2f a = unscale(projected_point.foot_pt).cast(); + Vec2f b = unscale(next_point.foot_pt).cast(); + float dist = (a - b).norm(); + if (dist > depth) { + Vec2f final_pos = a + (b - a) * depth / dist; + next_point.foot_pt = Point::new_scale(final_pos.x(), final_pos.y()); + } + depth -= dist; + projected_point = next_point; + } + seam_point = projected_point.foot_pt; + } } // Because the G-code export has 1um resolution, don't generate segments shorter than 1.5 microns, diff --git a/src/libslic3r/GCode/SeamPlacer.hpp b/src/libslic3r/GCode/SeamPlacer.hpp index 8d52fd79f9..12db7c72bc 100644 --- a/src/libslic3r/GCode/SeamPlacer.hpp +++ b/src/libslic3r/GCode/SeamPlacer.hpp @@ -143,8 +143,7 @@ public: void place_seam(const Layer *layer, ExtrusionLoop &loop, bool external_first, const Point &last_pos) const; private: - void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info, - const SeamPosition configured_seam_preference); + void gather_seam_candidates(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); void calculate_candidates_visibility(const PrintObject *po, const SeamPlacerImpl::GlobalModelInfo &global_model_info); void calculate_overhangs_and_layer_embedding(const PrintObject *po); diff --git a/src/libslic3r/Preset.cpp b/src/libslic3r/Preset.cpp index f740c874ca..2634e415c4 100644 --- a/src/libslic3r/Preset.cpp +++ b/src/libslic3r/Preset.cpp @@ -421,7 +421,7 @@ static std::vector s_Preset_print_options { "layer_height", "first_layer_height", "perimeters", "spiral_vase", "slice_closing_radius", "slicing_mode", "top_solid_layers", "top_solid_min_thickness", "bottom_solid_layers", "bottom_solid_min_thickness", "extra_perimeters", "ensure_vertical_shell_thickness", "avoid_crossing_perimeters", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", + "seam_position","staggered_inner_seams", "external_perimeters_first", "fill_density", "fill_pattern", "top_fill_pattern", "bottom_fill_pattern", "infill_every_layers", "infill_only_where_needed", "solid_infill_every_layers", "fill_angle", "bridge_angle", "solid_infill_below_area", "only_retract_when_crossing_perimeters", "infill_first", "ironing", "ironing_type", "ironing_flowrate", "ironing_speed", "ironing_spacing", diff --git a/src/libslic3r/PrintConfig.cpp b/src/libslic3r/PrintConfig.cpp index efb92d3d3c..9a3bc3ce6f 100644 --- a/src/libslic3r/PrintConfig.cpp +++ b/src/libslic3r/PrintConfig.cpp @@ -2253,6 +2253,12 @@ void PrintConfigDef::init_fff_params() def->mode = comSimple; def->set_default_value(new ConfigOptionEnum(spAligned)); + def = this->add("staggered_inner_seams", coBool); + def->label = L("Staggered inner seams"); + def->tooltip = L("This option causes the inner seams to be shifted backwards based on their depth, forming a zigzag pattern."); + def->mode = comAdvanced; + def->set_default_value(new ConfigOptionBool(false)); + #if 0 def = this->add("seam_preferred_direction", coFloat); // def->gui_type = ConfigOptionDef::GUIType::slider; diff --git a/src/libslic3r/PrintConfig.hpp b/src/libslic3r/PrintConfig.hpp index 5cc5cc59cd..48493aa0bd 100644 --- a/src/libslic3r/PrintConfig.hpp +++ b/src/libslic3r/PrintConfig.hpp @@ -503,6 +503,7 @@ PRINT_CONFIG_CLASS_DEFINE( ((ConfigOptionFloat, raft_first_layer_expansion)) ((ConfigOptionInt, raft_layers)) ((ConfigOptionEnum, seam_position)) + ((ConfigOptionBool, staggered_inner_seams)) // ((ConfigOptionFloat, seam_preferred_direction)) // ((ConfigOptionFloat, seam_preferred_direction_jitter)) ((ConfigOptionFloat, slice_closing_radius)) diff --git a/src/libslic3r/SupportMaterial.cpp b/src/libslic3r/SupportMaterial.cpp index e8ee782f43..4910168873 100644 --- a/src/libslic3r/SupportMaterial.cpp +++ b/src/libslic3r/SupportMaterial.cpp @@ -43,6 +43,9 @@ #include "SVG.hpp" #endif +#pragma message ("TODO: Wrap svg usages in DEBUG ifdef and remove the following include") +#include "SVG.hpp" + // #undef NDEBUG #include diff --git a/src/slic3r/GUI/ConfigManipulation.cpp b/src/slic3r/GUI/ConfigManipulation.cpp index 96bf2fe020..c571d1d2af 100644 --- a/src/slic3r/GUI/ConfigManipulation.cpp +++ b/src/slic3r/GUI/ConfigManipulation.cpp @@ -219,7 +219,7 @@ void ConfigManipulation::toggle_print_fff_options(DynamicPrintConfig* config) { bool have_perimeters = config->opt_int("perimeters") > 0; for (auto el : { "extra_perimeters", "ensure_vertical_shell_thickness", "thin_walls", "overhangs", - "seam_position", "external_perimeters_first", "external_perimeter_extrusion_width", + "seam_position","staggered_inner_seams", "external_perimeters_first", "external_perimeter_extrusion_width", "perimeter_speed", "small_perimeter_speed", "external_perimeter_speed" }) toggle_field(el, have_perimeters); diff --git a/src/slic3r/GUI/Tab.cpp b/src/slic3r/GUI/Tab.cpp index 8c6b349b40..5f92f98a37 100644 --- a/src/slic3r/GUI/Tab.cpp +++ b/src/slic3r/GUI/Tab.cpp @@ -1440,6 +1440,7 @@ void TabPrint::build() optgroup = page->new_optgroup(L("Advanced")); optgroup->append_single_option_line("seam_position", category_path + "seam-position"); + optgroup->append_single_option_line("staggered_inner_seams", category_path + "staggered-inner-seams"); optgroup->append_single_option_line("external_perimeters_first", category_path + "external-perimeters-first"); optgroup->append_single_option_line("gap_fill_enabled", category_path + "fill-gaps"); optgroup->append_single_option_line("perimeter_generator"); From 6e52fbc6d045371b987ec0437b2651893309db29 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Tue, 6 Sep 2022 11:48:27 +0200 Subject: [PATCH 7/7] Follow-up of 7b812a120a751dae4d5ce3eb833619d4fb57c22b - Added missing #if/#endif --- src/slic3r/GUI/SceneRaycaster.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/slic3r/GUI/SceneRaycaster.cpp b/src/slic3r/GUI/SceneRaycaster.cpp index 63e84558e5..6d255ccdb4 100644 --- a/src/slic3r/GUI/SceneRaycaster.cpp +++ b/src/slic3r/GUI/SceneRaycaster.cpp @@ -203,6 +203,7 @@ int SceneRaycaster::base_id(EType type) return -1; } +#if ENABLE_RAYCAST_PICKING_DEBUG size_t SceneRaycaster::active_beds_count() const { size_t count = 0; @@ -229,6 +230,7 @@ size_t SceneRaycaster::active_gizmos_count() const } return count; } +#endif // ENABLE_RAYCAST_PICKING_DEBUG int SceneRaycaster::encode_id(EType type, int id) { return base_id(type) + id; } int SceneRaycaster::decode_id(EType type, int id) { return id - base_id(type); }