From 774c69e3c6179228cde41bbf6c70467ba3cb7472 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Fri, 7 Jul 2017 16:40:23 +0200 Subject: [PATCH] Fix of "Problem with larger brim overlapping " https://github.com/prusa3d/Slic3r/issues/373 --- lib/Slic3r/Print.pm | 56 +++------------------------- xs/src/libslic3r/ExtrusionEntity.hpp | 54 ++++++++++++++++----------- xs/src/libslic3r/Print.cpp | 37 ++++++++++++++++++ xs/src/libslic3r/Print.hpp | 1 + xs/xsp/Print.xsp | 1 + 5 files changed, 76 insertions(+), 73 deletions(-) diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index ea0fee56c..c35d10572 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -228,62 +228,16 @@ sub make_brim { $self->make_skirt; return if $self->step_done(STEP_BRIM); + $self->set_step_started(STEP_BRIM); - # since this method must be idempotent, we clear brim paths *before* # checking whether we need to generate them $self->brim->clear; - - if ($self->config->brim_width == 0) { - $self->set_step_done(STEP_BRIM); - return; + if ($self->config->brim_width > 0) { + $self->status_cb->(88, "Generating brim"); + $self->_make_brim; } - $self->status_cb->(88, "Generating brim"); - - # brim is only printed on first layer and uses perimeter extruder - my $first_layer_height = $self->skirt_first_layer_height; - my $flow = $self->brim_flow; - my $mm3_per_mm = $flow->mm3_per_mm; - - my $grow_distance = $flow->scaled_width / 2; - my @islands = (); # array of polygons - foreach my $obj_idx (0 .. ($self->object_count - 1)) { - my $object = $self->objects->[$obj_idx]; - my $layer0 = $object->get_layer(0); - my @object_islands = ( - (map $_->contour, @{$layer0->slices}), - ); - if (@{ $object->support_layers }) { - my $support_layer0 = $object->support_layers->[0]; - push @object_islands, - (map @{$_->polyline->grow($grow_distance)}, @{$support_layer0->support_fills}) - if $support_layer0->support_fills; - } - foreach my $copy (@{$object->_shifted_copies}) { - push @islands, map { $_->translate(@$copy); $_ } map $_->clone, @object_islands; - } - } - - my @loops = (); - my $num_loops = sprintf "%.0f", $self->config->brim_width / $flow->width; - for my $i (reverse 1 .. $num_loops) { - # JT_SQUARE ensures no vertex is outside the given offset distance - # -0.5 because islands are not represented by their centerlines - # (first offset more, then step back - reverse order than the one used for - # perimeters because here we're offsetting outwards) - push @loops, @{offset2(\@islands, ($i + 0.5) * $flow->scaled_spacing, -1.0 * $flow->scaled_spacing, JT_SQUARE)}; - } - - $self->brim->append(map Slic3r::ExtrusionLoop->new_from_paths( - Slic3r::ExtrusionPath->new( - polyline => Slic3r::Polygon->new(@$_)->split_at_first_point, - role => EXTR_ROLE_SKIRT, - mm3_per_mm => $mm3_per_mm, - width => $flow->width, - height => $first_layer_height, - ), - ), reverse @{union_pt_chained(\@loops)}); - + $self->set_step_done(STEP_BRIM); } diff --git a/xs/src/libslic3r/ExtrusionEntity.hpp b/xs/src/libslic3r/ExtrusionEntity.hpp index 17b0b07f9..699821634 100644 --- a/xs/src/libslic3r/ExtrusionEntity.hpp +++ b/xs/src/libslic3r/ExtrusionEntity.hpp @@ -197,12 +197,12 @@ public: ExtrusionPaths paths; ExtrusionLoop(ExtrusionLoopRole role = elrDefault) : m_loop_role(role) {}; - ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) - : paths(paths), m_loop_role(role) {}; - ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) - : m_loop_role(role) { - this->paths.push_back(path); - }; + ExtrusionLoop(const ExtrusionPaths &paths, ExtrusionLoopRole role = elrDefault) : paths(paths), m_loop_role(role) {}; + ExtrusionLoop(ExtrusionPaths &&paths, ExtrusionLoopRole role = elrDefault) : paths(std::move(paths)), m_loop_role(role) {}; + ExtrusionLoop(const ExtrusionPath &path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role) + { this->paths.push_back(path); }; + ExtrusionLoop(const ExtrusionPath &&path, ExtrusionLoopRole role = elrDefault) : m_loop_role(role) + { this->paths.emplace_back(std::move(path)); }; bool is_loop() const { return true; } bool can_reverse() const { return false; } ExtrusionLoop* clone() const { return new ExtrusionLoop (*this); } @@ -243,49 +243,59 @@ private: inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); - for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { - if (it_polyline->is_valid()) { + for (Polyline &polyline : polylines) + if (polyline.is_valid()) { dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height)); - dst.back().polyline = *it_polyline; + dst.back().polyline = polyline; } - } } inline void extrusion_paths_append(ExtrusionPaths &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); - for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { - if (it_polyline->is_valid()) { + for (Polyline &polyline : polylines) + if (polyline.is_valid()) { dst.push_back(ExtrusionPath(role, mm3_per_mm, width, height)); - dst.back().polyline = std::move(*it_polyline); + dst.back().polyline = std::move(polyline); } - } polylines.clear(); } inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); - for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { - if (it_polyline->is_valid()) { + for (Polyline &polyline : polylines) + if (polyline.is_valid()) { ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height); dst.push_back(extrusion_path); - extrusion_path->polyline = *it_polyline; + extrusion_path->polyline = polyline; } - } } inline void extrusion_entities_append_paths(ExtrusionEntitiesPtr &dst, Polylines &&polylines, ExtrusionRole role, double mm3_per_mm, float width, float height) { dst.reserve(dst.size() + polylines.size()); - for (Polylines::const_iterator it_polyline = polylines.begin(); it_polyline != polylines.end(); ++ it_polyline) { - if (it_polyline->is_valid()) { + for (Polyline &polyline : polylines) + if (polyline.is_valid()) { ExtrusionPath *extrusion_path = new ExtrusionPath(role, mm3_per_mm, width, height); dst.push_back(extrusion_path); - extrusion_path->polyline = std::move(*it_polyline); + extrusion_path->polyline = std::move(polyline); + } + polylines.clear(); +} + +inline void extrusion_entities_append_loops(ExtrusionEntitiesPtr &dst, Polygons &&loops, ExtrusionRole role, double mm3_per_mm, float width, float height) +{ + dst.reserve(dst.size() + loops.size()); + for (Polygon &poly : loops) { + if (poly.is_valid()) { + ExtrusionPath path(role, mm3_per_mm, width, height); + path.polyline.points = std::move(poly.points); + path.polyline.points.push_back(path.polyline.points.front()); + dst.emplace_back(new ExtrusionLoop(std::move(path))); } } - polylines.clear(); + loops.clear(); } } diff --git a/xs/src/libslic3r/Print.cpp b/xs/src/libslic3r/Print.cpp index 45c13b52e..f1631b6d8 100644 --- a/xs/src/libslic3r/Print.cpp +++ b/xs/src/libslic3r/Print.cpp @@ -901,6 +901,43 @@ void Print::_make_skirt() this->skirt.reverse(); } +void Print::_make_brim() +{ + // Brim is only printed on first layer and uses perimeter extruder. + Flow flow = this->brim_flow(); + Polygons islands; + for (PrintObject *object : this->objects) { + Polygons object_islands; + for (ExPolygon &expoly : object->layers.front()->slices.expolygons) + object_islands.push_back(expoly.contour); + if (! object->support_layers.empty()) + object->support_layers.front()->support_fills.polygons_covered_by_spacing(object_islands, float(SCALED_EPSILON)); + islands.reserve(islands.size() + object_islands.size() * object->_shifted_copies.size()); + for (const Point &pt : object->_shifted_copies) + for (Polygon &poly : object_islands) { + islands.push_back(poly); + islands.back().translate(pt); + } + } + Polygons loops; + size_t num_loops = size_t(floor(this->config.brim_width.value / flow.width)); + for (size_t i = 0; i < num_loops; ++ i) { + islands = offset(islands, float(flow.scaled_spacing()), jtSquare); + for (Polygon &poly : islands) { + // poly.simplify(SCALED_RESOLUTION); + poly.points.push_back(poly.points.front()); + Points p = MultiPoint::_douglas_peucker(poly.points, SCALED_RESOLUTION); + p.pop_back(); + poly.points = std::move(p); + } + polygons_append(loops, offset(islands, -0.5f * float(flow.scaled_spacing()))); + } + + loops = union_pt_chained(loops, false); + std::reverse(loops.begin(), loops.end()); + extrusion_entities_append_loops(this->brim.entities, std::move(loops), erSkirt, float(flow.mm3_per_mm()), float(flow.width), float(this->skirt_first_layer_height())); +} + // Wipe tower support. bool Print::has_wipe_tower() { diff --git a/xs/src/libslic3r/Print.hpp b/xs/src/libslic3r/Print.hpp index af4c0e28c..3492a74fd 100644 --- a/xs/src/libslic3r/Print.hpp +++ b/xs/src/libslic3r/Print.hpp @@ -277,6 +277,7 @@ public: void auto_assign_extruders(ModelObject* model_object) const; void _make_skirt(); + void _make_brim(); // Wipe tower support. bool has_wipe_tower(); diff --git a/xs/xsp/Print.xsp b/xs/xsp/Print.xsp index b29b82ba4..9c5bf1e2f 100644 --- a/xs/xsp/Print.xsp +++ b/xs/xsp/Print.xsp @@ -230,6 +230,7 @@ _constant() Clone skirt_flow(); void _make_skirt(); + void _make_brim(); bool has_wipe_tower(); void _clear_wipe_tower();