From dda0b50b5c589a237b128bed2d6547659328414f Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 3 Nov 2022 12:14:27 +0100 Subject: [PATCH 01/16] Fixed a crash in measuring backend when handling broken models --- src/libslic3r/Measure.cpp | 45 +++++++++++++++++++++++++++++---------- 1 file changed, 34 insertions(+), 11 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index f64b79e22..6e11b853a 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -87,6 +87,10 @@ void MeasuringImpl::update_planes() return (std::abs(a(0) - b(0)) < 0.001 && std::abs(a(1) - b(1)) < 0.001 && std::abs(a(2) - b(2)) < 0.001); }; + // First go through all the triangles and fill in m_planes vector. For each "plane" + // detected on the model, it will contain list of facets that are part of it. + // We will also fill in m_face_to_plane, which contains index into m_planes + // for each of the source facets. while (1) { // Find next unvisited triangle: for (; seed_facet_idx < num_of_facets; ++ seed_facet_idx) @@ -117,20 +121,29 @@ void MeasuringImpl::update_planes() m_planes.back().normal = normal_ptr->cast(); std::sort(m_planes.back().facets.begin(), m_planes.back().facets.end()); } - + + // Check that each facet is part of one of the planes. assert(std::none_of(m_face_to_plane.begin(), m_face_to_plane.end(), [](size_t val) { return val == size_t(-1); })); + // Now we will walk around each of the planes and save vertices which form the border. SurfaceMesh sm(m_its); for (int plane_id=0; plane_id < int(m_planes.size()); ++plane_id) { - //int plane_id = 5; { const auto& facets = m_planes[plane_id].facets; m_planes[plane_id].borders.clear(); std::vector> visited(facets.size(), {false, false, false}); + + for (int face_id=0; face_id& border : plane.borders) { - assert(border.size() > 1); + if (border.size() <= 1) + continue; int start_idx = -1; // First calculate angles at all the vertices. From 05e82b1fc569f6fe02d29784a87aa7611164d349 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 3 Nov 2022 13:20:35 +0100 Subject: [PATCH 02/16] Measuring: validation for zero distance moved from backend to frontend --- src/libslic3r/Measure.cpp | 8 -------- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 2 +- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 6e11b853a..ffff12bab 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -1060,14 +1060,6 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& else result.angle = angle_plane_plane(f1.get_plane(), f2.get_plane()); } - - // validation - if (result.distance_infinite.has_value() && result.distance_infinite->dist < EPSILON) - result.distance_infinite.reset(); - if (result.distance_strict.has_value() && result.distance_strict->dist < EPSILON) - result.distance_strict.reset(); - if (result.angle.has_value() && std::abs(result.angle->angle) < EPSILON) - result.angle.reset(); return result; } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 74be878f1..d296bb3c4 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -905,7 +905,7 @@ void GLGizmoMeasure::render_dimensioning() return; auto point_point = [this, shader](const Vec3d& v1, const Vec3d& v2, float distance) { - if (v1.isApprox(v2)) + if ((v2 - v2).squaredNorm() < 0.000001) return; const Camera& camera = wxGetApp().plater()->get_camera(); From a4e4a716179ec9d5605da6959f087614fe33655e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 3 Nov 2022 13:37:38 +0100 Subject: [PATCH 03/16] Measuring: disabled rectangle selection when the Measure Gizmo is active --- src/slic3r/GUI/GLCanvas3D.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index 3fa5c24c6..fd4c705c5 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3460,6 +3460,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) m_gizmos.get_current_type() != GLGizmosManager::FdmSupports && m_gizmos.get_current_type() != GLGizmosManager::Seam && m_gizmos.get_current_type() != GLGizmosManager::Cut && + m_gizmos.get_current_type() != GLGizmosManager::Measure && m_gizmos.get_current_type() != GLGizmosManager::MmuSegmentation) { m_rectangle_selection.start_dragging(m_mouse.position, evt.ShiftDown() ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect); m_dirty = true; From 4f6217a54c3c7cdb433b3efdb5bb7b1c540e2aa5 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 3 Nov 2022 14:14:35 +0100 Subject: [PATCH 04/16] Fixed typo introduced with 05e82b1fc569f6fe02d29784a87aa7611164d349 --- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index d296bb3c4..4255eb7b9 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -905,7 +905,7 @@ void GLGizmoMeasure::render_dimensioning() return; auto point_point = [this, shader](const Vec3d& v1, const Vec3d& v2, float distance) { - if ((v2 - v2).squaredNorm() < 0.000001) + if ((v2 - v1).squaredNorm() < 0.000001 || distance < 0.001f) return; const Camera& camera = wxGetApp().plater()->get_camera(); From 7650be770c37e39d8a9763d8909fb71fabc19665 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 3 Nov 2022 14:24:28 +0100 Subject: [PATCH 05/16] Measuring: tweak to calculation of edge-edge distance --- src/libslic3r/Measure.cpp | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index ffff12bab..ef685b15d 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -682,16 +682,16 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& if (f2.get_type() == SurfaceFeatureType::Edge) { std::vector distances; -// auto add_point_edge_distance = [&distances](const Vec3d& v, const std::pair& e) { -// const MeasurementResult res = get_measurement(SurfaceFeature(v), SurfaceFeature(SurfaceFeatureType::Edge, e.first, e.second)); -// double distance = res.distance_strict->dist; -// Vec3d v2 = res.distance_strict->to; -// -// const Vec3d e1e2 = e.second - e.first; -// const Vec3d e1v2 = v2 - e.first; -// if (e1v2.dot(e1e2) >= 0.0 && e1v2.norm() < e1e2.norm()) -// distances.emplace_back(distance, v, v2); -// }; + auto add_point_edge_distance = [&distances](const Vec3d& v, const std::pair& e) { + const MeasurementResult res = get_measurement(SurfaceFeature(v), SurfaceFeature(SurfaceFeatureType::Edge, e.first, e.second)); + double distance = res.distance_strict->dist; + Vec3d v2 = res.distance_strict->to; + + const Vec3d e1e2 = e.second - e.first; + const Vec3d e1v2 = v2 - e.first; + if (e1v2.dot(e1e2) >= 0.0 && e1v2.norm() < e1e2.norm()) + distances.emplace_back(distance, v, v2); + }; std::pair e1 = f1.get_edge(); std::pair e2 = f2.get_edge(); @@ -700,10 +700,10 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& distances.emplace_back((e2.second - e1.first).norm(), e1.first, e2.second); distances.emplace_back((e2.first - e1.second).norm(), e1.second, e2.first); distances.emplace_back((e2.second - e1.second).norm(), e1.second, e2.second); -// add_point_edge_distance(e1.first, e2); -// add_point_edge_distance(e1.second, e2); -// add_point_edge_distance(e2.first, e1); -// add_point_edge_distance(e2.second, e1); + add_point_edge_distance(e1.first, e2); + add_point_edge_distance(e1.second, e2); + add_point_edge_distance(e2.first, e1); + add_point_edge_distance(e2.second, e1); auto it = std::min_element(distances.begin(), distances.end(), [](const DistAndPoints& item1, const DistAndPoints& item2) { return item1.dist < item2.dist; From 2eb363bc6484bd4270d740ff07da7a5c1e443c5a Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Thu, 3 Nov 2022 15:03:10 +0100 Subject: [PATCH 06/16] Measuring: modified rendering order of dimensioning items --- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 25 ++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 4255eb7b9..858b4e5ce 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -1271,13 +1271,6 @@ void GLGizmoMeasure::render_dimensioning() if (m_selected_features.second.feature.has_value()) { const bool has_distance = m_measurement_result.has_distance_data(); - if (has_distance) { - // Render the arrow between the points that the backend passed: - const Measure::DistAndPoints& dap = m_measurement_result.distance_infinite.has_value() - ? *m_measurement_result.distance_infinite - : *m_measurement_result.distance_strict; - point_point(dap.from, dap.to, dap.dist); - } const Measure::SurfaceFeature* f1 = &(*m_selected_features.first.feature); const Measure::SurfaceFeature* f2 = &(*m_selected_features.second.feature); @@ -1290,17 +1283,25 @@ void GLGizmoMeasure::render_dimensioning() std::swap(f1, f2); } - // Where needed, draw also the extension of the edge to where the dist is measured: - if (has_distance && ft1 == Measure::SurfaceFeatureType::Point && ft2 == Measure::SurfaceFeatureType::Edge) - point_edge(*f1, *f2); - - // Now if there is an angle to show, draw the arc: + // If there is an angle to show, draw the arc: if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Edge) arc_edge_edge(*f1, *f2); else if (ft1 == Measure::SurfaceFeatureType::Edge && ft2 == Measure::SurfaceFeatureType::Plane) arc_edge_plane(*f1, *f2); else if (ft1 == Measure::SurfaceFeatureType::Plane && ft2 == Measure::SurfaceFeatureType::Plane) arc_plane_plane(*f1, *f2); + + if (has_distance){ + // Where needed, draw the extension of the edge to where the dist is measured: + if (ft1 == Measure::SurfaceFeatureType::Point && ft2 == Measure::SurfaceFeatureType::Edge) + point_edge(*f1, *f2); + + // Render the arrow between the points that the backend passed: + const Measure::DistAndPoints& dap = m_measurement_result.distance_infinite.has_value() + ? *m_measurement_result.distance_infinite + : *m_measurement_result.distance_strict; + point_point(dap.from, dap.to, dap.dist); + } } glsafe(::glEnable(GL_DEPTH_TEST)); From 76064fc2ba9bb81c6eef55e97ecec8550978b49e Mon Sep 17 00:00:00 2001 From: YuSanka Date: Thu, 3 Nov 2022 15:24:23 +0100 Subject: [PATCH 07/16] Fix for #9100 - Search feature in the settings is broken - every time moves the cursor at the end of the text --- src/slic3r/GUI/Search.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/slic3r/GUI/Search.cpp b/src/slic3r/GUI/Search.cpp index 52e58193c..88d3e1376 100644 --- a/src/slic3r/GUI/Search.cpp +++ b/src/slic3r/GUI/Search.cpp @@ -594,8 +594,6 @@ void SearchDialog::ProcessSelection(wxDataViewItem selection) void SearchDialog::OnInputText(wxCommandEvent&) { - search_line->SetInsertionPointEnd(); - wxString input_string = search_line->GetValue(); if (input_string == default_string) input_string.Clear(); From 4b9630c23b7c46d3f7cfdb26837779ee690cc46a Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 3 Nov 2022 15:10:47 +0100 Subject: [PATCH 08/16] Measurement: Circles filtering (part 1) --- src/libslic3r/Measure.cpp | 36 +++++++++++++++++++++++++++--------- 1 file changed, 27 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index ef685b15d..b309fc56d 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -196,14 +196,17 @@ void MeasuringImpl::update_planes() if (last_border.size() == 1) m_planes[plane_id].borders.pop_back(); + else { + assert(m_planes[plane_id].borders.front() == m_planes[plane_id].borders.back()); + } } } - continue; // There was no failure. PLANE_FAILURE: m_planes[plane_id].borders.clear(); } + } @@ -233,15 +236,16 @@ void MeasuringImpl::extract_features() for (const std::vector& border : plane.borders) { if (border.size() <= 1) continue; + assert(border.front() == border.back()); int start_idx = -1; // First calculate angles at all the vertices. angles.clear(); lengths.clear(); - for (int i=0; i M_PI) @@ -268,10 +272,24 @@ void MeasuringImpl::extract_features() } } else { if (circle) { - // Add the circle and remember indices into borders. - const auto& [center, radius] = get_center_and_radius(border, start_idx, i, trafo); - circles_idxs.emplace_back(start_idx, i); - circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); + // Anything made up of less than 4 points shall not be considered a circle. + if (i-start_idx > 3) { + // This may be just a partial circle, maybe a small one generated by two short edges. + // To qualify as a circle, it should cover at least one quadrant. Check this now. + const auto& [center, radius] = get_center_and_radius(border, start_idx, i, trafo); + const Vec3d& p1 = border[start_idx]; + const Vec3d& p2 = border[i]; + const Vec3d& p3 = border[size_t(start_idx+i)/2]; + + // Measure angle between the first and the second radiuses. If smaller than 90 deg, measure angle + // between first radius and one corresponding to the middle of the circle. + if ((p1-center).normalized().dot((p2-center).normalized()) < 0.05 // exactly 90 deg might get rejected + || (p1-center).normalized().dot((p3-center).normalized()) < 0.) { + // Add the circle and remember indices into borders. + circles_idxs.emplace_back(start_idx, i); + circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); + } + } circle = false; } } From d07537c1f047a23082ead5bec131757b0e6598e1 Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Thu, 3 Nov 2022 17:57:09 +0100 Subject: [PATCH 09/16] Measurement: Merge adjacent edges --- src/libslic3r/Measure.cpp | 38 ++++++++++++++++++++++++++++++-------- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index b309fc56d..965fad9f9 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -206,7 +206,6 @@ void MeasuringImpl::update_planes() PLANE_FAILURE: m_planes[plane_id].borders.clear(); } - } @@ -261,6 +260,7 @@ void MeasuringImpl::extract_features() bool circle = false; std::vector circles; std::vector> circles_idxs; + //std::vector angle_and_vert_num_per_circle; for (int i=1; i<(int)angles.size(); ++i) { if (Slic3r::is_approx(lengths[i], lengths[i-1]) && Slic3r::is_approx(angles[i], angles[i-1]) @@ -288,12 +288,24 @@ void MeasuringImpl::extract_features() // Add the circle and remember indices into borders. circles_idxs.emplace_back(start_idx, i); circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); + //angle_and_vert_num_per_circle.emplace_back(..., ...); } } circle = false; } } } +/* + // At this point we must merge the first and last circles. The dicrimination of too small + // circles will follow, so we need a complete picture before that. + assert(circles.size() == angle_and_vert_num_per_circle.size()); + for (size_t i=0; i=0; --i) { + const auto& [first_start, first_end] = plane.surface_features[i==0 ? plane.surface_features.size()-1 : i-1].get_edge(); + const auto& [second_start, second_end] = plane.surface_features[i].get_edge(); + + if (Slic3r::is_approx(first_end, second_start) + && Slic3r::is_approx((first_end-first_start).normalized().dot((second_end-second_start).normalized()), 1.)) { + // The edges have the same direction and share a point. Merge them. + plane.surface_features[i==0 ? plane.surface_features.size()-1 : i-1] = SurfaceFeature(SurfaceFeatureType::Edge, first_start, second_end); + plane.surface_features.erase(plane.surface_features.begin() + i); + } + } + + + // FIXME Throw away / do not create edges which are parts of circles or // which lead to circle points (unless they belong to the same plane.) - // FIXME Check and merge first and last circle if needed. - // Now move the circles into the feature list. assert(std::all_of(circles.begin(), circles.end(), [](const SurfaceFeature& f) { return f.get_type() == SurfaceFeatureType::Circle; From 0c88b5712a0ab67c784c9a8ab4814959f049326c Mon Sep 17 00:00:00 2001 From: Lukas Matena Date: Fri, 4 Nov 2022 09:05:12 +0100 Subject: [PATCH 10/16] Measurement: Circles filtering (part 2) --- src/libslic3r/Measure.cpp | 187 ++++++++++++++++++++++++-------------- 1 file changed, 120 insertions(+), 67 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 965fad9f9..f15be5bea 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -197,7 +197,7 @@ void MeasuringImpl::update_planes() if (last_border.size() == 1) m_planes[plane_id].borders.pop_back(); else { - assert(m_planes[plane_id].borders.front() == m_planes[plane_id].borders.back()); + assert(last_border.front() == last_border.back()); } } } @@ -215,9 +215,6 @@ void MeasuringImpl::update_planes() void MeasuringImpl::extract_features() { - auto N_to_angle = [](double N) -> double { return 2.*M_PI / N; }; - constexpr double polygon_upper_threshold = N_to_angle(4.5); - constexpr double polygon_lower_threshold = N_to_angle(8.5); std::vector angles; std::vector lengths; @@ -238,6 +235,8 @@ void MeasuringImpl::extract_features() assert(border.front() == border.back()); int start_idx = -1; + std::vector edges; + // First calculate angles at all the vertices. angles.clear(); lengths.clear(); @@ -251,16 +250,19 @@ void MeasuringImpl::extract_features() angle = 2*M_PI - angle; angles.push_back(angle); - lengths.push_back(v2.squaredNorm()); + lengths.push_back(v2.norm()); } assert(border.size() == angles.size()); assert(border.size() == lengths.size()); + // First go around the border and pick what might be circular segments. + // Save pair of indices to where such potential segments start and end. + // Also remember the length of these segments. bool circle = false; std::vector circles; - std::vector> circles_idxs; - //std::vector angle_and_vert_num_per_circle; + std::vector> circles_idxs; + std::vector circles_lengths; for (int i=1; i<(int)angles.size(); ++i) { if (Slic3r::is_approx(lengths[i], lengths[i-1]) && Slic3r::is_approx(angles[i], angles[i-1]) @@ -272,98 +274,149 @@ void MeasuringImpl::extract_features() } } else { if (circle) { - // Anything made up of less than 4 points shall not be considered a circle. - if (i-start_idx > 3) { - // This may be just a partial circle, maybe a small one generated by two short edges. - // To qualify as a circle, it should cover at least one quadrant. Check this now. - const auto& [center, radius] = get_center_and_radius(border, start_idx, i, trafo); - const Vec3d& p1 = border[start_idx]; - const Vec3d& p2 = border[i]; - const Vec3d& p3 = border[size_t(start_idx+i)/2]; - - // Measure angle between the first and the second radiuses. If smaller than 90 deg, measure angle - // between first radius and one corresponding to the middle of the circle. - if ((p1-center).normalized().dot((p2-center).normalized()) < 0.05 // exactly 90 deg might get rejected - || (p1-center).normalized().dot((p3-center).normalized()) < 0.) { - // Add the circle and remember indices into borders. - circles_idxs.emplace_back(start_idx, i); - circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); - //angle_and_vert_num_per_circle.emplace_back(..., ...); - } - } + const auto& [center, radius] = get_center_and_radius(border, start_idx, i, trafo); + // Add the circle and remember indices into borders. + circles_idxs.emplace_back(start_idx, i); + circles.emplace_back(SurfaceFeature(SurfaceFeatureType::Circle, center, plane.normal, std::nullopt, radius)); + circles_lengths.emplace_back(std::accumulate(lengths.begin() + start_idx + 1, lengths.begin() + i + 1, 0.)); circle = false; } } } -/* - // At this point we must merge the first and last circles. The dicrimination of too small - // circles will follow, so we need a complete picture before that. - assert(circles.size() == angle_and_vert_num_per_circle.size()); - for (size_t i=0; i 1 + && circles_idxs.back().second == angles.size()-1 + && circles_idxs.front().first == 0) { + // Possibly the same circle. Check that the angle and length criterion holds along the combined segment. + bool same = true; + double last_len = -1.; + double last_angle = 0.; + for (int i=circles_idxs.back().first + 1; i != circles_idxs.front().second; ++i) { + if (i == angles.size()) + i = 1; + if (last_len == -1.) { + last_len = lengths[i]; + last_angle = angles[i]; + } else { + if (! Slic3r::is_approx(lengths[i], last_len) || ! Slic3r::is_approx(angles[i], last_angle)) { + same = false; + break; + } + } + } + if (same) { + // This seems to really be the same circle. Better apply ransac again. The parts can be small and inexact. + std::vector points(border.begin() + circles_idxs.back().first, border.end()); + points.insert(points.end(), border.begin(), border.begin() + circles_idxs.front().second+1); + auto [c, radius] = get_center_and_radius(points, 0, points.size()-1, trafo); + // Now replace the first circle with the combined one, remove the last circle. + // First index of the first circle is saved negative - we are going to pick edges + // from the border later, we will need to know where the merged in segment was. + // The sign simplifies the algorithm that picks the remaining edges - see below. + circles.front() = SurfaceFeature(SurfaceFeatureType::Circle, c, plane.normal, std::nullopt, radius); + circles_idxs.front().first = - circles_idxs.back().first; + circles_lengths.front() += circles_lengths.back(); + circles.pop_back(); + circles_idxs.pop_back(); + circles_lengths.pop_back(); + } + } - // Some of the "circles" may actually be polygons. We want them detected as - // edges, but also to remember the center and save it into those edges. - // We will add all such edges manually and delete the detected circles, - // leaving it in circles_idxs so they are not picked again: + // Now throw away all circles that subtend less than 90 deg. + assert(circles.size() == circles_lengths.size()); + for (int i=0; i(circles[i].get_circle()); + if (circles_lengths[i] / r < 0.9*M_PI/2.) { + circles_lengths.erase(circles_lengths.begin() + i); + circles.erase(circles.begin() + i); + circles_idxs.erase(circles_idxs.begin() + i); + --i; + } + } + circles_lengths.clear(); // no longer needed, make it obvious + + // Some of the "circles" may actually be polygons (5-8 vertices). We want them + // detected as edges, but also to remember the center and save it into those edges. + // We will add all such edges manually and delete the detected circles, leaving it + // in circles_idxs so they are not picked again. assert(circles.size() == circles_idxs.size()); for (int i=circles.size()-1; i>=0; --i) { - assert(circles_idxs[i].first + 1 < angles.size() - 1); // Check that this is internal point of the circle, not the first, not the last. - double angle = angles[circles_idxs[i].first + 1]; - if (angle > polygon_lower_threshold) { - if (angle < polygon_upper_threshold) { - const Vec3d center = std::get<0>(circles[i].get_circle()); - for (int j=(int)circles_idxs[i].first + 1; j<=(int)circles_idxs[i].second; ++j) - plane.surface_features.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, - border[j - 1], border[j], std::make_optional(center))); - } else { - // This will be handled just like a regular edge. - circles_idxs.erase(circles_idxs.begin() + i); + if (circles_idxs[i].first == 0 && circles_idxs[i].second == border.size()-1) { + int N = circles_idxs[i].second - circles_idxs[i].first; + if (N <= 8) { + if (N >= 5) { // polygon = 5,6,7,8 vertices + const Vec3d center = std::get<0>(circles[i].get_circle()); + for (int j=(int)circles_idxs[i].first + 1; j<=(int)circles_idxs[i].second; ++j) + edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, + border[j - 1], border[j], std::make_optional(center))); + } else { + // This will be handled just like a regular edge (squares, triangles). + circles_idxs.erase(circles_idxs.begin() + i); + } + circles.erase(circles.begin() + i); } - circles.erase(circles.begin() + i); } } - // We have the circles. Now go around again and pick edges. - int cidx = 0; // index of next circle in the way + // Anything under 5 vertices shall not be considered a circle. + assert(circles_idxs.size() == circles.size()); + for (int i=0; i= 0 + ? end - start + (start == 0 && end == border.size()-1 ? 0 : 1) // last point is the same as first + : end + (border.size() + start); + if (N < 5) { + circles.erase(circles.begin() + i); + circles_idxs.erase(circles_idxs.begin() + i); + --i; + } + } + + + // We have the circles. Now go around again and pick edges, while jumping over circles. + // If the first index of the first circle is negative, it means that it was merged + // with a segment that was originally at the back and is no longer there. Ressurect + // its pair of indices so that edges are not picked again. + if (! circles_idxs.empty() && circles_idxs.front().first < 0) + circles_idxs.emplace_back(-circles_idxs.front().first, int(border.size())); + int cidx = 0; // index of next circle to jump over for (int i=1; i (int)circles_idxs[cidx].first) i = circles_idxs[cidx++].second; else - plane.surface_features.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, border[i - 1], border[i])); + edges.emplace_back(SurfaceFeature(SurfaceFeatureType::Edge, border[i - 1], border[i])); } // Merge adjacent edges where needed. - assert(std::all_of(plane.surface_features.begin(), plane.surface_features.end(), + assert(std::all_of(edges.begin(), edges.end(), [](const SurfaceFeature& f) { return f.get_type() == SurfaceFeatureType::Edge; })); - for (int i=plane.surface_features.size()-1; i>=0; --i) { - const auto& [first_start, first_end] = plane.surface_features[i==0 ? plane.surface_features.size()-1 : i-1].get_edge(); - const auto& [second_start, second_end] = plane.surface_features[i].get_edge(); + for (int i=edges.size()-1; i>=0; --i) { + const auto& [first_start, first_end] = edges[i==0 ? edges.size()-1 : i-1].get_edge(); + const auto& [second_start, second_end] = edges[i].get_edge(); if (Slic3r::is_approx(first_end, second_start) && Slic3r::is_approx((first_end-first_start).normalized().dot((second_end-second_start).normalized()), 1.)) { // The edges have the same direction and share a point. Merge them. - plane.surface_features[i==0 ? plane.surface_features.size()-1 : i-1] = SurfaceFeature(SurfaceFeatureType::Edge, first_start, second_end); - plane.surface_features.erase(plane.surface_features.begin() + i); + edges[i==0 ? edges.size()-1 : i-1] = SurfaceFeature(SurfaceFeatureType::Edge, first_start, second_end); + edges.erase(edges.begin() + i); } } - - - // FIXME Throw away / do not create edges which are parts of circles or - // which lead to circle points (unless they belong to the same plane.) - - // Now move the circles into the feature list. + // Now move the circles and edges into the feature list for the plane. assert(std::all_of(circles.begin(), circles.end(), [](const SurfaceFeature& f) { return f.get_type() == SurfaceFeatureType::Circle; })); + assert(std::all_of(edges.begin(), edges.end(), [](const SurfaceFeature& f) { + return f.get_type() == SurfaceFeatureType::Edge; + })); plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()), - std::make_move_iterator(circles.end())); + std::make_move_iterator(circles.end())); + plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(edges.begin()), + std::make_move_iterator(edges.end())); } // The last surface feature is the plane itself. From a0a0b0d25399b4b037e736ae98ec83dfc8969c02 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 7 Nov 2022 09:58:25 +0100 Subject: [PATCH 11/16] Measuring - Keep showing dimensioning after scaling --- src/libslic3r/Measure.hpp | 11 +++++++++++ src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 21 ++++++++++++--------- src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp | 1 + 3 files changed, 24 insertions(+), 9 deletions(-) diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index d1a0e3866..6d6dca14f 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -150,6 +150,17 @@ struct MeasurementResult { bool has_any_data() const { return angle.has_value() || distance_infinite.has_value() || distance_strict.has_value() || distance_xyz.has_value(); } + + void transform(const Transform3d& trafo) { + if (angle.has_value()) + angle->transform(trafo); + if (distance_infinite.has_value()) + distance_infinite->transform(trafo); + if (distance_strict.has_value()) + distance_strict->transform(trafo); + if (distance_xyz.has_value()) + distance_xyz = trafo * *distance_xyz; + } }; // Returns distance/angle between two SurfaceFeatures. diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 858b4e5ce..04e4957d6 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -303,14 +303,7 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) if (m_selected_features != selected_features_old && m_selected_features.second.feature.has_value()) { m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); // transform to world coordinates - if (m_measurement_result.angle.has_value()) - m_measurement_result.angle->transform(m_volume_matrix); - if (m_measurement_result.distance_infinite.has_value()) - m_measurement_result.distance_infinite->transform(m_volume_matrix); - if (m_measurement_result.distance_strict.has_value()) - m_measurement_result.distance_strict->transform(m_volume_matrix); - if (m_measurement_result.distance_xyz.has_value()) - m_measurement_result.distance_xyz = TransformHelper::model_to_world(*m_measurement_result.distance_xyz, m_volume_matrix); + m_measurement_result.transform(m_volume_matrix); } return true; @@ -357,7 +350,14 @@ void GLGizmoMeasure::data_changed() m_last_inv_zoom = 0.0f; m_last_plane_idx = -1; - m_selected_features.reset(); + if (m_pending_scale) { + m_measurement_result = Measure::get_measurement(*m_selected_features.first.feature, *m_selected_features.second.feature, m_measuring.get()); + // transform to world coordinates + m_measurement_result.transform(m_volume_matrix); + m_pending_scale = false; + } + else + m_selected_features.reset(); m_selection_raycasters.clear(); m_editing_distance = false; m_is_editing_distance_first_frame = true; @@ -1007,6 +1007,9 @@ void GLGizmoMeasure::render_dimensioning() selection.scale(ratio * Vec3d::Ones(), type); wxGetApp().plater()->canvas3D()->do_scale(""); // avoid storing another snapshot wxGetApp().obj_manipul()->set_dirty(); + + // update measure on next call to data_changed() + m_pending_scale = true; }; auto action_exit = [this]() { m_editing_distance = false; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp index 7d20ca26a..4426457ff 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.hpp @@ -116,6 +116,7 @@ class GLGizmoMeasure : public GLGizmoBase KeyAutoRepeatFilter m_ctrl_kar_filter; SelectedFeatures m_selected_features; + bool m_pending_scale{ false }; bool m_editing_distance{ false }; bool m_is_editing_distance_first_frame{ true }; From 411535ecdf6d5e91a1f074c1b47755fb332975dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Luk=C3=A1=C5=A1=20Hejl?= Date: Tue, 18 Oct 2022 01:23:47 +0200 Subject: [PATCH 12/16] Fixed undefined behavior (dereferencing std::unique_ptr pointing to nullptr) in the G-Code processing pipeline. --- src/libslic3r/GCode.cpp | 36 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/libslic3r/GCode.cpp b/src/libslic3r/GCode.cpp index e2bd6ef65..798f7759d 100644 --- a/src/libslic3r/GCode.cpp +++ b/src/libslic3r/GCode.cpp @@ -1502,27 +1502,27 @@ void GCode::process_layers( } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&spiral_vase = *this->m_spiral_vase](LayerResult in) -> LayerResult { + [spiral_vase = this->m_spiral_vase.get()](LayerResult in) -> LayerResult { if (in.nop_layer_result) return in; - spiral_vase.enable(in.spiral_vase_enable); - return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush}; + spiral_vase->enable(in.spiral_vase_enable); + return { spiral_vase->process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush}; }); const auto pressure_equalizer = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&pressure_equalizer = *this->m_pressure_equalizer](LayerResult in) -> LayerResult { - return pressure_equalizer.process_layer(std::move(in)); + [pressure_equalizer = this->m_pressure_equalizer.get()](LayerResult in) -> LayerResult { + return pressure_equalizer->process_layer(std::move(in)); }); const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer](LayerResult in) -> std::string { + [cooling_buffer = this->m_cooling_buffer.get()](LayerResult in) -> std::string { if (in.nop_layer_result) return in.gcode; - return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); + return cooling_buffer->process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); const auto find_replace = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&self = *this->m_find_replace](std::string s) -> std::string { - return self.process_layer(std::move(s)); + [find_replace = this->m_find_replace.get()](std::string s) -> std::string { + return find_replace->process_layer(std::move(s)); }); const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [&output_stream](std::string s) { output_stream.write(s); } @@ -1584,25 +1584,25 @@ void GCode::process_layers( } }); const auto spiral_vase = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&spiral_vase = *this->m_spiral_vase](LayerResult in)->LayerResult { + [spiral_vase = this->m_spiral_vase.get()](LayerResult in)->LayerResult { if (in.nop_layer_result) return in; - spiral_vase.enable(in.spiral_vase_enable); - return { spiral_vase.process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush }; + spiral_vase->enable(in.spiral_vase_enable); + return { spiral_vase->process_layer(std::move(in.gcode)), in.layer_id, in.spiral_vase_enable, in.cooling_buffer_flush }; }); const auto pressure_equalizer = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&pressure_equalizer = *this->m_pressure_equalizer](LayerResult in) -> LayerResult { - return pressure_equalizer.process_layer(std::move(in)); + [pressure_equalizer = this->m_pressure_equalizer.get()](LayerResult in) -> LayerResult { + return pressure_equalizer->process_layer(std::move(in)); }); const auto cooling = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&cooling_buffer = *this->m_cooling_buffer](LayerResult in)->std::string { + [cooling_buffer = this->m_cooling_buffer.get()](LayerResult in)->std::string { if (in.nop_layer_result) return in.gcode; - return cooling_buffer.process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); + return cooling_buffer->process_layer(std::move(in.gcode), in.layer_id, in.cooling_buffer_flush); }); const auto find_replace = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, - [&self = *this->m_find_replace](std::string s) -> std::string { - return self.process_layer(std::move(s)); + [find_replace = this->m_find_replace.get()](std::string s) -> std::string { + return find_replace->process_layer(std::move(s)); }); const auto output = tbb::make_filter(slic3r_tbb_filtermode::serial_in_order, [&output_stream](std::string s) { output_stream.write(s); } From 8abb8a654630254d5056cf86a369936db6066c25 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 7 Nov 2022 12:52:10 +0100 Subject: [PATCH 13/16] #8252 - GCodeViewer - Fixed crash when importing invalid gcode --- src/slic3r/GUI/3DBed.cpp | 5 ++++- src/slic3r/GUI/MainFrame.cpp | 2 +- src/slic3r/GUI/Plater.cpp | 24 +++++++++++++++++++++++- src/slic3r/GUI/Plater.hpp | 1 + 4 files changed, 29 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/3DBed.cpp b/src/slic3r/GUI/3DBed.cpp index 4319a28cf..7572d4fc4 100644 --- a/src/slic3r/GUI/3DBed.cpp +++ b/src/slic3r/GUI/3DBed.cpp @@ -223,7 +223,10 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c #if ENABLE_LEGACY_OPENGL_REMOVAL m_contour = ExPolygon(Polygon::new_scale(bed_shape)); - m_polygon = offset(m_contour.contour, (float)m_contour.contour.bounding_box().radius() * 1.7f, jtRound, scale_(0.5)).front(); + const BoundingBox bbox = m_contour.contour.bounding_box(); + if (!bbox.defined) + throw RuntimeError(std::string("Invalid bed shape")); + m_polygon = offset(m_contour.contour, (float)bbox.radius() * 1.7f, jtRound, scale_(0.5)).front(); m_triangles.reset(); m_gridlines.reset(); diff --git a/src/slic3r/GUI/MainFrame.cpp b/src/slic3r/GUI/MainFrame.cpp index 96959f33b..5764b283c 100644 --- a/src/slic3r/GUI/MainFrame.cpp +++ b/src/slic3r/GUI/MainFrame.cpp @@ -538,7 +538,7 @@ void MainFrame::update_layout() case ESettingsLayout::GCodeViewer: { m_main_sizer->Add(m_plater, 1, wxEXPAND); - m_plater->set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, 0.0, {}, {}, true); + m_plater->set_default_bed_shape(); m_plater->get_collapse_toolbar().set_enabled(false); m_plater->collapse_sidebar(true); m_plater->Show(); diff --git a/src/slic3r/GUI/Plater.cpp b/src/slic3r/GUI/Plater.cpp index dd47325b5..ccaf28ec0 100644 --- a/src/slic3r/GUI/Plater.cpp +++ b/src/slic3r/GUI/Plater.cpp @@ -5477,10 +5477,27 @@ void Plater::load_gcode(const wxString& filename) p->gcode_result = std::move(processor.extract_result()); // show results - p->preview->reload_print(false); + try + { + p->preview->reload_print(false); + } + catch (const std::exception&) + { + wxEndBusyCursor(); + p->gcode_result.reset(); + reset_gcode_toolpaths(); + set_default_bed_shape(); + p->preview->reload_print(false); + p->get_current_canvas3D()->render(); + MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), + wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error while loading .gcode file"), wxOK | wxICON_WARNING | wxCENTRE).ShowModal(); + set_project_filename(wxEmptyString); + return; + } p->preview->get_canvas3d()->zoom_to_gcode(); if (p->preview->get_canvas3d()->get_gcode_layers_zs().empty()) { + wxEndBusyCursor(); //wxMessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), MessageDialog(this, _L("The selected file") + ":\n" + filename + "\n" + _L("does not contain valid gcode."), wxString(GCODEVIEWER_APP_NAME) + " - " + _L("Error while loading .gcode file"), wxOK | wxICON_WARNING | wxCENTRE).ShowModal(); @@ -6646,6 +6663,11 @@ void Plater::set_bed_shape(const Pointfs& shape, const double max_print_height, p->set_bed_shape(shape, max_print_height, custom_texture, custom_model, force_as_custom); } +void Plater::set_default_bed_shape() const +{ + set_bed_shape({ { 0.0, 0.0 }, { 200.0, 0.0 }, { 200.0, 200.0 }, { 0.0, 200.0 } }, 0.0, {}, {}, true); +} + void Plater::force_filament_colors_update() { bool update_scheduled = false; diff --git a/src/slic3r/GUI/Plater.hpp b/src/slic3r/GUI/Plater.hpp index 9dc9f6316..ff750d561 100644 --- a/src/slic3r/GUI/Plater.hpp +++ b/src/slic3r/GUI/Plater.hpp @@ -399,6 +399,7 @@ public: void set_bed_shape() const; void set_bed_shape(const Pointfs& shape, const double max_print_height, const std::string& custom_texture, const std::string& custom_model, bool force_as_custom = false) const; + void set_default_bed_shape() const; NotificationManager * get_notification_manager(); const NotificationManager * get_notification_manager() const; From 380c746871803d412a07a5f99c33b0fc5694111b Mon Sep 17 00:00:00 2001 From: YuSanka Date: Mon, 7 Nov 2022 13:47:07 +0100 Subject: [PATCH 14/16] Linux specific issue: Prevent ObjectList's events, when updating the volumes in object. On Linux DeleteVolumeChildren() called the update selection event, what caused the unexpected one by one selection of all volumes in object. --- src/slic3r/GUI/GUI_ObjectList.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/slic3r/GUI/GUI_ObjectList.cpp b/src/slic3r/GUI/GUI_ObjectList.cpp index d6bbbeba1..abb22392b 100644 --- a/src/slic3r/GUI/GUI_ObjectList.cpp +++ b/src/slic3r/GUI/GUI_ObjectList.cpp @@ -2882,6 +2882,9 @@ static bool can_add_volumes_to_object(const ModelObject* object) wxDataViewItemArray ObjectList::add_volumes_to_object_in_list(size_t obj_idx, std::function add_to_selection/* = nullptr*/) { + const bool is_prevent_list_events = m_prevent_list_events; + m_prevent_list_events = true; + wxDataViewItem object_item = m_objects_model->GetItemById(int(obj_idx)); m_objects_model->DeleteVolumeChildren(object_item); @@ -2909,6 +2912,7 @@ wxDataViewItemArray ObjectList::add_volumes_to_object_in_list(size_t obj_idx, st Expand(object_item); } + m_prevent_list_events = is_prevent_list_events; return items; } From 236f97aded731d5100f27b70d8ce42dd2d128915 Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 7 Nov 2022 14:15:36 +0100 Subject: [PATCH 15/16] Gizmo Measure - Fixed loss of selection when panning the view --- src/slic3r/GUI/GLCanvas3D.cpp | 5 +++-- src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp | 4 +++- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index fd4c705c5..a5698f67b 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -3696,7 +3696,7 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) // if right clicking on volume, propagate event through callback (shows context menu) int volume_idx = get_first_hover_volume_idx(); if (!m_volumes.volumes[volume_idx]->is_wipe_tower // no context menu for the wipe tower - && m_gizmos.get_current_type() != GLGizmosManager::SlaSupports) // disable context menu when the gizmo is open + && (m_gizmos.get_current_type() != GLGizmosManager::SlaSupports && m_gizmos.get_current_type() != GLGizmosManager::Measure)) // disable context menu when the gizmo is open { // forces the selection of the volume /* m_selection.add(volume_idx); // #et_FIXME_if_needed @@ -3720,7 +3720,8 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt) if (!m_mouse.dragging) { // do not post the event if the user is panning the scene // or if right click was done over the wipe tower - const bool post_right_click_event = m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower; + const bool post_right_click_event = (m_hover_volume_idxs.empty() || !m_volumes.volumes[get_first_hover_volume_idx()]->is_wipe_tower) && + m_gizmos.get_current_type() != GLGizmosManager::Measure; if (post_right_click_event) post_event(RBtnEvent(EVT_GLCANVAS_RIGHT_CLICK, { logical_pos, m_hover_volume_idxs.empty() })); } diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 04e4957d6..3fa8d8d6f 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -306,6 +306,8 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) m_measurement_result.transform(m_volume_matrix); } + m_imgui->set_requires_extra_frame(); + return true; } @@ -327,7 +329,7 @@ bool GLGizmoMeasure::on_mouse(const wxMouseEvent &mouse_event) else if (mouse_event.RightDown() && mouse_event.CmdDown()) { m_selected_features.reset(); m_selection_raycasters.clear(); - m_imgui->set_requires_extra_frame(); + m_parent.request_extra_frame(); } else if (mouse_event.Leaving()) m_mouse_left_down = false; From 5df27130107b1d70fee09664372afdd2d84e883e Mon Sep 17 00:00:00 2001 From: enricoturri1966 Date: Mon, 7 Nov 2022 14:46:21 +0100 Subject: [PATCH 16/16] Measuring - Fixed transformation of distance_xyz --- src/libslic3r/Measure.cpp | 4 ++-- src/libslic3r/Measure.hpp | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index f15be5bea..fc27f0383 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -723,8 +723,8 @@ MeasurementResult get_measurement(const SurfaceFeature& a, const SurfaceFeature& if (f2.get_type() == SurfaceFeatureType::Point) { Vec3d diff = (f2.get_point() - f1.get_point()); result.distance_strict = std::make_optional(DistAndPoints{diff.norm(), f1.get_point(), f2.get_point()}); - result.distance_xyz = diff; - + result.distance_xyz = diff.cwiseAbs(); + /////////////////////////////////////////////////////////////////////////// } else if (f2.get_type() == SurfaceFeatureType::Edge) { const auto [s,e] = f2.get_edge(); diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index 6d6dca14f..ede8c634e 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -156,10 +156,10 @@ struct MeasurementResult { angle->transform(trafo); if (distance_infinite.has_value()) distance_infinite->transform(trafo); - if (distance_strict.has_value()) + if (distance_strict.has_value()) { distance_strict->transform(trafo); - if (distance_xyz.has_value()) - distance_xyz = trafo * *distance_xyz; + distance_xyz = (distance_strict->to - distance_strict->from).cwiseAbs(); + } } };