mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-08-18 01:35:54 +08:00
New feature: brim connections
This commit is contained in:
parent
7dfea3ecf0
commit
e901514212
@ -1285,7 +1285,9 @@ sub load_print_toolpaths {
|
|||||||
|
|
||||||
return if !$print->step_done(STEP_SKIRT);
|
return if !$print->step_done(STEP_SKIRT);
|
||||||
return if !$print->step_done(STEP_BRIM);
|
return if !$print->step_done(STEP_BRIM);
|
||||||
return if !$print->has_skirt && $print->config->brim_width == 0;
|
return if !$print->has_skirt
|
||||||
|
&& $print->config->brim_width == 0
|
||||||
|
&& $print->config->brim_connections_width == 0;
|
||||||
|
|
||||||
my $qverts = Slic3r::GUI::_3DScene::GLVertexArray->new;
|
my $qverts = Slic3r::GUI::_3DScene::GLVertexArray->new;
|
||||||
my $tverts = Slic3r::GUI::_3DScene::GLVertexArray->new;
|
my $tverts = Slic3r::GUI::_3DScene::GLVertexArray->new;
|
||||||
|
@ -479,7 +479,7 @@ sub build {
|
|||||||
perimeter_acceleration infill_acceleration bridge_acceleration
|
perimeter_acceleration infill_acceleration bridge_acceleration
|
||||||
first_layer_acceleration default_acceleration
|
first_layer_acceleration default_acceleration
|
||||||
skirts skirt_distance skirt_height min_skirt_length
|
skirts skirt_distance skirt_height min_skirt_length
|
||||||
brim_width
|
brim_connections_width brim_width
|
||||||
support_material support_material_threshold support_material_enforce_layers
|
support_material support_material_threshold support_material_enforce_layers
|
||||||
raft_layers
|
raft_layers
|
||||||
support_material_pattern support_material_spacing support_material_angle
|
support_material_pattern support_material_spacing support_material_angle
|
||||||
@ -571,6 +571,7 @@ sub build {
|
|||||||
{
|
{
|
||||||
my $optgroup = $page->new_optgroup('Brim');
|
my $optgroup = $page->new_optgroup('Brim');
|
||||||
$optgroup->append_single_option_line('brim_width');
|
$optgroup->append_single_option_line('brim_width');
|
||||||
|
$optgroup->append_single_option_line('brim_connections_width');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -848,7 +849,7 @@ sub _update {
|
|||||||
$self->get_field($_)->toggle($have_skirt)
|
$self->get_field($_)->toggle($have_skirt)
|
||||||
for qw(skirt_distance skirt_height);
|
for qw(skirt_distance skirt_height);
|
||||||
|
|
||||||
my $have_brim = $config->brim_width > 0;
|
my $have_brim = $config->brim_width > 0 || $config->brim_connections_width;
|
||||||
# perimeter_extruder uses the same logic as in Print::extruders()
|
# perimeter_extruder uses the same logic as in Print::extruders()
|
||||||
$self->get_field('perimeter_extruder')->toggle($have_perimeters || $have_brim);
|
$self->get_field('perimeter_extruder')->toggle($have_perimeters || $have_brim);
|
||||||
|
|
||||||
|
@ -12,8 +12,9 @@ use Slic3r::ExtrusionPath ':roles';
|
|||||||
use Slic3r::Flow ':roles';
|
use Slic3r::Flow ':roles';
|
||||||
use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale convex_hull);
|
use Slic3r::Geometry qw(X Y Z X1 Y1 X2 Y2 MIN MAX PI scale unscale convex_hull);
|
||||||
use Slic3r::Geometry::Clipper qw(diff_ex union_ex intersection_ex intersection offset
|
use Slic3r::Geometry::Clipper qw(diff_ex union_ex intersection_ex intersection offset
|
||||||
offset2 union union_pt_chained JT_ROUND JT_SQUARE);
|
offset2 union union_pt_chained JT_ROUND JT_SQUARE diff_pl);
|
||||||
use Slic3r::Print::State ':steps';
|
use Slic3r::Print::State ':steps';
|
||||||
|
use Slic3r::Surface qw(S_TYPE_BOTTOM);
|
||||||
|
|
||||||
our $status_cb;
|
our $status_cb;
|
||||||
|
|
||||||
@ -356,7 +357,7 @@ sub make_brim {
|
|||||||
# checking whether we need to generate them
|
# checking whether we need to generate them
|
||||||
$self->brim->clear;
|
$self->brim->clear;
|
||||||
|
|
||||||
if ($self->config->brim_width == 0) {
|
if ($self->config->brim_width == 0 && $self->config->brim_connections_width == 0) {
|
||||||
$self->set_step_done(STEP_BRIM);
|
$self->set_step_done(STEP_BRIM);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -390,7 +391,7 @@ sub make_brim {
|
|||||||
}
|
}
|
||||||
|
|
||||||
my @loops = ();
|
my @loops = ();
|
||||||
my $num_loops = sprintf "%.0f", $self->config->brim_width / $flow->width;
|
my $num_loops = int($self->config->brim_width / $flow->width + 0.5);
|
||||||
for my $i (reverse 1 .. $num_loops) {
|
for my $i (reverse 1 .. $num_loops) {
|
||||||
# JT_SQUARE ensures no vertex is outside the given offset distance
|
# JT_SQUARE ensures no vertex is outside the given offset distance
|
||||||
# -0.5 because islands are not represented by their centerlines
|
# -0.5 because islands are not represented by their centerlines
|
||||||
@ -409,6 +410,65 @@ sub make_brim {
|
|||||||
),
|
),
|
||||||
), reverse @{union_pt_chained(\@loops)});
|
), reverse @{union_pt_chained(\@loops)});
|
||||||
|
|
||||||
|
if ($self->config->brim_connections_width > 0) {
|
||||||
|
# get islands to connects
|
||||||
|
@islands = map convex_hull(\@$_), @islands;
|
||||||
|
@islands = @{offset(\@islands, ($num_loops-0.2) * $flow->scaled_spacing, 10000, JT_SQUARE)};
|
||||||
|
|
||||||
|
# compute centroid for each island
|
||||||
|
my @centroids = map $_->centroid, @islands;
|
||||||
|
|
||||||
|
# in order to check visibility we need to account for the connections width,
|
||||||
|
# so let's use grown islands
|
||||||
|
my $scaled_width = scale($self->config->brim_connections_width);
|
||||||
|
my $grown = offset(\@islands, +$scaled_width/2);
|
||||||
|
|
||||||
|
# find pairs of islands having direct visibility
|
||||||
|
my @lines = ();
|
||||||
|
for my $i (0..$#islands) {
|
||||||
|
for my $j (($i+1)..$#islands) {
|
||||||
|
# check visibility
|
||||||
|
my $line = Slic3r::Line->new(@centroids[$i,$j]);
|
||||||
|
next if @{diff_pl([$line->as_polyline], $grown)} != 1;
|
||||||
|
|
||||||
|
push @lines, $line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
my $filler = Slic3r::Filler->new_from_type('rectilinear');
|
||||||
|
$filler->set_spacing($flow->spacing);
|
||||||
|
$filler->set_dont_adjust(1);
|
||||||
|
|
||||||
|
# subtract already generated connections in order to prevent crossings
|
||||||
|
# and overextrusion
|
||||||
|
my @other = ();
|
||||||
|
|
||||||
|
foreach my $line (@lines) {
|
||||||
|
my $expolygons = diff_ex(
|
||||||
|
$line->grow($scaled_width/2),
|
||||||
|
[ @islands, @other ],
|
||||||
|
);
|
||||||
|
push @other, map $_->clone, map @$_, @$expolygons;
|
||||||
|
|
||||||
|
$filler->set_angle($line->direction);
|
||||||
|
foreach my $expolygon (@$expolygons) {
|
||||||
|
my $paths = $filler->fill_surface(
|
||||||
|
Slic3r::Surface->new(expolygon => $expolygon, surface_type => S_TYPE_BOTTOM),
|
||||||
|
layer_height => $first_layer_height,
|
||||||
|
density => 1,
|
||||||
|
);
|
||||||
|
|
||||||
|
$self->brim->append(map Slic3r::ExtrusionPath->new(
|
||||||
|
polyline => $_,
|
||||||
|
role => EXTR_ROLE_SKIRT,
|
||||||
|
mm3_per_mm => $mm3_per_mm,
|
||||||
|
width => $flow->width,
|
||||||
|
height => $first_layer_height,
|
||||||
|
), @$paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$self->set_step_done(STEP_BRIM);
|
$self->set_step_done(STEP_BRIM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -357,7 +357,7 @@ sub process_layer {
|
|||||||
# check whether we're going to apply spiralvase logic
|
# check whether we're going to apply spiralvase logic
|
||||||
if (defined $self->_spiral_vase) {
|
if (defined $self->_spiral_vase) {
|
||||||
$self->_spiral_vase->enable(
|
$self->_spiral_vase->enable(
|
||||||
($layer->id > 0 || $self->print->config->brim_width == 0)
|
($layer->id > 0 || $self->print->config->brim_width == 0 || $self->print->config->brim_connections_width == 0)
|
||||||
&& ($layer->id >= $self->print->config->skirt_height && !$self->print->has_infinite_skirt)
|
&& ($layer->id >= $self->print->config->skirt_height && !$self->print->has_infinite_skirt)
|
||||||
&& !defined(first { $_->region->config->bottom_solid_layers > $layer->id } @{$layer->regions})
|
&& !defined(first { $_->region->config->bottom_solid_layers > $layer->id } @{$layer->regions})
|
||||||
&& !defined(first { $_->perimeters->items_count > 1 } @{$layer->regions})
|
&& !defined(first { $_->perimeters->items_count > 1 } @{$layer->regions})
|
||||||
@ -447,7 +447,7 @@ sub process_layer {
|
|||||||
$gcode .= $self->_gcodegen->set_extruder($self->print->regions->[0]->config->perimeter_extruder-1);
|
$gcode .= $self->_gcodegen->set_extruder($self->print->regions->[0]->config->perimeter_extruder-1);
|
||||||
$self->_gcodegen->set_origin(Slic3r::Pointf->new(0,0));
|
$self->_gcodegen->set_origin(Slic3r::Pointf->new(0,0));
|
||||||
$self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(1);
|
$self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(1);
|
||||||
$gcode .= $self->_gcodegen->extrude_loop($_, 'brim', $object->config->support_material_speed)
|
$gcode .= $self->_gcodegen->extrude($_, 'brim', $object->config->support_material_speed)
|
||||||
for @{$self->print->brim};
|
for @{$self->print->brim};
|
||||||
$self->_brim_done(1);
|
$self->_brim_done(1);
|
||||||
$self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(0);
|
$self->_gcodegen->avoid_crossing_perimeters->set_use_external_mp(0);
|
||||||
|
@ -163,7 +163,8 @@ Print::invalidate_state_by_config_options(const std::vector<t_config_option_key>
|
|||||||
|| *opt_key == "min_skirt_length"
|
|| *opt_key == "min_skirt_length"
|
||||||
|| *opt_key == "ooze_prevention") {
|
|| *opt_key == "ooze_prevention") {
|
||||||
steps.insert(psSkirt);
|
steps.insert(psSkirt);
|
||||||
} else if (*opt_key == "brim_width") {
|
} else if (*opt_key == "brim_width"
|
||||||
|
|| *opt_key == "brim_connections_width") {
|
||||||
steps.insert(psBrim);
|
steps.insert(psBrim);
|
||||||
steps.insert(psSkirt);
|
steps.insert(psSkirt);
|
||||||
} else if (*opt_key == "nozzle_diameter"
|
} else if (*opt_key == "nozzle_diameter"
|
||||||
@ -304,7 +305,7 @@ Print::object_extruders() const
|
|||||||
FOREACH_REGION(this, region) {
|
FOREACH_REGION(this, region) {
|
||||||
// these checks reflect the same logic used in the GUI for enabling/disabling
|
// these checks reflect the same logic used in the GUI for enabling/disabling
|
||||||
// extruder selection fields
|
// extruder selection fields
|
||||||
if ((*region)->config.perimeters.value > 0 || this->config.brim_width.value > 0)
|
if ((*region)->config.perimeters.value > 0 || this->config.brim_width.value > 0 || this->config.brim_connections_width.value > 0)
|
||||||
extruders.insert((*region)->config.perimeter_extruder - 1);
|
extruders.insert((*region)->config.perimeter_extruder - 1);
|
||||||
|
|
||||||
if ((*region)->config.fill_density.value > 0)
|
if ((*region)->config.fill_density.value > 0)
|
||||||
|
@ -91,6 +91,14 @@ PrintConfigDef::PrintConfigDef()
|
|||||||
def->min = 0;
|
def->min = 0;
|
||||||
def->default_value = new ConfigOptionFloat(60);
|
def->default_value = new ConfigOptionFloat(60);
|
||||||
|
|
||||||
|
def = this->add("brim_connections_width", coFloat);
|
||||||
|
def->label = "Brim connections width";
|
||||||
|
def->tooltip = "If set to a positive value, straight connections will be built on the first layer between adjacent objects.";
|
||||||
|
def->sidetext = "mm";
|
||||||
|
def->cli = "brim-connections-width=f";
|
||||||
|
def->min = 0;
|
||||||
|
def->default_value = new ConfigOptionFloat(0);
|
||||||
|
|
||||||
def = this->add("brim_width", coFloat);
|
def = this->add("brim_width", coFloat);
|
||||||
def->label = "Brim width";
|
def->label = "Brim width";
|
||||||
def->tooltip = "Horizontal width of the brim that will be printed around each object on the first layer.";
|
def->tooltip = "Horizontal width of the brim that will be printed around each object on the first layer.";
|
||||||
|
@ -366,6 +366,7 @@ class PrintConfig : public GCodeConfig
|
|||||||
ConfigOptionInt bed_temperature;
|
ConfigOptionInt bed_temperature;
|
||||||
ConfigOptionFloat bridge_acceleration;
|
ConfigOptionFloat bridge_acceleration;
|
||||||
ConfigOptionInt bridge_fan_speed;
|
ConfigOptionInt bridge_fan_speed;
|
||||||
|
ConfigOptionFloat brim_connections_width;
|
||||||
ConfigOptionFloat brim_width;
|
ConfigOptionFloat brim_width;
|
||||||
ConfigOptionBool complete_objects;
|
ConfigOptionBool complete_objects;
|
||||||
ConfigOptionBool cooling;
|
ConfigOptionBool cooling;
|
||||||
@ -425,6 +426,7 @@ class PrintConfig : public GCodeConfig
|
|||||||
OPT_PTR(bed_temperature);
|
OPT_PTR(bed_temperature);
|
||||||
OPT_PTR(bridge_acceleration);
|
OPT_PTR(bridge_acceleration);
|
||||||
OPT_PTR(bridge_fan_speed);
|
OPT_PTR(bridge_fan_speed);
|
||||||
|
OPT_PTR(brim_connections_width);
|
||||||
OPT_PTR(brim_width);
|
OPT_PTR(brim_width);
|
||||||
OPT_PTR(complete_objects);
|
OPT_PTR(complete_objects);
|
||||||
OPT_PTR(cooling);
|
OPT_PTR(cooling);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user