diff --git a/lib/Slic3r/Test.pm b/lib/Slic3r/Test.pm index 570bca41b..8d2a79f2a 100644 --- a/lib/Slic3r/Test.pm +++ b/lib/Slic3r/Test.pm @@ -192,12 +192,12 @@ sub init_print { if (defined $params{duplicate} && $params{duplicate} > 1) { $model->duplicate($params{duplicate} // 1, $config->min_object_distance); } - $model->arrange_objects($config->min_object_distance); - $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); foreach my $model_object (@{$model->objects}) { $model_object->ensure_on_bed; $print->auto_assign_extruders($model_object); } + $model->arrange_objects($config->min_object_distance); + $model->center_instances_around_point($params{print_center} ? Slic3r::Pointf->new(@{$params{print_center}}) : Slic3r::Pointf->new(100,100)); $print->apply($model, $config); $print->validate; diff --git a/src/libslic3r/TriangleMesh.cpp b/src/libslic3r/TriangleMesh.cpp index 8648edc52..fba1429ea 100644 --- a/src/libslic3r/TriangleMesh.cpp +++ b/src/libslic3r/TriangleMesh.cpp @@ -914,7 +914,7 @@ void its_collect_mesh_projection_points_above(const indexed_triangle_set &its, c float t = (z - p1.z()) / (p2.z() - p1.z()); all_pts.emplace_back(scaled(p1.x() + (p2.x() - p1.x()) * t), scaled(p1.y() + (p2.y() - p1.y()) * t)); } - if (p2.z() > z) + if (p2.z() >= z) all_pts.emplace_back(scaled(p2.x()), scaled(p2.y())); iprev = iedge; } diff --git a/src/slic3r/GUI/GCodeViewer.cpp b/src/slic3r/GUI/GCodeViewer.cpp index d13daa750..e7daa24ec 100644 --- a/src/slic3r/GUI/GCodeViewer.cpp +++ b/src/slic3r/GUI/GCodeViewer.cpp @@ -596,7 +596,7 @@ void GCodeViewer::load(const GCodeProcessor::Result& gcode_result, const Print& m_last_result_id = gcode_result.id; // release gpu memory, if used - reset(); + reset(); #if ENABLE_GCODE_WINDOW m_sequential_view.gcode_window.set_filename(gcode_result.filename); diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 826342678..1c69683c9 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -4621,6 +4621,14 @@ void GLCanvas3D::_resize(unsigned int w, unsigned int h) if (m_canvas == nullptr && m_context == nullptr) return; +#if ENABLE_SCROLLABLE_LEGEND + const std::array new_size = { w, h }; + if (m_old_size == new_size) + return; + + m_old_size = new_size; +#endif // ENABLE_SCROLLABLE_LEGEND + auto *imgui = wxGetApp().imgui(); imgui->set_display_size(static_cast(w), static_cast(h)); const float font_size = 1.5f * wxGetApp().em_unit(); diff --git a/src/slic3r/GUI/GLCanvas3D.hpp b/src/slic3r/GUI/GLCanvas3D.hpp index 9b5c3a911..9b823eae7 100644 --- a/src/slic3r/GUI/GLCanvas3D.hpp +++ b/src/slic3r/GUI/GLCanvas3D.hpp @@ -425,6 +425,10 @@ private: Model* m_model; BackgroundSlicingProcess *m_process; +#if ENABLE_SCROLLABLE_LEGEND + std::array m_old_size{ 0, 0 }; +#endif // ENABLE_SCROLLABLE_LEGEND + // Screen is only refreshed from the OnIdle handler if it is dirty. bool m_dirty; bool m_initialized; @@ -756,6 +760,10 @@ public: const Print* fff_print() const; const SLAPrint* sla_print() const; +#if ENABLE_SCROLLABLE_LEGEND + void reset_old_size() { m_old_size = { 0, 0 }; } +#endif // ENABLE_SCROLLABLE_LEGEND + private: bool _is_shown_on_screen() const; diff --git a/src/slic3r/GUI/NotificationManager.cpp b/src/slic3r/GUI/NotificationManager.cpp index 1b29b7f76..921f9f2b1 100644 --- a/src/slic3r/GUI/NotificationManager.cpp +++ b/src/slic3r/GUI/NotificationManager.cpp @@ -6,6 +6,7 @@ #include "PrintHostDialogs.hpp" #include "wxExtensions.hpp" #include "../Utils/PrintHost.hpp" +#include "libslic3r/Config.hpp" #include #include @@ -304,8 +305,8 @@ void NotificationManager::PopNotification::count_lines() } // hypertext calculation if (!m_hypertext.empty()) { - int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; - if (ImGui::CalcTextSize((text.substr(prev_end, last_end - prev_end) + m_hypertext).c_str()).x > m_window_width - m_window_width_offset) { + int prev_end = m_endlines.size() > 1 ? m_endlines[m_endlines.size() - 2] : 0; // m_endlines.size() - 2 because we are fitting hypertext instead of last endline + if (ImGui::CalcTextSize((escape_string_cstyle(text.substr(prev_end, last_end - prev_end)) + m_hypertext).c_str()).x > m_window_width - m_window_width_offset) { m_endlines.push_back(last_end); m_lines_count++; } @@ -366,7 +367,7 @@ void NotificationManager::PopNotification::render_text(ImGuiWrapper& imgui, cons } //hyperlink text if (!m_hypertext.empty()) { - render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + " ").c_str()).x, starting_y + (m_lines_count - 1) * shift_y, m_hypertext); + render_hypertext(imgui, x_offset + ImGui::CalcTextSize((line + (line.empty() ? "" : " ")).c_str()).x, starting_y + (m_lines_count - 1) * shift_y, m_hypertext); } diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index 54eddb5e1..45242c593 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -3452,8 +3452,12 @@ void Plater::priv::set_current_panel(wxPanel* panel) // sets the canvas as dirty to force a render at the 1st idle event (wxWidgets IsShownOnScreen() is buggy and cannot be used reliably) view3D->set_as_dirty(); +#if ENABLE_SCROLLABLE_LEGEND + // reset cached size to force a resize on next call to render() to keep imgui in synch with canvas size + view3D->get_canvas3d()->reset_old_size(); +#endif // ENABLE_SCROLLABLE_LEGEND view_toolbar.select_item("3D"); - if(notification_manager != nullptr) + if (notification_manager != nullptr) notification_manager->set_in_preview(false); } else if (current_panel == preview) { @@ -3472,6 +3476,10 @@ void Plater::priv::set_current_panel(wxPanel* panel) preview->reload_print(true); preview->set_as_dirty(); +#if ENABLE_SCROLLABLE_LEGEND + // reset cached size to force a resize on next call to render() to keep imgui in synch with canvas size + preview->get_canvas3d()->reset_old_size(); +#endif // ENABLE_SCROLLABLE_LEGEND view_toolbar.select_item("Preview"); if (notification_manager != nullptr) notification_manager->set_in_preview(true); diff --git a/tests/libslic3r/test_3mf.cpp b/tests/libslic3r/test_3mf.cpp index fb41ef93b..d6d3686d9 100644 --- a/tests/libslic3r/test_3mf.cpp +++ b/tests/libslic3r/test_3mf.cpp @@ -85,3 +85,43 @@ SCENARIO("Export+Import geometry to/from 3mf file cycle", "[3mf]") { } } } + +SCENARIO("2D convex hull of sinking object", "[3mf]") { + GIVEN("model") { + // load a model + Model model; + std::string src_file = std::string(TEST_DATA_DIR) + "/test_3mf/Prusa.stl"; + load_stl(src_file.c_str(), &model); + model.add_default_instances(); + + WHEN("model is rotated, scaled and set as sinking") { + ModelObject* object = model.objects[0]; + object->center_around_origin(false); + + // set instance's attitude so that it is rotated, scaled and sinking + ModelInstance* instance = object->instances[0]; + instance->set_rotation(Y, -M_PI / 4.0); + instance->set_offset(Vec3d::Zero()); + instance->set_scaling_factor({ 2.0, 2.0, 2.0 }); + + // calculate 2D convex hull + Polygon hull_2d = object->convex_hull_2d(instance->get_transformation().get_matrix()); + + // verify result + Points result = { + { -4242641, -16299551 }, + { -4241, -19502998 }, + { 66824768, -19502998 }, + { 66824768, 19502998 }, + { -4244, 19502998 }, + { -4242640, -8537523 } + }; + bool res = hull_2d.points == result; + + THEN("2D convex hull should match with reference") { + REQUIRE(res); + } + } + } +} +