diff --git a/src/libslic3r/GCode/SeamGeometry.cpp b/src/libslic3r/GCode/SeamGeometry.cpp index 054f5c03a4..fbc4d07d93 100644 --- a/src/libslic3r/GCode/SeamGeometry.cpp +++ b/src/libslic3r/GCode/SeamGeometry.cpp @@ -215,10 +215,10 @@ BoundedPolygons project_to_geometry(const Geometry::Extrusions &external_perimet )}; if (distance > max_bb_distance) { - Polygons expanded_extrusion{expand(external_perimeter.polygon, external_perimeter.width / 2.0)}; + Polygons expanded_extrusion{expand(external_perimeter.polygon, Slic3r::scaled(external_perimeter.width / 2.0))}; if (!expanded_extrusion.empty()) { return BoundedPolygon{ - expanded_extrusion.front(), expanded_extrusion.front().bounding_box(), external_perimeter.polygon.is_clockwise() + expanded_extrusion.front(), expanded_extrusion.front().bounding_box(), external_perimeter.polygon.is_clockwise(), 0.0 }; } } @@ -227,7 +227,7 @@ BoundedPolygons project_to_geometry(const Geometry::Extrusions &external_perimet const Polygon &adjacent_boundary{ !is_hole ? external_perimeter.island_boundary.contour : external_perimeter.island_boundary.holes[choosen_index - 1]}; - return BoundedPolygon{adjacent_boundary, external_perimeter.island_boundary_bounding_boxes[choosen_index], is_hole}; + return BoundedPolygon{adjacent_boundary, external_perimeter.island_boundary_bounding_boxes[choosen_index], is_hole, 0.0}; } ); return result; @@ -243,6 +243,27 @@ std::vector project_to_geometry(const std::vector convert_to_geometry(const std::vector &extrusions) { + std::vector result; + result.reserve(extrusions.size()); + + for (const Geometry::Extrusions &layer : extrusions) { + result.emplace_back(); + + using std::transform, std::back_inserter; + transform( + layer.begin(), layer.end(), back_inserter(result.back()), + [&](const Geometry::Extrusion &extrusion) { + return BoundedPolygon{ + extrusion.polygon, extrusion.bounding_box, extrusion.polygon.is_clockwise(), extrusion.width / 2.0 + }; + } + ); + } + + return result; +} + std::vector oversample_edge(const Vec2d &from, const Vec2d &to, const double max_distance) { const double total_distance{(from - to).norm()}; const auto points_count{static_cast(std::ceil(total_distance / max_distance)) + 1}; diff --git a/src/libslic3r/GCode/SeamGeometry.hpp b/src/libslic3r/GCode/SeamGeometry.hpp index 9b4849a3a2..c861e3d40d 100644 --- a/src/libslic3r/GCode/SeamGeometry.hpp +++ b/src/libslic3r/GCode/SeamGeometry.hpp @@ -61,12 +61,14 @@ struct BoundedPolygon { Polygon polygon; BoundingBox bounding_box; bool is_hole{false}; + double offset_inside{}; }; using BoundedPolygons = std::vector; BoundedPolygons project_to_geometry(const Geometry::Extrusions &external_perimeters, const double max_bb_distance); std::vector project_to_geometry(const std::vector &extrusions, const double max_bb_distance); +std::vector convert_to_geometry(const std::vector &extrusions); Vec2d get_polygon_normal( const std::vector &points, const std::size_t index, const double min_arm_length diff --git a/src/libslic3r/GCode/SeamPerimeters.cpp b/src/libslic3r/GCode/SeamPerimeters.cpp index 9241c98867..78d7c246c9 100644 --- a/src/libslic3r/GCode/SeamPerimeters.cpp +++ b/src/libslic3r/GCode/SeamPerimeters.cpp @@ -326,7 +326,8 @@ Perimeter Perimeter::create( const Polygon &polygon, const ModelInfo::Painting &painting, const LayerInfo &layer_info, - const PerimeterParams ¶ms + const PerimeterParams ¶ms, + const double offset_inside ) { if (polygon.size() < 3) { return Perimeter::create_degenerate( @@ -353,10 +354,17 @@ Perimeter Perimeter::create( Impl::oversample_painted(points, is_painted, layer_info.slice_z, params.oversampling_max_distance)}; std::vector point_types{ - Impl::get_point_types(perimeter_points, painting, layer_info.slice_z, params.painting_radius)}; + Impl::get_point_types(perimeter_points, painting, layer_info.slice_z, offset_inside > 0 ? offset_inside * 2 : params.painting_radius)}; - std::tie(perimeter_points, point_types) = - Impl::remove_redundant_points(perimeter_points, point_types, params.simplification_epsilon); + // Geometry converted from extrusions has non zero offset_inside. + // Do not remomve redundant points for extrusions, becouse the redundant + // points can be on overhangs. + if (offset_inside < std::numeric_limits::epsilon()) { + // The following is optimization with significant impact. If in doubt, run + // the "Seam benchmarks" test case in fff_print_tests. + std::tie(perimeter_points, point_types) = + Impl::remove_redundant_points(perimeter_points, point_types, params.simplification_epsilon); + } const std::vector embeddings{ Geometry::get_embedding_distances(perimeter_points, layer_info.distancer)}; @@ -411,7 +419,7 @@ LayerPerimeters create_perimeters( const Geometry::BoundedPolygon &bounded_polygon{layer[polygon_index]}; const LayerInfo &layer_info{layer_infos[layer_index]}; result[layer_index][polygon_index] = BoundedPerimeter{ - Perimeter::create(bounded_polygon.polygon, painting, layer_info, params), + Perimeter::create(bounded_polygon.polygon, painting, layer_info, params, bounded_polygon.offset_inside), bounded_polygon.bounding_box}; } ); diff --git a/src/libslic3r/GCode/SeamPerimeters.hpp b/src/libslic3r/GCode/SeamPerimeters.hpp index 2dcee2ddc9..54660f6ddb 100644 --- a/src/libslic3r/GCode/SeamPerimeters.hpp +++ b/src/libslic3r/GCode/SeamPerimeters.hpp @@ -151,7 +151,8 @@ struct Perimeter const Polygon &polygon, const ModelInfo::Painting &painting, const LayerInfo &layer_info, - const PerimeterParams ¶ms + const PerimeterParams ¶ms, + const double offset_inside ); static Perimeter create_degenerate( diff --git a/src/libslic3r/GCode/SeamPlacer.cpp b/src/libslic3r/GCode/SeamPlacer.cpp index 950a99d7e9..8517732624 100644 --- a/src/libslic3r/GCode/SeamPlacer.cpp +++ b/src/libslic3r/GCode/SeamPlacer.cpp @@ -38,7 +38,11 @@ ObjectLayerPerimeters get_perimeters( const Perimeters::LayerInfos layer_infos{Perimeters::get_layer_infos( print_object->layers(), params.perimeter.elephant_foot_compensation )}; - const std::vector projected{Geometry::project_to_geometry(extrusions, params.max_distance)}; + const std::vector projected{ + print_object->config().seam_position == spRandom ? + Geometry::convert_to_geometry(extrusions) : + Geometry::project_to_geometry(extrusions, params.max_distance) + }; Perimeters::LayerPerimeters perimeters{Perimeters::create_perimeters(projected, layer_infos, painting, params.perimeter)}; throw_if_canceled(); diff --git a/tests/fff_print/test_seam_shells.cpp b/tests/fff_print/test_seam_shells.cpp index 56bd273780..852b17cbe4 100644 --- a/tests/fff_print/test_seam_shells.cpp +++ b/tests/fff_print/test_seam_shells.cpp @@ -52,7 +52,7 @@ TEST_CASE_METHOD(ProjectionFixture, "Project to geometry does not match", "[Seam REQUIRE(result.size() == 1); REQUIRE(result[0].polygon.size() == 4); - const Polygon expanded{expand(extrusions.front().polygon, extrusion_width / 2.0).front()}; + const Polygon expanded{expand(extrusions.front().polygon, scaled(extrusion_width / 2.0)).front()}; // The extrusion is expanded and returned. CHECK(result[0].polygon == expanded);