Merge branch 'master' into wipe
This commit is contained in:
commit
d2b451d9a1
13 changed files with 110 additions and 76 deletions
|
@ -85,15 +85,7 @@ sub offset_ex {
|
|||
|
||||
sub safety_offset {
|
||||
my $self = shift;
|
||||
|
||||
# we're offsetting contour and holes separately
|
||||
# because Clipper doesn't return polygons in the same order as
|
||||
# we feed them to it
|
||||
|
||||
return (ref $self)->new(
|
||||
$self->contour->safety_offset,
|
||||
@{ Slic3r::Geometry::Clipper::safety_offset([$self->holes]) },
|
||||
);
|
||||
return Slic3r::Geometry::Clipper::safety_offset_ex($self, @_);
|
||||
}
|
||||
|
||||
sub noncollapsing_offset_ex {
|
||||
|
|
|
@ -13,7 +13,7 @@ has '_crossing_edges' => (is => 'rw', default => sub { {} }); # edge_idx => boo
|
|||
|
||||
use List::Util qw(first);
|
||||
use Slic3r::Geometry qw(A B scale epsilon nearest_point);
|
||||
use Slic3r::Geometry::Clipper qw(diff_ex JT_MITER);
|
||||
use Slic3r::Geometry::Clipper qw(diff_ex offset JT_MITER);
|
||||
|
||||
# clearance (in mm) from the perimeters
|
||||
has '_inner_margin' => (is => 'ro', default => sub { scale 0.5 });
|
||||
|
@ -68,7 +68,8 @@ sub BUILD {
|
|||
: [ $self->islands->[$i]->offset_ex(-$self->_inner_margin) ];
|
||||
|
||||
# offset the island outwards to make the boundaries for external movements
|
||||
$self->_outer->[$i] = [ $self->islands->[$i]->contour->offset($self->_outer_margin) ];
|
||||
$self->_outer->[$i] = [ offset([ $self->islands->[$i]->contour], $self->_outer_margin) ];
|
||||
bless $_, 'Slic3r::Polygon' for @{ $self->_outer->[$i] };
|
||||
|
||||
# if internal motion is enabled, build a set of utility expolygons representing
|
||||
# the outer boundaries (as contours) and the inner boundaries (as holes). whenever
|
||||
|
@ -168,11 +169,17 @@ sub BUILD {
|
|||
lines => \@lines,
|
||||
points => [ values %{$self->_pointmap} ],
|
||||
no_arrows => 1,
|
||||
polygons => [ map @$_, @{$self->islands} ],
|
||||
expolygons => $self->islands,
|
||||
#red_polygons => [ map $_->holes, map @$_, @{$self->_inner} ],
|
||||
#white_polygons => [ map @$_, @{$self->_outer} ],
|
||||
);
|
||||
printf "%d islands\n", scalar @{$self->islands};
|
||||
|
||||
eval "use Devel::Size";
|
||||
print "MEMORY USAGE:\n";
|
||||
printf " %-19s = %.1fMb\n", $_, Devel::Size::total_size($self->$_)/1024/1024
|
||||
for qw(_inner _outer _contours_ex _pointmap _edges _crossing_edges islands last_crossings);
|
||||
printf " %-19s = %.1fMb\n", 'self', Devel::Size::total_size($self)/1024/1024;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@ use File::Basename qw(basename dirname);
|
|||
use List::Util qw(max sum first);
|
||||
use Math::ConvexHull::MonotoneChain qw(convex_hull);
|
||||
use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX);
|
||||
use Slic3r::Geometry::Clipper qw(JT_ROUND);
|
||||
use Slic3r::Geometry::Clipper qw(offset JT_ROUND);
|
||||
use threads::shared qw(shared_clone);
|
||||
use Wx qw(:bitmap :brush :button :cursor :dialog :filedialog :font :keycode :icon :id :listctrl :misc :panel :pen :sizer :toolbar :window);
|
||||
use Wx::Event qw(EVT_BUTTON EVT_COMMAND EVT_KEY_DOWN EVT_LIST_ITEM_ACTIVATED EVT_LIST_ITEM_DESELECTED EVT_LIST_ITEM_SELECTED EVT_MOUSE_EVENTS EVT_PAINT EVT_TOOL EVT_CHOICE);
|
||||
|
@ -881,7 +881,7 @@ sub repaint {
|
|||
# if sequential printing is enabled and we have more than one object
|
||||
if ($parent->{config}->complete_objects && (map @{$_->instances}, @{$parent->{objects}}) > 1) {
|
||||
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, @{$parent->{object_previews}->[-1][2]->expolygons} ]));
|
||||
my $clearance = +($convex_hull->offset($parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND))[0];
|
||||
my ($clearance) = offset([$convex_hull], $parent->{config}->extruder_clearance_radius / 2 * $parent->{scaling_factor}, 1, JT_ROUND);
|
||||
$dc->SetPen($parent->{clearance_pen});
|
||||
$dc->SetBrush($parent->{transparent_brush});
|
||||
$dc->DrawPolygon($parent->_y($clearance), 0, 0);
|
||||
|
@ -892,7 +892,7 @@ sub repaint {
|
|||
# draw skirt
|
||||
if (@{$parent->{object_previews}} && $parent->{config}->skirts) {
|
||||
my $convex_hull = Slic3r::Polygon->new(convex_hull([ map @{$_->contour}, map @{$_->[2]->expolygons}, @{$parent->{object_previews}} ]));
|
||||
$convex_hull = +($convex_hull->offset($parent->{config}->skirt_distance * $parent->{scaling_factor}, 1, JT_ROUND))[0];
|
||||
($convex_hull) = offset([$convex_hull], $parent->{config}->skirt_distance * $parent->{scaling_factor}, 1, JT_ROUND);
|
||||
$dc->SetPen($parent->{skirt_pen});
|
||||
$dc->SetBrush($parent->{transparent_brush});
|
||||
$dc->DrawPolygon($parent->_y($convex_hull), 0, 0) if $convex_hull;
|
||||
|
@ -1052,8 +1052,8 @@ sub OnDropFiles {
|
|||
# https://rt.perl.org/rt3/Public/Bug/Display.html?id=70602
|
||||
@_ = ();
|
||||
|
||||
# only accept STL and AMF files
|
||||
return 0 if grep !/\.(?:stl|amf(?:\.xml)?)$/i, @$filenames;
|
||||
# only accept STL, OBJ and AMF files
|
||||
return 0 if grep !/\.(?:stl|obj|amf(?:\.xml)?)$/i, @$filenames;
|
||||
|
||||
$self->{window}->load_file($_) for @$filenames;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ sub new {
|
|||
my $sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||
|
||||
{
|
||||
my $label = Wx::StaticText->new($self, -1, "You can use this section to override the default layer height for parts of this object.",
|
||||
my $label = Wx::StaticText->new($self, -1, "You can use this section to override the default layer height for parts of this object. Set layer height to zero to skip portions of the input file.",
|
||||
wxDefaultPosition, [-1, 25]);
|
||||
$label->SetFont(Wx::SystemSettings::GetFont(wxSYS_DEFAULT_GUI_FONT));
|
||||
$sizer->Add($label, 0, wxEXPAND | wxALL, 10);
|
||||
|
@ -162,7 +162,7 @@ sub CanClose {
|
|||
Slic3r::GUI::show_error($self, "Invalid Z range $min-$max.");
|
||||
return 0;
|
||||
}
|
||||
if ($height <= 0) {
|
||||
if ($height < 0) {
|
||||
Slic3r::GUI::show_error($self, "Invalid layer height $height.");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -172,11 +172,6 @@ sub build {
|
|||
},
|
||||
],
|
||||
);
|
||||
|
||||
$self->append_optgroup(
|
||||
title => 'Cooling',
|
||||
options => [qw(cooling)],
|
||||
);
|
||||
}
|
||||
|
||||
package Slic3r::GUI::SimpleTab::Printer;
|
||||
|
|
|
@ -14,6 +14,7 @@ our $last_output_file;
|
|||
our $last_config;
|
||||
|
||||
use constant FILE_WILDCARDS => {
|
||||
known => 'Known files (*.stl, *.obj, *.amf, *.xml)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML',
|
||||
stl => 'STL files (*.stl)|*.stl;*.STL',
|
||||
obj => 'OBJ files (*.obj)|*.obj;*.OBJ',
|
||||
amf => 'AMF files (*.amf)|*.amf;*.AMF;*.xml;*.XML',
|
||||
|
@ -21,7 +22,7 @@ use constant FILE_WILDCARDS => {
|
|||
gcode => 'G-code files (*.gcode, *.gco, *.g)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G',
|
||||
svg => 'SVG files *.svg|*.svg;*.SVG',
|
||||
};
|
||||
use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(stl obj amf)};
|
||||
use constant MODEL_WILDCARD => join '|', @{&FILE_WILDCARDS}{qw(known stl obj amf)};
|
||||
|
||||
sub new {
|
||||
my $class = shift;
|
||||
|
|
|
@ -4,7 +4,7 @@ use warnings;
|
|||
|
||||
require Exporter;
|
||||
our @ISA = qw(Exporter);
|
||||
our @EXPORT_OK = qw(safety_offset offset offset_ex collapse_ex
|
||||
our @EXPORT_OK = qw(safety_offset safety_offset_ex offset offset_ex collapse_ex
|
||||
diff_ex diff union_ex intersection_ex xor_ex PFT_EVENODD JT_MITER JT_ROUND
|
||||
JT_SQUARE is_counter_clockwise);
|
||||
|
||||
|
@ -17,6 +17,11 @@ sub safety_offset {
|
|||
return Math::Clipper::offset($polygons, $factor // (scale 1e-05), 100000, JT_MITER, 2);
|
||||
}
|
||||
|
||||
sub safety_offset_ex {
|
||||
# offset polygons and then apply holes to the right contours
|
||||
return @{ union_ex([ safety_offset(@_) ]) };
|
||||
}
|
||||
|
||||
sub offset {
|
||||
my ($polygons, $distance, $scale, $joinType, $miterLimit) = @_;
|
||||
$scale ||= 100000;
|
||||
|
|
|
@ -290,7 +290,7 @@ sub make_perimeters {
|
|||
)};
|
||||
|
||||
my $w = $self->perimeter_flow->width;
|
||||
my @widths = (1.5 * $w, $w, 0.5 * $w); # worth trying 0.2 too?
|
||||
my @widths = (1.5 * $w, $w, 0.4 * $w); # worth trying 0.2 too?
|
||||
foreach my $width (@widths) {
|
||||
my $flow = $self->perimeter_flow->clone(width => $width);
|
||||
|
||||
|
@ -462,7 +462,7 @@ sub prepare_fill_surfaces {
|
|||
}
|
||||
|
||||
# turn too small internal regions into solid regions according to the user setting
|
||||
{
|
||||
if ($Slic3r::Config->fill_density > 0) {
|
||||
my $min_area = scale scale $Slic3r::Config->solid_infill_below_area; # scaling an area requires two calls!
|
||||
my @small = grep $_->surface_type == S_TYPE_INTERNAL && $_->expolygon->contour->area <= $min_area, @{$self->fill_surfaces};
|
||||
$_->surface_type(S_TYPE_INTERNALSOLID) for @small;
|
||||
|
|
|
@ -95,16 +95,6 @@ sub area {
|
|||
return Slic3r::Geometry::Clipper::area($self);
|
||||
}
|
||||
|
||||
sub safety_offset {
|
||||
my $self = shift;
|
||||
return (ref $self)->new(Slic3r::Geometry::Clipper::safety_offset([$self])->[0]);
|
||||
}
|
||||
|
||||
sub offset {
|
||||
my $self = shift;
|
||||
return map Slic3r::Polygon->new($_), Slic3r::Geometry::Clipper::offset([$self], @_);
|
||||
}
|
||||
|
||||
sub grow {
|
||||
my $self = shift;
|
||||
return $self->split_at_first_point->grow(@_);
|
||||
|
@ -152,7 +142,7 @@ sub is_printable {
|
|||
# detect them and we would be discarding them.
|
||||
my $p = $self->clone;
|
||||
$p->make_counter_clockwise;
|
||||
return $p->offset(-$width / 2) ? 1 : 0;
|
||||
return Slic3r::Geometry::Clipper::offset([$p], -$width / 2) ? 1 : 0;
|
||||
}
|
||||
|
||||
sub is_valid {
|
||||
|
|
|
@ -86,7 +86,10 @@ sub length {
|
|||
|
||||
sub grow {
|
||||
my $self = shift;
|
||||
return Slic3r::Polygon->new(@$self, CORE::reverse @$self[1..($#$self-1)])->offset(@_);
|
||||
return Slic3r::Geometry::Clipper::offset(
|
||||
[ Slic3r::Polygon->new(@$self, CORE::reverse @$self[1..($#$self-1)]) ],
|
||||
@_,
|
||||
);
|
||||
}
|
||||
|
||||
sub nearest_point_to {
|
||||
|
|
|
@ -151,7 +151,7 @@ sub validate {
|
|||
{
|
||||
my @points = map [ @$_[X,Y] ], map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes};
|
||||
my $convex_hull = Slic3r::Polygon->new(convex_hull(\@points));
|
||||
$clearance = +($convex_hull->offset(scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND))[0];
|
||||
($clearance) = offset([$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND);
|
||||
}
|
||||
for my $copy (@{$self->objects->[$obj_idx]->copies}) {
|
||||
my $copy_clearance = $clearance->clone;
|
||||
|
@ -693,7 +693,7 @@ sub write_gcode {
|
|||
print $fh "; $_\n" foreach split /\R/, $Slic3r::Config->notes;
|
||||
print $fh "\n" if $Slic3r::Config->notes;
|
||||
|
||||
for (qw(layer_height perimeters top_solid_layers bottom_solid_layers fill_density perimeter_speed infill_speed travel_speed scale)) {
|
||||
for (qw(layer_height perimeters top_solid_layers bottom_solid_layers fill_density perimeter_speed infill_speed travel_speed)) {
|
||||
printf $fh "; %s = %s\n", $_, $Slic3r::Config->$_;
|
||||
}
|
||||
for (qw(nozzle_diameter filament_diameter extrusion_multiplier)) {
|
||||
|
@ -881,24 +881,24 @@ sub write_gcode {
|
|||
if ($Slic3r::Config->avoid_crossing_perimeters) {
|
||||
push @islands, map +{ perimeters => [], fills => [] }, @{$layer->slices};
|
||||
PERIMETER: foreach my $perimeter (@{$layerm->perimeters}) {
|
||||
$perimeter = $perimeter->unpack;
|
||||
my $p = $perimeter->unpack;
|
||||
for my $i (0 .. $#{$layer->slices}-1) {
|
||||
if ($layer->slices->[$i]->contour->encloses_point($perimeter->first_point)) {
|
||||
push @{ $islands[$i]{perimeters} }, $perimeter;
|
||||
if ($layer->slices->[$i]->contour->encloses_point($p->first_point)) {
|
||||
push @{ $islands[$i]{perimeters} }, $p;
|
||||
next PERIMETER;
|
||||
}
|
||||
}
|
||||
push @{ $islands[-1]{perimeters} }, $perimeter; # optimization
|
||||
push @{ $islands[-1]{perimeters} }, $p; # optimization
|
||||
}
|
||||
FILL: foreach my $fill (@{$layerm->fills}) {
|
||||
my $f = $fill->unpack;
|
||||
for my $i (0 .. $#{$layer->slices}-1) {
|
||||
$fill = $fill->unpack;
|
||||
if ($layer->slices->[$i]->contour->encloses_point($fill->first_point)) {
|
||||
push @{ $islands[$i]{fills} }, $fill;
|
||||
if ($layer->slices->[$i]->contour->encloses_point($f->first_point)) {
|
||||
push @{ $islands[$i]{fills} }, $f;
|
||||
next FILL;
|
||||
}
|
||||
}
|
||||
push @{ $islands[-1]{fills} }, $fill; # optimization
|
||||
push @{ $islands[-1]{fills} }, $f; # optimization
|
||||
}
|
||||
} else {
|
||||
push @islands, {
|
||||
|
@ -927,9 +927,10 @@ sub write_gcode {
|
|||
}
|
||||
};
|
||||
|
||||
# give priority to infill if we were already using its extruder
|
||||
# give priority to infill if we were already using its extruder and it wouldn't
|
||||
# be good for perimeters
|
||||
if ($Slic3r::Config->infill_first
|
||||
|| ($gcodegen->multiple_extruders && $region->extruders->{infill} eq $gcodegen->extruder)) {
|
||||
|| ($gcodegen->multiple_extruders && $region->extruders->{infill} eq $gcodegen->extruder) && $region->extruders->{infill} ne $region->extruders->{perimeter}) {
|
||||
$extrude_fills->();
|
||||
$extrude_perimeters->();
|
||||
} else {
|
||||
|
|
|
@ -18,26 +18,50 @@ has 'layer_height_ranges' => (is => 'rw', default => sub { [] }); # [ z_min, z_m
|
|||
sub BUILD {
|
||||
my $self = shift;
|
||||
|
||||
# make layers
|
||||
my $print_z = my $slice_z = my $raft_z = 0;
|
||||
while (!@{$self->layers} || $self->layers->[-1]->slice_z < $self->size->[Z]) {
|
||||
my $id = $#{$self->layers} + 1;
|
||||
my $height = $Slic3r::Config->layer_height;
|
||||
$height = $Slic3r::Config->get_value('first_layer_height') if $id == 0;
|
||||
if (my $range = first { $_->[0] <= ($print_z + $_->[2]) && $_->[1] >= ($print_z + $_->[2]) } @{$self->layer_height_ranges}) {
|
||||
$height = $range->[2];
|
||||
}
|
||||
# make layers taking custom heights into account
|
||||
my $print_z = my $slice_z = my $height = 0;
|
||||
|
||||
# add raft layers
|
||||
for my $id (0 .. $Slic3r::Config->raft_layers-1) {
|
||||
$height = ($id == 0)
|
||||
? $Slic3r::Config->get_value('first_layer_height')
|
||||
: $Slic3r::Config->layer_height;
|
||||
|
||||
$print_z += $height;
|
||||
|
||||
if ($id < $Slic3r::Config->raft_layers) {
|
||||
# this is a raft layer
|
||||
$raft_z += $height;
|
||||
$slice_z = -1;
|
||||
} else {
|
||||
$slice_z = $print_z - ($height/2) - $raft_z;
|
||||
push @{$self->layers}, Slic3r::Layer->new(
|
||||
object => $self,
|
||||
id => $id,
|
||||
height => $height,
|
||||
print_z => scale $print_z,
|
||||
slice_z => -1,
|
||||
);
|
||||
}
|
||||
|
||||
# loop until we have at least one layer and the max slice_z reaches the object height
|
||||
my $max_z = unscale $self->size->[Z];
|
||||
while (!@{$self->layers} || ($slice_z - $height) <= $max_z) {
|
||||
my $id = $#{$self->layers} + 1;
|
||||
|
||||
# assign the default height to the layer according to the general settings
|
||||
$height = ($id == 0)
|
||||
? $Slic3r::Config->get_value('first_layer_height')
|
||||
: $Slic3r::Config->layer_height;
|
||||
|
||||
# look for an applicable custom range
|
||||
if (my $range = first { $_->[0] <= $slice_z && $_->[1] > $slice_z } @{$self->layer_height_ranges}) {
|
||||
$height = $range->[2];
|
||||
|
||||
# if user set custom height to zero we should just skip the range and resume slicing over it
|
||||
if ($height == 0) {
|
||||
$slice_z += $range->[1] - $range->[0];
|
||||
next;
|
||||
}
|
||||
}
|
||||
|
||||
$print_z += $height;
|
||||
$slice_z += $height/2;
|
||||
|
||||
### Slic3r::debugf "Layer %d: height = %s; slice_z = %s; print_z = %s\n", $id, $height, $slice_z, $print_z;
|
||||
|
||||
push @{$self->layers}, Slic3r::Layer->new(
|
||||
|
@ -47,6 +71,8 @@ sub BUILD {
|
|||
print_z => scale $print_z,
|
||||
slice_z => scale $slice_z,
|
||||
);
|
||||
|
||||
$slice_z += $height/2; # add the other half layer
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,9 +157,8 @@ sub slice {
|
|||
# free memory
|
||||
$self->meshes(undef);
|
||||
|
||||
# remove last layer if empty
|
||||
# (we might have created it because of the $max_layer = ... + 1 code in TriangleMesh)
|
||||
pop @{$self->layers} if !map @{$_->lines}, @{$self->layers->[-1]->regions};
|
||||
# remove last layer(s) if empty
|
||||
pop @{$self->layers} while !map @{$_->lines}, @{$self->layers->[-1]->regions};
|
||||
|
||||
foreach my $layer (@{ $self->layers }) {
|
||||
# make sure all layers contain layer region objects for all regions
|
||||
|
@ -806,8 +831,7 @@ sub generate_support_material {
|
|||
[ map @$_, @current_layer_offsetted_slices ],
|
||||
);
|
||||
$layers_contact_areas{$i} = [
|
||||
map $_->simplify($flow->scaled_spacing),
|
||||
@{collapse_ex([ map @$_, @{$layers_contact_areas{$i}} ], $flow->scaled_width)},
|
||||
@{collapse_ex([ map @$_, @{$layers_contact_areas{$i}} ], $flow->scaled_width)},
|
||||
];
|
||||
|
||||
# to define interface regions of this layer we consider the overhangs of all the upper layers
|
||||
|
@ -820,8 +844,7 @@ sub generate_support_material {
|
|||
],
|
||||
);
|
||||
$layers_interfaces{$i} = [
|
||||
map $_->simplify($flow->scaled_spacing),
|
||||
@{collapse_ex([ map @$_, @{$layers_interfaces{$i}} ], $flow->scaled_width)},
|
||||
@{collapse_ex([ map @$_, @{$layers_interfaces{$i}} ], $flow->scaled_width)},
|
||||
];
|
||||
|
||||
# generate support material in current layer (for upper layers)
|
||||
|
@ -842,8 +865,7 @@ sub generate_support_material {
|
|||
],
|
||||
);
|
||||
$layers{$i} = [
|
||||
map $_->simplify($flow->scaled_spacing),
|
||||
@{collapse_ex([ map @$_, @{$layers{$i}} ], $flow->scaled_width)},
|
||||
@{collapse_ex([ map @$_, @{$layers{$i}} ], $flow->scaled_width)},
|
||||
];
|
||||
|
||||
# get layer overhangs and put them into queue for adding support inside lower layers;
|
||||
|
|
18
t/fill.t
18
t/fill.t
|
@ -95,4 +95,22 @@ sub scale_points (@) { map [scale $_->[X], scale $_->[Y]], @_ }
|
|||
ok Slic3r::Test::gcode($print), 'successful hilbertcurve infill generation';
|
||||
}
|
||||
|
||||
{
|
||||
my $config = Slic3r::Config->new_from_defaults;
|
||||
$config->set('skirts', 0);
|
||||
$config->set('perimeters', 0);
|
||||
$config->set('fill_density', 0);
|
||||
$config->set('top_solid_layers', 0);
|
||||
$config->set('bottom_solid_layers', 0);
|
||||
$config->set('solid_infill_below_area', 20000000);
|
||||
|
||||
my $print = Slic3r::Test::init_print('20mm_cube', config => $config);
|
||||
Slic3r::Test::GCodeReader->new(gcode => Slic3r::Test::gcode($print))->parse(sub {
|
||||
my ($self, $cmd, $args, $info) = @_;
|
||||
|
||||
fail "solid_infill_below_area should be ignored when fill_density is 0"
|
||||
if $info->{extruding};
|
||||
});
|
||||
}
|
||||
|
||||
__END__
|
||||
|
|
Loading…
Reference in a new issue