More incomplete work

This commit is contained in:
Alessandro Ranellucci 2013-12-31 14:33:03 +01:00
parent beb1baa096
commit 83326845dd
7 changed files with 85 additions and 111 deletions

View File

@ -14,8 +14,7 @@ has 'layer' => (
is => 'ro',
weak_ref => 1,
required => 1,
trigger => 1,
handles => [qw(id slice_z print_z height flow config)],
handles => [qw(id slice_z print_z height config)],
);
has 'region' => (is => 'ro', required => 1, handles => [qw(extruders)]);
has 'infill_area_threshold' => (is => 'lazy');

View File

@ -5,6 +5,7 @@ use File::Basename qw(basename fileparse);
use File::Spec;
use List::Util qw(min max first);
use Slic3r::ExtrusionPath ':roles';
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale move_points chained_path
convex_hull);
use Slic3r::Geometry::Clipper qw(diff_ex union_ex union_pt intersection_ex intersection offset
@ -96,6 +97,7 @@ sub add_model_object {
my $config = $object->model->materials->{ $volume->material_id }->config;
} else {
$config = Slic3r::Config->new;
$config->set('extruder', 0);
}
# find an existing print region with the same config
@ -110,7 +112,10 @@ sub add_model_object {
# if no region exists with the same config, create a new one
if (!defined $region_id) {
push @{$self->regions}, Slic3r::Print::Region->new(config => $config->clone);
push @{$self->regions}, Slic3r::Print::Region->new(
print => $self,
config => $config->clone,
);
$region_id = $#{$self->regions};
}
@ -233,15 +238,19 @@ sub validate {
sub init_extruders {
my $self = shift;
# map regions to extruders (ghetto mapping for now)
my %extruder_mapping = map { $_ => $_ } 0..$#{$self->regions};
# initialize all extruder(s) we need
my @used_extruders = (
0,
(map $self->config->get("${_}_extruder")-1, qw(perimeter infill support_material support_material_interface)),
(values %extruder_mapping),
);
my @used_extruders = ();
foreach my $region (@{$self->regions}) {
push @used_extruders,
map $region->config->get("${_}_extruder")-1,
qw(perimeter infill);
}
foreach my $object (@{$self->objects}) {
push @used_extruders,
map $object->config->get("${_}_extruder")-1,
qw(support_material support_material_interface);
}
for my $extruder_id (keys %{{ map {$_ => 1} @used_extruders }}) {
$self->extruders->[$extruder_id] = Slic3r::Extruder->new(
config => $self->config,
@ -251,51 +260,8 @@ sub init_extruders {
);
}
# calculate regions' flows
for my $region_id (0 .. $#{$self->regions}) {
my $region = $self->regions->[$region_id];
# per-role extruders and flows
for (qw(perimeter infill solid_infill top_infill)) {
my $extruder_name = $_;
$extruder_name =~ s/^(?:solid|top)_//;
$region->extruders->{$_} = ($self->regions_count > 1)
? $self->extruders->[$extruder_mapping{$region_id}]
: $self->extruders->[$self->config->get("${extruder_name}_extruder")-1];
$region->flows->{$_} = $region->extruders->{$_}->make_flow(
layer_height => $self->config->layer_height,
width => $self->config->get("${_}_extrusion_width") || $self->config->extrusion_width,
role => $_,
);
$region->first_layer_flows->{$_} = $region->extruders->{$_}->make_flow(
layer_height => $self->config->get_value('first_layer_height'),
width => $self->config->first_layer_extrusion_width,
role => $_,
) if $self->config->first_layer_extrusion_width;
}
}
# calculate support material flow
# Note: we should calculate a different flow for support material interface
# TODO: support material layers have their own variable layer heights, so we
# probably need a DynamicFlow object that calculates flow on the fly
# (or the Flow object must support a mutable layer_height)
if ($self->has_support_material) {
my $extruder = $self->extruders->[$self->config->support_material_extruder-1];
$self->support_material_flow($extruder->make_flow(
layer_height => $self->config->layer_height, # WRONG!
width => $self->config->support_material_extrusion_width || $self->config->extrusion_width,
role => 'support_material',
));
$self->first_layer_support_material_flow($extruder->make_flow(
layer_height => $self->config->get_value('first_layer_height'),
width => $self->config->first_layer_extrusion_width,
role => 'support_material',
));
}
# enforce tall skirt if using ooze_prevention
# NOTE: this is not idempotent (i.e. switching ooze_prevention off will not revert skirt settings)
# FIXME: this is not idempotent (i.e. switching ooze_prevention off will not revert skirt settings)
if ($self->config->ooze_prevention && @{$self->extruders} > 1) {
$self->config->set('skirt_height', -1);
$self->config->set('skirts', 1) if $self->config->skirts == 0;
@ -636,8 +602,17 @@ sub make_skirt {
my @extruded_length = (); # for each extruder
# skirt may be printed on several layers, having distinct layer heights,
# but loops must be aligned so can't vary width/spacing
# TODO: use each extruder's own flow
my $spacing = $self->flow(FLOW_ROLE_SUPPORT_MATERIAL)->spacing;
my $flow = Slic3r::Flow->new(
width => ($self->config->first_layer_extrusion_width || $self->config->perimeter_extrusion_width),
role => FLOW_ROLE_PERIMETER,
nozzle_diameter => $self->config->nozzle_diameter->[0],
layer_height => $self->config->get_abs_value('first_layer_height'),
bridge_flow_ratio => 0,
);
my $spacing = $flow->spacing;
my $first_layer_height = $self->config->get_value('first_layer_height');
my @extruders_e_per_mm = ();
@ -678,7 +653,14 @@ sub make_brim {
$self->brim->clear; # method must be idempotent
my $flow = $self->flow(FLOW_ROLE_SUPPORT_MATERIAL);
# brim is only printed on first layer and uses support material extruder
my $flow = Slic3r::Flow->new(
width => ($self->config->first_layer_extrusion_width || $self->config->perimeter_extrusion_width),
role => FLOW_ROLE_PERIMETER,
nozzle_diameter => $self->config->nozzle_diameter->[ $self->config->support_material_extruder-1 ],
layer_height => $self->config->get_abs_value('first_layer_height'),
bridge_flow_ratio => 0,
);
my $grow_distance = $flow->scaled_width / 2;
my @islands = (); # array of polygons
@ -763,11 +745,11 @@ sub write_gcode {
printf $fh "; top infill extrusion width = %.2fmm\n",
$self->regions->[$region_id]->flow(FLOW_ROLE_TOP_SOLID_INFILL)->width;
printf $fh "; support material extrusion width = %.2fmm\n",
$self->flow(FLOW_ROLE_SUPPORT_MATERIAL)->width
if $self->support_material_flow;
$self->objects->[0]->support_material_flow->width
if $self->has_support_material;
printf $fh "; first layer extrusion width = %.2fmm\n",
$self->flow(FLOW_ROLE_SUPPORT_MATERIAL, 0, 1)->width
if $self->regions->[0]->first_layer_flows->{perimeter};
$self->regions->[$region_id]->flow(FLOW_ROLE_PERIMETER, 0, 1)->width
if ($self->regions->[$region_id]->config->first_layer_extrusion_width != 0);
print $fh "\n";
}
@ -1045,45 +1027,4 @@ sub auto_assign_extruders {
}
}
sub flow {
my ($self, $role, $layer_height, $bridge, $first_layer, $width) = @_;
$bridge //= 0;
$first_layer //= 0;
# use the supplied custom width, if any
my $config_width = $width;
if (!defined $config_width) {
# get extrusion width from configuration
# (might be an absolute value, or a percent value, or zero for auto)
if ($first_layer) {
$config_width = $self->config->first_layer_extrusion_width;
} elsif ($role == FLOW_ROLE_SUPPORT_MATERIAL || $role == FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE) {
$config_width = $self->config->support_material_extrusion_width;
} else {
die "Unknown role $role";
}
}
# get the configured nozzle_diameter for the extruder associated
# to the flow role requested
my $extruder; # 1-based
if ($role == FLOW_ROLE_SUPPORT_MATERIAL) {
$config_width = $self->config->support_material_extruder;
} elsif ($role == FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE) {
$config_width = $self->config->support_material_interface_extruder;
} else {
die "Unknown role $role";
}
my $nozzle_diameter = $self->config->nozzle_diameter->[$extruder-1];
return Slic3r::Flow->new(
width => $config_width,
role => $role,
nozzle_diameter => $nozzle_diameter,
layer_height => $layer_height,
bridge_flow_ratio => ($bridge ? $self->config->bridge_flow_ratio : 0),
);
}
1;

View File

@ -2,6 +2,7 @@ package Slic3r::Print::Object;
use Moo;
use List::Util qw(min max sum first);
use Slic3r::Flow ':roles';
use Slic3r::Geometry qw(X Y Z PI scale unscale deg2rad rad2deg scaled_epsilon chained_path);
use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
offset offset_ex offset2 offset2_ex CLIPPER_OFFSET_SCALE JT_MITER);
@ -300,7 +301,7 @@ sub make_perimeters {
for my $layer_id (0 .. $self->layer_count-2) {
my $layerm = $self->layers->[$layer_id]->regions->[$region_id];
my $upper_layerm = $self->layers->[$layer_id+1]->regions->[$region_id];
my $perimeter_spacing = $layerm->perimeter_flow->scaled_spacing;
my $perimeter_spacing = $layerm->flow(FLOW_ROLE_PERIMETER)->scaled_spacing;
my $overlap = $perimeter_spacing; # one perimeter
@ -862,8 +863,9 @@ sub generate_support_material {
&& $self->layer_count >= 2;
my $s = Slic3r::Print::SupportMaterial->new(
config => $self->config,
flow => $self->print->support_material_flow,
config => $self->config,
flow => $self->support_material_flow,
interface_flow => $self->support_material_flow(FLOW_ROLE_SUPPORT_MATERIAL_INTERFACE),
);
$s->generate($self);
}
@ -877,4 +879,23 @@ sub _simplify_slices {
}
}
sub support_material_flow {
my ($self, $role) = @_;
$role //= FLOW_ROLE_SUPPORT_MATERIAL;
my $extruder = ($role == FLOW_ROLE_SUPPORT_MATERIAL)
? $self->config->support_material_extruder
: $self->config->support_material_interface_extruder;
# we use a bogus layer_height because we use the same flow for all
# support material layers
return Slic3r::Flow->new(
width => $self->config->support_material_extrusion_width,
role => $role,
nozzle_diameter => $self->print->config->nozzle_diameter->[$extruder-1],
layer_height => $self->config->layer_height,
bridge_flow_ratio => 0,
);
}
1;

View File

@ -21,7 +21,7 @@ sub flow {
if (!defined $config_width) {
# get extrusion width from configuration
# (might be an absolute value, or a percent value, or zero for auto)
if ($first_layer) {
if ($first_layer && $self->config->first_layer_extrusion_width != 0) {
$config_width = $self->config->first_layer_extrusion_width;
} elsif ($role == FLOW_ROLE_PERIMETER) {
$config_width = $self->config->perimeter_extrusion_width;

View File

@ -131,6 +131,13 @@ ConfigBase::set(t_config_option_key opt_key, SV* value) {
ConfigOption* opt = this->option(opt_key, true);
if (opt == NULL) CONFESS("Trying to set non-existing option");
ConfigOptionDef* optdef = &(*this->def)[opt_key];
if (!optdef->shortcut.empty()) {
for (std::vector<t_config_option_key>::iterator it = optdef->shortcut.begin(); it != optdef->shortcut.end(); ++it)
this->set(*it, value);
return;
}
if (ConfigOptionFloat* optv = dynamic_cast<ConfigOptionFloat*>(opt)) {
optv->value = SvNV(value);
} else if (ConfigOptionFloats* optv = dynamic_cast<ConfigOptionFloats*>(opt)) {

View File

@ -576,6 +576,14 @@ class PrintConfig : public StaticConfig
Options["extra_perimeters"].cli = "extra-perimeters!";
Options["extra_perimeters"].scope = "object";
Options["extruder"].type = coInt;
Options["extruder"].label = "Extruder";
Options["extruder"].cli = "extruder=i";
Options["extruder"].shortcut.push_back("perimeter_extruder");
Options["extruder"].shortcut.push_back("infill_extruder");
Options["extruder"].shortcut.push_back("support_material_extruder");
Options["extruder"].shortcut.push_back("support_material_interface_extruder");
Options["extruder_clearance_height"].type = coFloat;
Options["extruder_clearance_height"].label = "Height";
Options["extruder_clearance_height"].tooltip = "Set this to the vertical distance between your nozzle tip and (usually) the X carriage rods. In other words, this is the height of the clearance cylinder around your extruder, and it represents the maximum depth the extruder can peek before colliding with other printed objects.";
@ -761,7 +769,6 @@ class PrintConfig : public StaticConfig
Options["infill_extruder"].label = "Infill extruder";
Options["infill_extruder"].tooltip = "The extruder to use when printing infill.";
Options["infill_extruder"].cli = "infill-extruder=i";
Options["infill_extruder"].shortcut.push_back("extruder");
Options["infill_extrusion_width"].type = coFloatOrPercent;
Options["infill_extrusion_width"].label = "Infill";
@ -879,7 +886,6 @@ class PrintConfig : public StaticConfig
Options["perimeter_extruder"].tooltip = "The extruder to use when printing perimeters.";
Options["perimeter_extruder"].cli = "perimeter-extruder=i";
Options["perimeter_extruder"].aliases.push_back("perimeters_extruder");
Options["perimeter_extruder"].shortcut.push_back("extruder");
Options["perimeter_extrusion_width"].type = coFloatOrPercent;
Options["perimeter_extrusion_width"].label = "Perimeters";
@ -1141,7 +1147,6 @@ class PrintConfig : public StaticConfig
Options["support_material_extruder"].label = "Support material extruder";
Options["support_material_extruder"].tooltip = "The extruder to use when printing support material. This affects brim and raft too.";
Options["support_material_extruder"].cli = "support-material-extruder=i";
Options["support_material_extruder"].shortcut.push_back("extruder");
Options["support_material_extrusion_width"].type = coFloatOrPercent;
Options["support_material_extrusion_width"].label = "Support material";
@ -1153,7 +1158,6 @@ class PrintConfig : public StaticConfig
Options["support_material_interface_extruder"].label = "Support material interface extruder";
Options["support_material_interface_extruder"].tooltip = "The extruder to use when printing support material interface. This affects raft too.";
Options["support_material_interface_extruder"].cli = "support-material-interface-extruder=i";
Options["support_material_interface_extruder"].shortcut.push_back("extruder");
Options["support_material_interface_layers"].type = coInt;
Options["support_material_interface_layers"].label = "Interface layers";

View File

@ -4,7 +4,7 @@ use strict;
use warnings;
use Slic3r::XS;
use Test::More tests => 78;
use Test::More tests => 79;
foreach my $config (Slic3r::Config->new, Slic3r::Config::Print->new) {
$config->set('layer_height', 0.3);
@ -88,6 +88,8 @@ foreach my $config (Slic3r::Config->new, Slic3r::Config::Print->new) {
{
my $config = Slic3r::Config->new;
$config->set('perimeters', 2);
$config->set('solid_layers', 2);
is $config->get('top_solid_layers'), 2, 'shortcut';
# test that no crash happens when using set_deserialize() with a key that hasn't been set() yet
$config->set_deserialize('filament_diameter', '3');