mirror of
https://git.mirrors.martin98.com/https://github.com/slic3r/Slic3r.git
synced 2025-08-06 05:37:04 +08:00
Integration of spline based layer height postprocessing
This commit is contained in:
parent
7293f56f9b
commit
a3867b0be8
@ -149,9 +149,9 @@ sub new {
|
|||||||
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new($Slic3r::var->("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_SCALE, "Scale…", Wx::Bitmap->new($Slic3r::var->("arrow_out.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new($Slic3r::var->("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_SPLIT, "Split", Wx::Bitmap->new($Slic3r::var->("shape_ungroup.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new($Slic3r::var->("package.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_CUT, "Cut…", Wx::Bitmap->new($Slic3r::var->("package.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
$self->{htoolbar}->AddTool(TB_LAYERS, "Layers…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
|
||||||
$self->{htoolbar}->AddSeparator;
|
$self->{htoolbar}->AddSeparator;
|
||||||
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
$self->{htoolbar}->AddTool(TB_SETTINGS, "Settings…", Wx::Bitmap->new($Slic3r::var->("cog.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
|
$self->{htoolbar}->AddTool(TB_LAYERS, "Layers…", Wx::Bitmap->new($Slic3r::var->("layers.png"), wxBITMAP_TYPE_PNG), '');
|
||||||
} else {
|
} else {
|
||||||
my %tbar_buttons = (
|
my %tbar_buttons = (
|
||||||
add => "Add…",
|
add => "Add…",
|
||||||
|
@ -4,6 +4,7 @@ use warnings;
|
|||||||
use utf8;
|
use utf8;
|
||||||
|
|
||||||
use Slic3r::Geometry qw(PI X scale unscale);
|
use Slic3r::Geometry qw(PI X scale unscale);
|
||||||
|
use Slic3r::Print::State ':steps';
|
||||||
use List::Util qw(min max sum first);
|
use List::Util qw(min max sum first);
|
||||||
use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
|
use Wx qw(wxTheApp :dialog :id :misc :sizer wxTAB_TRAVERSAL);
|
||||||
use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
|
use Wx::Event qw(EVT_CLOSE EVT_BUTTON);
|
||||||
@ -14,12 +15,11 @@ sub new {
|
|||||||
my ($parent, %params) = @_;
|
my ($parent, %params) = @_;
|
||||||
my $self = $class->SUPER::new($parent, -1, $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
my $self = $class->SUPER::new($parent, -1, $params{object}->name, wxDefaultPosition, [500,500], wxDEFAULT_DIALOG_STYLE | wxRESIZE_BORDER);
|
||||||
$self->{model_object} = $params{model_object};
|
$self->{model_object} = $params{model_object};
|
||||||
|
|
||||||
|
|
||||||
my $model_object = $self->{model_object} = $params{model_object};
|
my $model_object = $self->{model_object} = $params{model_object};
|
||||||
my $obj_idx = $self->{obj_idx} = $params{obj_idx};
|
my $obj_idx = $self->{obj_idx} = $params{obj_idx};
|
||||||
my $plater = $self->{plater} = $parent;
|
my $plater = $self->{plater} = $parent;
|
||||||
|
my $object = $self->{object} = $self->{plater}->{print}->get_object($self->{obj_idx});
|
||||||
|
|
||||||
# Initialize 3D toolpaths preview
|
# Initialize 3D toolpaths preview
|
||||||
if ($Slic3r::GUI::have_OpenGL) {
|
if ($Slic3r::GUI::have_OpenGL) {
|
||||||
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self, $plater->{print});
|
$self->{preview3D} = Slic3r::GUI::Plater::3DPreview->new($self, $plater->{print});
|
||||||
@ -32,8 +32,8 @@ sub new {
|
|||||||
$self->{preview3D}->load_print;
|
$self->{preview3D}->load_print;
|
||||||
$self->{preview3D}->canvas->zoom_to_volumes;
|
$self->{preview3D}->canvas->zoom_to_volumes;
|
||||||
}
|
}
|
||||||
|
|
||||||
$self->{splineControl} = Slic3r::GUI::Plater::SplineControl->new($self, Wx::Size->new(100, 200));
|
$self->{splineControl} = Slic3r::GUI::Plater::SplineControl->new($self, Wx::Size->new(200, 200), $object);
|
||||||
|
|
||||||
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
my $right_sizer = Wx::BoxSizer->new(wxVERTICAL);
|
||||||
$right_sizer->Add($self->{splineControl}, 1, wxEXPAND | wxALL, 0);
|
$right_sizer->Add($self->{splineControl}, 1, wxEXPAND | wxALL, 0);
|
||||||
@ -46,9 +46,7 @@ sub new {
|
|||||||
$self->SetSize([800, 600]);
|
$self->SetSize([800, 600]);
|
||||||
$self->SetMinSize($self->GetSize);
|
$self->SetMinSize($self->GetSize);
|
||||||
|
|
||||||
# init spline control values
|
# init spline control values
|
||||||
my $object = $self->{plater}->{print}->get_object($self->{obj_idx});
|
|
||||||
|
|
||||||
# determine min and max layer height from perimeter extruder capabilities.
|
# determine min and max layer height from perimeter extruder capabilities.
|
||||||
my %extruders;
|
my %extruders;
|
||||||
for my $region_id (0 .. ($object->region_count - 1)) {
|
for my $region_id (0 .. ($object->region_count - 1)) {
|
||||||
@ -62,10 +60,12 @@ sub new {
|
|||||||
|
|
||||||
$self->{splineControl}->set_size_parameters($min_height, $max_height, unscale($object->size->z));
|
$self->{splineControl}->set_size_parameters($min_height, $max_height, unscale($object->size->z));
|
||||||
|
|
||||||
# get array of current Z coordinates for selected object
|
|
||||||
my @layer_heights = map $_->print_z, @{$object->layers};
|
|
||||||
|
|
||||||
$self->{splineControl}->set_layer_points(@layer_heights);
|
$self->{splineControl}->on_layer_update(sub {
|
||||||
|
# trigger re-slicing
|
||||||
|
$self->{object}->invalidate_step(STEP_SLICE);
|
||||||
|
$self->{plater}->start_background_process;
|
||||||
|
});
|
||||||
|
|
||||||
return $self;
|
return $self;
|
||||||
}
|
}
|
||||||
|
@ -89,118 +89,144 @@ sub slice {
|
|||||||
my $slice_z = 0;
|
my $slice_z = 0;
|
||||||
my $height = 0;
|
my $height = 0;
|
||||||
my $cusp_height = 0;
|
my $cusp_height = 0;
|
||||||
|
my @layers = ();
|
||||||
|
|
||||||
# create stateful objects and variables for the adaptive slicing process
|
if(!$self->layer_height_spline->updateRequired) { # layer heights are already generated, just update layers from spline
|
||||||
my @adaptive_slicing;
|
@layers = @{$self->layer_height_spline->getInterpolatedLayers};
|
||||||
my $min_height = 0;
|
}else{ # create new set of layers
|
||||||
my $max_height = 0;
|
# create stateful objects and variables for the adaptive slicing process
|
||||||
if ($self->config->adaptive_slicing) {
|
my @adaptive_slicing;
|
||||||
for my $region_id (0 .. ($self->region_count - 1)) {
|
my $min_height = 0;
|
||||||
my $mesh;
|
my $max_height = 0;
|
||||||
foreach my $volume_id (@{ $self->get_region_volumes($region_id) }) {
|
if ($self->config->adaptive_slicing) {
|
||||||
my $volume = $self->model_object->volumes->[$volume_id];
|
for my $region_id (0 .. ($self->region_count - 1)) {
|
||||||
next if $volume->modifier;
|
my $mesh;
|
||||||
if (defined $mesh) {
|
foreach my $volume_id (@{ $self->get_region_volumes($region_id) }) {
|
||||||
$mesh->merge($volume->mesh);
|
my $volume = $self->model_object->volumes->[$volume_id];
|
||||||
} else {
|
next if $volume->modifier;
|
||||||
$mesh = $volume->mesh->clone;
|
if (defined $mesh) {
|
||||||
}
|
$mesh->merge($volume->mesh);
|
||||||
}
|
} else {
|
||||||
|
$mesh = $volume->mesh->clone;
|
||||||
if (defined $mesh) {
|
}
|
||||||
$adaptive_slicing[$region_id] = Slic3r::AdaptiveSlicing->new(
|
}
|
||||||
mesh => $mesh,
|
|
||||||
size => $self->size->z
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# determine min and max layer height from perimeter extruder capabilities.
|
|
||||||
if($self->region_count > 1) { # multimaterial object
|
|
||||||
$min_height = max(map {$self->print->config->get_at('min_layer_height', $_)} (0..($self->region_count-1)));
|
|
||||||
$max_height = min(map {$self->print->config->get_at('max_layer_height', $_)} (0..($self->region_count-1)));
|
|
||||||
}else{ #single material object
|
|
||||||
my $perimeter_extruder = $self->print->get_region(0)->config->get('perimeter_extruder')-1;
|
|
||||||
$min_height = $self->print->config->get_at('min_layer_height', $perimeter_extruder);
|
|
||||||
$max_height = $self->print->config->get_at('max_layer_height', $perimeter_extruder);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
# 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 (($slice_z - $height) <= $max_z) {
|
|
||||||
|
|
||||||
if ($self->config->adaptive_slicing) {
|
|
||||||
$height = 999;
|
|
||||||
my $cusp_value = $self->config->get_value('cusp_value');
|
|
||||||
|
|
||||||
Slic3r::debugf "\n Slice layer: %d\n", $id;
|
|
||||||
|
|
||||||
# determine next layer height
|
|
||||||
for my $region_id (0 .. ($self->region_count - 1)) {
|
|
||||||
# get cusp height
|
|
||||||
next if(!defined $adaptive_slicing[$region_id]);
|
|
||||||
my $cusp_height = $adaptive_slicing[$region_id]->cusp_height(scale $slice_z, $cusp_value, $min_height, $max_height);
|
|
||||||
|
|
||||||
# check for horizontal features and object size
|
|
||||||
if($self->config->get_value('match_horizontal_surfaces')) {
|
|
||||||
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height);
|
|
||||||
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) {
|
|
||||||
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist;
|
|
||||||
# can we shrink the current layer a bit?
|
|
||||||
if($cusp_height-($min_height-$horizontal_dist) > $min_height) {
|
|
||||||
# yes we can
|
|
||||||
$cusp_height = $cusp_height-($min_height-$horizontal_dist);
|
|
||||||
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height;
|
|
||||||
}else{
|
|
||||||
# no, current layer would become too thin
|
|
||||||
$cusp_height = $cusp_height+$horizontal_dist;
|
|
||||||
Slic3r::debugf "Widen layer height to %f\n", $cusp_height;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
$height = ($id == 0)
|
if (defined $mesh) {
|
||||||
? $self->config->get_value('first_layer_height')
|
$adaptive_slicing[$region_id] = Slic3r::AdaptiveSlicing->new(
|
||||||
: min($cusp_height, $height);
|
mesh => $mesh,
|
||||||
}
|
size => $self->size->z
|
||||||
|
);
|
||||||
}else{
|
}
|
||||||
# assign the default height to the layer according to the general settings
|
|
||||||
$height = ($id == 0)
|
|
||||||
? $self->config->get_value('first_layer_height')
|
|
||||||
: $self->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;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
# determine min and max layer height from perimeter extruder capabilities.
|
||||||
|
if($self->region_count > 1) { # multimaterial object
|
||||||
|
$min_height = max(map {$self->print->config->get_at('min_layer_height', $_)} (0..($self->region_count-1)));
|
||||||
|
$max_height = min(map {$self->print->config->get_at('max_layer_height', $_)} (0..($self->region_count-1)));
|
||||||
|
}else{ #single material object
|
||||||
|
my $perimeter_extruder = $self->print->get_region(0)->config->get('perimeter_extruder')-1;
|
||||||
|
$min_height = $self->print->config->get_at('min_layer_height', $perimeter_extruder);
|
||||||
|
$max_height = $self->print->config->get_at('max_layer_height', $perimeter_extruder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# 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 (($slice_z) < $max_z) {
|
||||||
|
|
||||||
|
if ($self->config->adaptive_slicing) {
|
||||||
|
$height = 999;
|
||||||
|
my $cusp_value = $self->config->get_value('cusp_value');
|
||||||
|
|
||||||
|
Slic3r::debugf "\n Slice layer: %d\n", $id;
|
||||||
|
|
||||||
|
# determine next layer height
|
||||||
|
for my $region_id (0 .. ($self->region_count - 1)) {
|
||||||
|
# get cusp height
|
||||||
|
next if(!defined $adaptive_slicing[$region_id]);
|
||||||
|
my $cusp_height = $adaptive_slicing[$region_id]->cusp_height(scale $slice_z, $cusp_value, $min_height, $max_height);
|
||||||
|
|
||||||
|
# check for horizontal features and object size
|
||||||
|
if($self->config->get_value('match_horizontal_surfaces')) {
|
||||||
|
my $horizontal_dist = $adaptive_slicing[$region_id]->horizontal_facet_distance(scale $slice_z+$cusp_height, $min_height);
|
||||||
|
if(($horizontal_dist < $min_height) && ($horizontal_dist > 0)) {
|
||||||
|
Slic3r::debugf "Horizontal feature ahead, distance: %f\n", $horizontal_dist;
|
||||||
|
# can we shrink the current layer a bit?
|
||||||
|
if($cusp_height-($min_height-$horizontal_dist) > $min_height) {
|
||||||
|
# yes we can
|
||||||
|
$cusp_height = $cusp_height-($min_height-$horizontal_dist);
|
||||||
|
Slic3r::debugf "Shrink layer height to %f\n", $cusp_height;
|
||||||
|
}else{
|
||||||
|
# no, current layer would become too thin
|
||||||
|
$cusp_height = $cusp_height+$horizontal_dist;
|
||||||
|
Slic3r::debugf "Widen layer height to %f\n", $cusp_height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$height = ($id == 0)
|
||||||
|
? $self->config->get_value('first_layer_height')
|
||||||
|
: min($cusp_height, $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
}else{
|
||||||
|
# assign the default height to the layer according to the general settings
|
||||||
|
$height = ($id == 0)
|
||||||
|
? $self->config->get_value('first_layer_height')
|
||||||
|
: $self->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 ($first_object_layer_height != -1 && !@{$self->layers}) {
|
# if user set custom height to zero we should just skip the range and resume slicing over it
|
||||||
$height = $first_object_layer_height;
|
if ($height == 0) {
|
||||||
$print_z += ($first_object_layer_distance - $height);
|
$slice_z += $range->[1] - $range->[0];
|
||||||
|
next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
# set first layer height if raft is active
|
||||||
|
if ($first_object_layer_height != -1 && !@layers) {
|
||||||
|
$height = $first_object_layer_height;
|
||||||
|
#$print_z += ($first_object_layer_distance - $height);
|
||||||
|
}
|
||||||
|
|
||||||
|
$slice_z += $height;
|
||||||
|
$id++;
|
||||||
|
|
||||||
|
# collect layers for spline smoothing
|
||||||
|
push (@layers, $slice_z);
|
||||||
}
|
}
|
||||||
|
$self->layer_height_spline->setLayers(\@layers);
|
||||||
|
if ($self->config->adaptive_slicing) { # smoothing after adaptive algorithm
|
||||||
|
$self->layer_height_spline->setLayers($self->layer_height_spline->getInterpolatedLayers);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$id = 0;
|
||||||
|
if ($self->config->raft_layers > 0) {
|
||||||
|
$id = $self->config->raft_layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
# generate layer objects
|
||||||
|
$slice_z = 0;
|
||||||
|
foreach my $z (@layers) {
|
||||||
|
$height = $z - $slice_z;
|
||||||
$print_z += $height;
|
$print_z += $height;
|
||||||
$slice_z += $height/2;
|
$slice_z += $height/2;
|
||||||
|
|
||||||
### Slic3r::debugf "Layer %d: height = %s; slice_z = %s; print_z = %s\n", $id, $height, $slice_z, $print_z;
|
Slic3r::debugf "Layer %d: height = %s; slice_z = %s; print_z = %s\n", $id, $height, $slice_z, $print_z;
|
||||||
|
|
||||||
$self->add_layer($id, $height, $print_z, $slice_z);
|
$self->add_layer($id, $height, $print_z, $slice_z);
|
||||||
if ($self->layer_count >= 2) {
|
if ($self->layer_count >= 2) {
|
||||||
my $lc = $self->layer_count;
|
my $lc = $self->layer_count;
|
||||||
$self->get_layer($lc - 2)->set_upper_layer($self->get_layer($lc - 1));
|
$self->get_layer($lc - 2)->set_upper_layer($self->get_layer($lc - 1));
|
||||||
$self->get_layer($lc - 1)->set_lower_layer($self->get_layer($lc - 2));
|
$self->get_layer($lc - 1)->set_lower_layer($self->get_layer($lc - 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
$id++;
|
$id++;
|
||||||
|
|
||||||
$slice_z += $height/2; # add the other half layer
|
$slice_z += $height/2; # add the other half layer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,7 @@
|
|||||||
#include "Layer.hpp"
|
#include "Layer.hpp"
|
||||||
#include "Model.hpp"
|
#include "Model.hpp"
|
||||||
#include "PlaceholderParser.hpp"
|
#include "PlaceholderParser.hpp"
|
||||||
|
#include "LayerHeightSpline.hpp"
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
@ -83,6 +83,8 @@ class PrintObject
|
|||||||
PrintObjectConfig config;
|
PrintObjectConfig config;
|
||||||
t_layer_height_ranges layer_height_ranges;
|
t_layer_height_ranges layer_height_ranges;
|
||||||
|
|
||||||
|
LayerHeightSpline layer_height_spline;
|
||||||
|
|
||||||
// this is set to true when LayerRegion->slices is split in top/internal/bottom
|
// this is set to true when LayerRegion->slices is split in top/internal/bottom
|
||||||
// so that next call to make_perimeters() performs a union() before computing loops
|
// so that next call to make_perimeters() performs a union() before computing loops
|
||||||
bool typed_slices;
|
bool typed_slices;
|
||||||
|
@ -8,7 +8,8 @@ namespace Slic3r {
|
|||||||
PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox)
|
PrintObject::PrintObject(Print* print, ModelObject* model_object, const BoundingBoxf3 &modobj_bbox)
|
||||||
: typed_slices(false),
|
: typed_slices(false),
|
||||||
_print(print),
|
_print(print),
|
||||||
_model_object(model_object)
|
_model_object(model_object),
|
||||||
|
layer_height_spline(modobj_bbox.size().z)
|
||||||
{
|
{
|
||||||
// Compute the translation to be applied to our meshes so that we work with smaller coordinates
|
// Compute the translation to be applied to our meshes so that we work with smaller coordinates
|
||||||
{
|
{
|
||||||
|
@ -58,6 +58,8 @@ _constant()
|
|||||||
Points copies();
|
Points copies();
|
||||||
t_layer_height_ranges layer_height_ranges()
|
t_layer_height_ranges layer_height_ranges()
|
||||||
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
%code%{ RETVAL = THIS->layer_height_ranges; %};
|
||||||
|
Ref<LayerHeightSpline> layer_height_spline()
|
||||||
|
%code%{ RETVAL = &THIS->layer_height_spline; %};
|
||||||
Ref<Point3> size()
|
Ref<Point3> size()
|
||||||
%code%{ RETVAL = &THIS->size; %};
|
%code%{ RETVAL = &THIS->size; %};
|
||||||
Clone<BoundingBox> bounding_box();
|
Clone<BoundingBox> bounding_box();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user