diff --git a/src/libslic3r/Measure.cpp b/src/libslic3r/Measure.cpp index 724f4ab80..056178bc4 100644 --- a/src/libslic3r/Measure.cpp +++ b/src/libslic3r/Measure.cpp @@ -192,10 +192,11 @@ void MeasuringImpl::update_planes() void MeasuringImpl::extract_features() { - - - const double edge_threshold = 25. * (M_PI/180.); + 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; for (int i=0; i M_PI) + angle = 2*M_PI - angle; + angles.push_back(angle); + lengths.push_back(v2.squaredNorm()); } assert(border.size() == angles.size()); + assert(border.size() == lengths.size()); bool circle = false; - std::vector> circles; + std::vector> circles; + std::vector> circles_idxs; for (int i=1; i( + new Circle(center, radius, plane.normal))); circle = false; } } } + // 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: + 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 = static_cast(circles[i].get())->get_center(); + for (int j=circles_idxs[i].first + 1; j<=circles_idxs[i].second; ++j) + plane.surface_features.emplace_back(std::unique_ptr( + new Edge(border[j-1], border[j], center))); + } else { + // This will be handled just like a regular edge. + circles_idxs.erase(circles_idxs.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 for (int i=1; i circles[cidx].first) - i = circles[cidx++].second; + if (cidx < circles_idxs.size() && i > circles_idxs[cidx].first) + i = circles_idxs[cidx++].second; else plane.surface_features.emplace_back(std::unique_ptr( new Edge(border[i-1], border[i]))); } @@ -258,13 +297,10 @@ void MeasuringImpl::extract_features() // FIXME Check and merge first and last circle if needed. - // Now create the circle-typed surface features. - for (const auto& [start_idx, end_idx] : circles) { - std::pair center_and_radius = get_center_and_radius(border, start_idx, end_idx, trafo); - plane.surface_features.emplace_back(std::unique_ptr( - new Circle(center_and_radius.first, center_and_radius.second, plane.normal))); - } - + // Now move the circles into the feature list. + assert(std::all_of(circles.begin(), circles.end(), [](const std::unique_ptr& f) { return f->get_type() == SurfaceFeatureType::Circle; })); + plane.surface_features.insert(plane.surface_features.end(), std::make_move_iterator(circles.begin()), + std::make_move_iterator(circles.end())); } // The last surface feature is the plane itself. diff --git a/src/libslic3r/Measure.hpp b/src/libslic3r/Measure.hpp index 0455291bf..1db35d9fc 100644 --- a/src/libslic3r/Measure.hpp +++ b/src/libslic3r/Measure.hpp @@ -32,6 +32,7 @@ public: m_pin{std::unique_ptr(new Vec3d(pin))} {} SurfaceFeatureType get_type() const override { return SurfaceFeatureType::Edge; } std::pair get_edge() const { return std::make_pair(m_start, m_end); } + const Vec3d* get_point_of_interest() const { return m_pin.get(); } private: Vec3d m_start; Vec3d m_end; diff --git a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp index 44dd44cc5..186998301 100644 --- a/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp +++ b/src/slic3r/GUI/Gizmos/GLGizmoMeasure.cpp @@ -207,6 +207,14 @@ void GLGizmoMeasure::on_render() shader->set_uniform("view_model_matrix", view_feature_matrix); m_vbo_cylinder.set_color(ColorRGBA(0.8f, 0.2f, 0.2f, 1.f)); m_vbo_cylinder.render(); + if (edge->get_point_of_interest()) { + Vec3d pin = *edge->get_point_of_interest(); + view_feature_matrix = view_model_matrix * Transform3d(Eigen::Translation3d(pin)); + view_feature_matrix.scale(0.5); + shader->set_uniform("view_model_matrix", view_feature_matrix); + m_vbo_sphere.set_color(ColorRGBA(0.8f, 0.2f, 0.2f, 1.f)); + m_vbo_sphere.render(); + } } else if (feature->get_type() == Measure::SurfaceFeatureType::Plane) { const auto* plane = static_cast(feature);