diff --git a/lib/Slic3r/GUI/Projector.pm b/lib/Slic3r/GUI/Projector.pm
index a783ecf554..d7d9e7eb85 100644
--- a/lib/Slic3r/GUI/Projector.pm
+++ b/lib/Slic3r/GUI/Projector.pm
@@ -415,7 +415,7 @@ sub new {
my $duration = $self->controller->remaining_print_time;
$self->_set_status(sprintf "Printing layer %d/%d (z = %.2f); %d minutes and %d seconds left",
- $layer_num, $self->controller->layer_count,
+ $layer_num, $self->controller->_print->layer_count,
$self->controller->current_layer_height,
int($duration/60), ($duration - int($duration/60)*60)); # % truncates to integer
},
@@ -426,7 +426,7 @@ sub new {
},
));
{
- my $max = $self->controller->layer_count-1;
+ my $max = $self->controller->_print->layer_count-1;
$self->{layers_spinctrl}->SetRange(0, $max);
$self->{layers_slider}->SetRange(0, $max);
}
@@ -527,7 +527,24 @@ sub BUILD {
Slic3r::GUI::disable_screensaver();
- $self->set_print(wxTheApp->{mainframe}->{plater}->{print});
+ # init print
+ {
+ my $print = Slic3r::SLAPrint->new(wxTheApp->{mainframe}->{plater}->{model});
+ $print->apply_config(wxTheApp->{mainframe}->config);
+ $self->_print($print);
+ $self->screen->print($print);
+
+ # make sure layers were sliced
+ {
+ my $progress_dialog = Wx::ProgressDialog->new('Slicing…', "Processing layers…", 100, undef, 0);
+ $progress_dialog->Pulse;
+ $print->slice;
+ $progress_dialog->Destroy;
+ }
+
+ $self->_layers([ map $print->slices($_), 0..($print->layer_count-1) ]);
+ $self->_heights($print->heights);
+ }
# projection timer
my $timer_id = &Wx::NewId();
@@ -546,40 +563,6 @@ sub delay {
$self->timer->Start($wait * 1000, wxTIMER_ONE_SHOT);
}
-sub set_print {
- my ($self, $print) = @_;
-
- # make sure layers were sliced
- {
- my $progress_dialog;
- foreach my $object (@{$print->objects}) {
- next if $object->step_done(STEP_SLICE);
- $progress_dialog //= Wx::ProgressDialog->new('Slicing…', "Processing layers…", 100, undef, 0);
- $progress_dialog->Pulse;
- $object->slice;
- }
- $progress_dialog->Destroy if $progress_dialog;
- }
-
- $self->_print($print);
-
- # sort layers by Z
- my %layers = ();
- foreach my $layer (map { @{$_->layers}, @{$_->support_layers} } @{$print->objects}) {
- my $height = $layer->print_z;
- $layers{$height} //= [];
- push @{$layers{$height}}, $layer;
- }
- $self->_layers({ %layers });
- $self->_heights([ sort { $a <=> $b } keys %layers ]);
-}
-
-sub layer_count {
- my ($self) = @_;
-
- return scalar @{$self->_heights};
-}
-
sub current_layer_height {
my ($self) = @_;
@@ -613,7 +596,7 @@ sub start_print {
# start with black
Slic3r::debugf "starting black projection\n";
$self->_layer_num(-1);
- $self->screen->project_layers(undef);
+ $self->screen->project_layer(undef);
$self->delay($self->config2->{settle_time}, sub {
$self->project_next_layer;
});
@@ -630,7 +613,7 @@ sub stop_print {
$self->is_printing(0);
$self->timer->Stop;
$self->_timer_cb(undef);
- $self->screen->project_layers(undef);
+ $self->screen->project_layer(undef);
}
sub print_completed {
@@ -652,19 +635,18 @@ sub print_completed {
sub is_projecting {
my ($self) = @_;
- return defined $self->screen->layers;
+ return defined $self->screen->layer;
}
sub project_layer {
my ($self, $layer_num) = @_;
- if (!defined $layer_num || $layer_num >= $self->layer_count) {
- $self->screen->project_layers(undef);
+ if (!defined $layer_num || $layer_num >= $self->_print->layer_count) {
+ $self->screen->project_layer(undef);
return;
}
- my @layers = @{ $self->_layers->{ $self->_heights->[$layer_num] } };
- $self->screen->project_layers([ @layers ]);
+ $self->screen->project_layer($self->_layers->[$layer_num], $layer_num);
}
sub project_next_layer {
@@ -672,7 +654,7 @@ sub project_next_layer {
$self->_layer_num($self->_layer_num + 1);
Slic3r::debugf "projecting layer %d\n", $self->_layer_num;
- if ($self->_layer_num >= $self->layer_count) {
+ if ($self->_layer_num >= $self->_print->layer_count) {
$self->print_completed;
return;
}
@@ -699,7 +681,7 @@ sub project_next_layer {
}
$self->delay($time, sub {
- $self->screen->project_layers(undef);
+ $self->screen->project_layer(undef);
$self->project_next_layer;
});
});
@@ -743,7 +725,7 @@ use List::Util qw(min);
use Slic3r::Geometry qw(X Y unscale scale);
use Slic3r::Geometry::Clipper qw(intersection_pl);
-__PACKAGE__->mk_accessors(qw(config config2 scaling_factor bed_origin layers));
+__PACKAGE__->mk_accessors(qw(config config2 scaling_factor bed_origin layer print layer_num));
sub new {
my ($class, $parent, $config, $config2) = @_;
@@ -803,10 +785,11 @@ sub _resize {
$self->Refresh;
}
-sub project_layers {
- my ($self, $layers) = @_;
+sub project_layer {
+ my ($self, $layer, $layer_num) = @_;
- $self->layers($layers);
+ $self->layer($layer);
+ $self->layer_num($layer_num);
$self->Refresh;
}
@@ -865,31 +848,46 @@ sub _repaint {
$dc->SetTextForeground(wxWHITE);
$dc->SetFont(Wx::Font->new(20, wxDEFAULT, wxNORMAL, wxNORMAL));
- $dc->DrawText("X", @{$self->unscaled_point_to_pixel([10, -2])});
- $dc->DrawText("Y", @{$self->unscaled_point_to_pixel([-2, 10])});
+
+ my $p = $self->unscaled_point_to_pixel([10, 0]);
+ $dc->DrawText("X", $p->[X], $p->[Y]);
+ $p = $self->unscaled_point_to_pixel([0, 10]);
+ $dc->DrawText("Y", $p->[X]-20, $p->[Y]-10);
}
}
- return if !defined $self->layers;
+ return if !defined $self->layer;
# get layers at this height
# draw layers
$dc->SetPen(Wx::Pen->new(wxWHITE, 1, wxSOLID));
- foreach my $layer (@{$self->layers}) {
- my @polygons = sort { $a->contains_point($b->first_point) ? -1 : 1 } map @$_, @{ $layer->slices };
- foreach my $copy (@{$layer->object->_shifted_copies}) {
- foreach my $polygon (@polygons) {
- $polygon = $polygon->clone;
- $polygon->translate(@$copy);
-
- if ($polygon->is_counter_clockwise) {
- $dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
- } else {
- $dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
- }
- $dc->DrawPolygon($self->scaled_points_to_pixel($polygon->pp), 0, 0);
- }
+
+ my @polygons = sort { $a->contains_point($b->first_point) ? -1 : 1 } map @$_, @{$self->layer};
+ foreach my $polygon (@polygons) {
+ if ($polygon->is_counter_clockwise) {
+ $dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
+ } else {
+ $dc->SetBrush(Wx::Brush->new(wxBLACK, wxSOLID));
}
+ $dc->DrawPolygon($self->scaled_points_to_pixel($polygon->pp), 0, 0);
+ }
+
+ # draw support material
+ my $sm_radius = $self->print->config->get_abs_value_over('support_material_extrusion_width', $self->print->config->layer_height)/2;
+ $dc->SetBrush(Wx::Brush->new(wxWHITE, wxSOLID));
+ foreach my $pillar (@{$self->print->sm_pillars}) {
+ next unless $pillar->{top_layer} >= $self->layer_num
+ && $pillar->{bottom_layer} <= $self->layer_num;
+
+ my $radius = min(
+ $sm_radius,
+ ($pillar->{top_layer} - $self->layer_num + 1) * $self->print->config->layer_height,
+ );
+
+ $dc->DrawCircle(
+ @{$self->scaled_points_to_pixel([$pillar->{point}])->[0]},
+ $radius * $self->scaling_factor,
+ );
}
}
diff --git a/xs/src/libslic3r/SLAPrint.cpp b/xs/src/libslic3r/SLAPrint.cpp
index a0a8c38a1f..a50859fbd7 100644
--- a/xs/src/libslic3r/SLAPrint.cpp
+++ b/xs/src/libslic3r/SLAPrint.cpp
@@ -10,19 +10,17 @@ SLAPrint::slice()
{
TriangleMesh mesh = this->model->mesh();
mesh.repair();
- mesh.mirror_x();
// align to origin taking raft into account
- BoundingBoxf3 bb = mesh.bounding_box();
+ this->bb = mesh.bounding_box();
if (this->config.raft_layers > 0) {
- bb.min.x -= this->config.raft_offset.value;
- bb.min.y -= this->config.raft_offset.value;
- bb.max.x += this->config.raft_offset.value;
- bb.max.y += this->config.raft_offset.value;
+ this->bb.min.x -= this->config.raft_offset.value;
+ this->bb.min.y -= this->config.raft_offset.value;
+ this->bb.max.x += this->config.raft_offset.value;
+ this->bb.max.y += this->config.raft_offset.value;
}
- mesh.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin
- bb.translate(-bb.min.x, -bb.min.y, -bb.min.z); // align to origin
- this->size = bb.size();
+ mesh.translate(0, 0, -bb.min.z);
+ this->bb.translate(0, 0, -bb.min.z);
// if we are generating a raft, first_layer_height will not affect mesh slicing
const float lh = this->config.layer_height.value;
@@ -68,9 +66,11 @@ SLAPrint::slice()
// generate points following the shape of each island
Points pillars_pos;
- const float spacing = scale_(this->config.support_material_spacing);
+ const coordf_t spacing = scale_(this->config.support_material_spacing);
+ const coordf_t radius = scale_(this->sm_pillars_radius());
for (ExPolygons::const_iterator it = overhangs.begin(); it != overhangs.end(); ++it) {
- for (float inset = -spacing/2; inset += spacing; ) {
+ // leave a radius/2 gap between pillars and contour to prevent lateral adhesion
+ for (float inset = radius * 1.5;; inset += spacing) {
// inset according to the configured spacing
Polygons curr = offset(*it, -inset);
if (curr.empty()) break;
@@ -134,7 +134,8 @@ SLAPrint::slice()
void
SLAPrint::write_svg(const std::string &outputfile) const
{
- double support_material_radius = this->config.support_material_extrusion_width.get_abs_value(this->config.layer_height)/2;
+ const Sizef3 size = this->bb.size();
+ const double support_material_radius = sm_pillars_radius();
FILE* f = fopen(outputfile.c_str(), "w");
fprintf(f,
@@ -142,7 +143,7 @@ SLAPrint::write_svg(const std::string &outputfile) const
"\n"
"\n");
}
+coordf_t
+SLAPrint::sm_pillars_radius() const
+{
+ coordf_t radius = this->config.support_material_extrusion_width.get_abs_value(this->config.support_material_spacing)/2;
+ if (radius == 0) radius = this->config.support_material_spacing / 3; // auto
+ return radius;
+}
+
}
diff --git a/xs/src/libslic3r/SLAPrint.hpp b/xs/src/libslic3r/SLAPrint.hpp
index 202eed8c2a..09664b386c 100644
--- a/xs/src/libslic3r/SLAPrint.hpp
+++ b/xs/src/libslic3r/SLAPrint.hpp
@@ -38,7 +38,9 @@ class SLAPrint
private:
Model* model;
- Sizef3 size;
+ BoundingBoxf3 bb;
+
+ coordf_t sm_pillars_radius() const;
};
}
diff --git a/xs/src/perlglue.cpp b/xs/src/perlglue.cpp
index 5bba8fcb6d..6852cb8ddf 100644
--- a/xs/src/perlglue.cpp
+++ b/xs/src/perlglue.cpp
@@ -51,6 +51,7 @@ REGISTER_CLASS(PrintRegionConfig, "Config::PrintRegion");
REGISTER_CLASS(GCodeConfig, "Config::GCode");
REGISTER_CLASS(PrintConfig, "Config::Print");
REGISTER_CLASS(FullPrintConfig, "Config::Full");
+REGISTER_CLASS(SLAPrint, "SLAPrint");
REGISTER_CLASS(Surface, "Surface");
REGISTER_CLASS(SurfaceCollection, "Surface::Collection");
REGISTER_CLASS(TriangleMesh, "TriangleMesh");
diff --git a/xs/xsp/SLAPrint.xsp b/xs/xsp/SLAPrint.xsp
new file mode 100644
index 0000000000..daecce38fa
--- /dev/null
+++ b/xs/xsp/SLAPrint.xsp
@@ -0,0 +1,61 @@
+%module{Slic3r::XS};
+
+%{
+#include
+#include "libslic3r/SLAPrint.hpp"
+%}
+
+%name{Slic3r::SLAPrint} class SLAPrint {
+ SLAPrint(Model* model);
+ ~SLAPrint();
+
+ void apply_config(DynamicPrintConfig* config)
+ %code%{ THIS->config.apply(*config, true); %};
+ void slice();
+ size_t layer_count()
+ %code{% RETVAL = THIS->layers.size(); %};
+
+ DynamicPrintConfig* config()
+ %code%{ RETVAL = new DynamicPrintConfig; RETVAL->apply(THIS->config); %};
+
+%{
+
+ExPolygons
+SLAPrint::slices(i)
+ size_t i;
+ CODE:
+ RETVAL = THIS->layers[i].slices;
+ OUTPUT:
+ RETVAL
+
+std::vector
+SLAPrint::heights()
+ CODE:
+ for (std::vector::const_iterator it = THIS->layers.begin();
+ it != THIS->layers.end();
+ ++it)
+ RETVAL.push_back(it->print_z);
+ OUTPUT:
+ RETVAL
+
+SV*
+SLAPrint::sm_pillars()
+ CODE:
+ AV* av = newAV();
+ for (std::vector::const_iterator it = THIS->sm_pillars.begin();
+ it != THIS->sm_pillars.end();
+ ++it)
+ {
+ HV* hv = newHV();
+ (void)hv_stores( hv, "top_layer", newSViv(it->top_layer) );
+ (void)hv_stores( hv, "bottom_layer", newSViv(it->bottom_layer) );
+ (void)hv_stores( hv, "point", perl_to_SV_clone_ref((Point)*it) );
+ av_push(av, newRV_noinc((SV*)hv));
+ }
+ RETVAL = newRV_noinc((SV*)av);
+ OUTPUT:
+ RETVAL
+
+%}
+
+};
diff --git a/xs/xsp/my.map b/xs/xsp/my.map
index 5f87f51c2c..b91ba47941 100644
--- a/xs/xsp/my.map
+++ b/xs/xsp/my.map
@@ -56,6 +56,10 @@ TriangleMesh* O_OBJECT_SLIC3R
Ref O_OBJECT_SLIC3R_T
Clone O_OBJECT_SLIC3R_T
+SLAPrint* O_OBJECT_SLIC3R
+Ref O_OBJECT_SLIC3R_T
+Clone O_OBJECT_SLIC3R_T
+
Point* O_OBJECT_SLIC3R
Ref O_OBJECT_SLIC3R_T
Clone O_OBJECT_SLIC3R_T
diff --git a/xs/xsp/typemap.xspt b/xs/xsp/typemap.xspt
index 89975c949a..87039c5648 100644
--- a/xs/xsp/typemap.xspt
+++ b/xs/xsp/typemap.xspt
@@ -192,6 +192,9 @@
%typemap{Ref}{simple};
%typemap{Clone}{simple};
%typemap{GLVertexArray*};
+%typemap{SLAPrint*};
+%typemap{Ref}{simple};
+%typemap{Clone}{simple};
%typemap{PrintRegionPtrs*};
%typemap{PrintObjectPtrs*};