diff --git a/src/libslic3r/GCode/SeamGeometry.cpp b/src/libslic3r/GCode/SeamGeometry.cpp index 054f5c03a4..f622d32e00 100644 --- a/src/libslic3r/GCode/SeamGeometry.cpp +++ b/src/libslic3r/GCode/SeamGeometry.cpp @@ -218,7 +218,7 @@ BoundedPolygons project_to_geometry(const Geometry::Extrusions &external_perimet Polygons expanded_extrusion{expand(external_perimeter.polygon, 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..fd3c07bf77 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 == spAligned ? + Geometry::project_to_geometry(extrusions, params.max_distance) : + Geometry::convert_to_geometry(extrusions) + }; Perimeters::LayerPerimeters perimeters{Perimeters::create_perimeters(projected, layer_infos, painting, params.perimeter)}; throw_if_canceled();