From 93687c1491e8df144829804e7d7c142ca70d9f32 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 1 Jan 2015 12:37:38 +0100 Subject: [PATCH 01/16] Disable Growl notifications if register() fails - this prevents a deadlock on growler->notify() --- lib/Slic3r/GUI/Notifier.pm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/Slic3r/GUI/Notifier.pm b/lib/Slic3r/GUI/Notifier.pm index 78d31de3c..d347b74b3 100644 --- a/lib/Slic3r/GUI/Notifier.pm +++ b/lib/Slic3r/GUI/Notifier.pm @@ -14,6 +14,8 @@ sub BUILD { $self->growler(Growl::GNTP->new(AppName => 'Slic3r', AppIcon => $icon)); $self->growler->register([{Name => 'SKEIN_DONE', DisplayName => 'Slicing Done'}]); }; + # if register() fails (for example because of a timeout), disable growler at all + $self->growler(undef) if $@; } } From 69da8b09997c58c3f47d1e676fe578f68cbb96e9 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 1 Jan 2015 17:14:57 +0100 Subject: [PATCH 02/16] Use borderless buttons for save/delete in presets management (better look on wxOSX with 3.0.0) --- lib/Slic3r/GUI/Tab.pm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 6aac1c862..7f5df07a0 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -6,7 +6,7 @@ use utf8; use File::Basename qw(basename); use List::Util qw(first); use Wx qw(:bookctrl :dialog :keycode :icon :id :misc :panel :sizer :treectrl :window - wxTheApp); + :button wxTheApp); use Wx::Event qw(EVT_BUTTON EVT_CHOICE EVT_KEY_DOWN EVT_TREE_SEL_CHANGED); use base qw(Wx::Panel Class::Accessor); @@ -36,8 +36,10 @@ sub new { $self->{presets_choice}->SetFont($Slic3r::GUI::small_font); # buttons - $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", wxBITMAP_TYPE_PNG)); - $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG)); + $self->{btn_save_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/disk.png", wxBITMAP_TYPE_PNG), + wxDefaultPosition, [16,16], wxBORDER_NONE); + $self->{btn_delete_preset} = Wx::BitmapButton->new($self, -1, Wx::Bitmap->new("$Slic3r::var/delete.png", wxBITMAP_TYPE_PNG), + wxDefaultPosition, [16,16], wxBORDER_NONE); $self->{btn_save_preset}->SetToolTipString("Save current " . lc($self->title)); $self->{btn_delete_preset}->SetToolTipString("Delete this preset"); $self->{btn_delete_preset}->Disable; From d8be67c28bca470bcc0cb334d3073d122c296404 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 3 Jan 2015 15:03:53 +0100 Subject: [PATCH 03/16] Bugfix: Douglas-Peucker used perpendicular distance instead of shortest distance, thus clipping more than it should. #2474 --- xs/src/libslic3r/Geometry.cpp | 4 ++-- xs/src/libslic3r/MultiPoint.cpp | 1 + xs/src/libslic3r/Point.cpp | 24 ++++++++++++++++++++++++ xs/src/libslic3r/Point.hpp | 1 + xs/t/03_point.t | 19 +++++++++++++++++-- xs/t/09_polyline.t | 18 +++++++++++++++++- xs/xsp/Point.xsp | 2 ++ 7 files changed, 64 insertions(+), 5 deletions(-) diff --git a/xs/src/libslic3r/Geometry.cpp b/xs/src/libslic3r/Geometry.cpp index 996d3fe10..e30e73702 100644 --- a/xs/src/libslic3r/Geometry.cpp +++ b/xs/src/libslic3r/Geometry.cpp @@ -328,8 +328,8 @@ MedialAxis::is_valid_edge(const VD::edge_type& edge) const // our skeleton Point v0( edge.vertex0()->x(), edge.vertex0()->y() ); Point v1( edge.vertex1()->x(), edge.vertex1()->y() ); - double dist0 = v0.distance_to(segment1); - double dist1 = v1.distance_to(segment1); + double dist0 = v0.perp_distance_to(segment1); + double dist1 = v1.perp_distance_to(segment1); /* double diff = fabs(dist1 - dist0); diff --git a/xs/src/libslic3r/MultiPoint.cpp b/xs/src/libslic3r/MultiPoint.cpp index 24f210a99..e4944edca 100644 --- a/xs/src/libslic3r/MultiPoint.cpp +++ b/xs/src/libslic3r/MultiPoint.cpp @@ -90,6 +90,7 @@ MultiPoint::_douglas_peucker(const Points &points, const double tolerance) size_t index = 0; Line full(points.front(), points.back()); for (Points::const_iterator it = points.begin() + 1; it != points.end(); ++it) { + // we use shortest distance, not perpendicular distance double d = it->distance_to(full); if (d > dmax) { index = it - points.begin(); diff --git a/xs/src/libslic3r/Point.cpp b/xs/src/libslic3r/Point.cpp index 77f4224d5..d40a8efc7 100644 --- a/xs/src/libslic3r/Point.cpp +++ b/xs/src/libslic3r/Point.cpp @@ -1,6 +1,7 @@ #include "Point.hpp" #include "Line.hpp" #include "MultiPoint.hpp" +#include #include #include @@ -130,8 +131,31 @@ Point::distance_to(const Point &point) const return sqrt(dx*dx + dy*dy); } +/* distance to the closest point of line */ double Point::distance_to(const Line &line) const +{ + const double dx = line.b.x - line.a.x; + const double dy = line.b.y - line.a.y; + + const double l2 = dx*dx + dy*dy; // avoid a sqrt + if (l2 == 0.0) return this->distance_to(line.a); // line.a == line.b case + + // Consider the line extending the segment, parameterized as line.a + t (line.b - line.a). + // We find projection of this point onto the line. + // It falls where t = [(this-line.a) . (line.b-line.a)] / |line.b-line.a|^2 + const double t = ((this->x - line.a.x) * dx + (this->y - line.a.y) * dy) / l2; + if (t < 0.0) return this->distance_to(line.a); // beyond the 'a' end of the segment + else if (t > 1.0) return this->distance_to(line.b); // beyond the 'b' end of the segment + Point projection( + line.a.x + t * dx, + line.a.y + t * dy + ); + return this->distance_to(projection); +} + +double +Point::perp_distance_to(const Line &line) const { if (line.a.coincides_with(line.b)) return this->distance_to(line.a); diff --git a/xs/src/libslic3r/Point.hpp b/xs/src/libslic3r/Point.hpp index 368fb1af8..6fa216405 100644 --- a/xs/src/libslic3r/Point.hpp +++ b/xs/src/libslic3r/Point.hpp @@ -48,6 +48,7 @@ class Point bool nearest_point(const Points &points, Point* point) const; double distance_to(const Point &point) const; double distance_to(const Line &line) const; + double perp_distance_to(const Line &line) const; double ccw(const Point &p1, const Point &p2) const; double ccw(const Line &line) const; double ccw_angle(const Point &p1, const Point &p2) const; diff --git a/xs/t/03_point.t b/xs/t/03_point.t index 0ec9df552..d983fafc9 100644 --- a/xs/t/03_point.t +++ b/xs/t/03_point.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 15; +use Test::More tests => 22; my $point = Slic3r::Point->new(10, 15); is_deeply [ @$point ], [10, 15], 'point roundtrip'; @@ -30,13 +30,28 @@ ok !$point->coincides_with($point2), 'coincides_with'; ok $nearest->coincides_with($point2), 'nearest_point'; } +{ + my $line = Slic3r::Line->new([0,0], [100,0]); + is +Slic3r::Point->new(0,0)->distance_to_line($line), 0, 'distance_to_line()'; + is +Slic3r::Point->new(100,0)->distance_to_line($line), 0, 'distance_to_line()'; + is +Slic3r::Point->new(50,0)->distance_to_line($line), 0, 'distance_to_line()'; + is +Slic3r::Point->new(150,0)->distance_to_line($line), 50, 'distance_to_line()'; + is +Slic3r::Point->new(0,50)->distance_to_line($line), 50, 'distance_to_line()'; + is +Slic3r::Point->new(50,50)->distance_to_line($line), 50, 'distance_to_line()'; +} + +{ + my $line = Slic3r::Line->new([50,50], [125,-25]); + is +Slic3r::Point->new(100,0)->distance_to_line($line), 0, 'distance_to_line()'; +} + { my $line = Slic3r::Line->new( [18335846,18335845], [18335846,1664160], ); $point = Slic3r::Point->new(1664161,18335848); - is $point->distance_to_line($line), 16671685, 'distance_to_line() does not overflow'; + is $point->perp_distance_to_line($line), 16671685, 'perp_distance_to_line() does not overflow'; } { diff --git a/xs/t/09_polyline.t b/xs/t/09_polyline.t index 5ce8d87cb..99077aad3 100644 --- a/xs/t/09_polyline.t +++ b/xs/t/09_polyline.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 14; +use Test::More tests => 16; my $points = [ [100, 100], @@ -34,6 +34,14 @@ is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline'; ok abs($polyline->length - ($len-($len/3))) < 1, 'clip_end'; } +{ + my $polyline = Slic3r::Polyline->new( + [0,0], [20,0], [50,0], [80,0], [100,0], + ); + $polyline->simplify(2); + is_deeply $polyline->pp, [ [0,0], [100,0] ], 'Douglas-Peucker'; +} + { my $polyline = Slic3r::Polyline->new( [0,0], [50,50], [100,0], [125,-25], [150,50], @@ -42,6 +50,14 @@ is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline'; is_deeply $polyline->pp, [ [0, 0], [50, 50], [125, -25], [150, 50] ], 'Douglas-Peucker'; } +{ + my $polyline = Slic3r::Polyline->new( + [0,0], [100,0], [50,10], + ); + $polyline->simplify(25); + is_deeply $polyline->pp, [ [0,0], [100,0], [50,10] ], 'Douglas-Peucker uses shortest distance instead of perpendicular distance'; +} + { my $polyline = Slic3r::Polyline->new(@$points); is $polyline->length, 100*2, 'length'; diff --git a/xs/xsp/Point.xsp b/xs/xsp/Point.xsp index e45c41213..871911239 100644 --- a/xs/xsp/Point.xsp +++ b/xs/xsp/Point.xsp @@ -29,6 +29,8 @@ %code{% RETVAL = THIS->distance_to(*point); %}; double distance_to_line(Line* line) %code{% RETVAL = THIS->distance_to(*line); %}; + double perp_distance_to_line(Line* line) + %code{% RETVAL = THIS->perp_distance_to(*line); %}; double ccw(Point* p1, Point* p2) %code{% RETVAL = THIS->ccw(*p1, *p2); %}; double ccw_angle(Point* p1, Point* p2) From 73d45dd851ffaa35d419376f8546923a6201ab80 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 3 Jan 2015 15:11:33 +0100 Subject: [PATCH 04/16] Minor cleanup of Layer::Region::_fill_gaps() --- lib/Slic3r/Layer/Region.pm | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index f48282ee3..8e3db00e5 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -412,6 +412,12 @@ sub _fill_gaps { offset2([ map @$_, @$gaps ], -$max/2, +$max/2), 1, ); + my @polylines = map @{$_->medial_axis($max, $min/2)}, @$this; + + return if !@polylines; + + Slic3r::debugf " %d gaps filled with extrusion width = %s\n", scalar @$this, $w + if @$this; my $flow = $self->flow(FLOW_ROLE_SOLID_INFILL, 0, $w); my %path_args = ( @@ -420,26 +426,23 @@ sub _fill_gaps { width => $flow->width, height => $self->height, ); - my @polylines = map @{$_->medial_axis($max, $min/2)}, @$this; - Slic3r::debugf " %d gaps filled with extrusion width = %s\n", scalar @$this, $w - if @$this; - - for my $i (0..$#polylines) { - if ($polylines[$i]->isa('Slic3r::Polygon')) { - my $loop = Slic3r::ExtrusionLoop->new; - $loop->append(Slic3r::ExtrusionPath->new(polyline => $polylines[$i]->split_at_first_point, %path_args)); - $polylines[$i] = $loop; - } elsif ($polylines[$i]->is_valid && $polylines[$i]->first_point->coincides_with($polylines[$i]->last_point)) { + my @entities = (); + foreach my $polyline (@polylines) { + #if ($polylines[$i]->isa('Slic3r::Polygon')) { + # my $loop = Slic3r::ExtrusionLoop->new; + # $loop->append(Slic3r::ExtrusionPath->new(polyline => $polylines[$i]->split_at_first_point, %path_args)); + # $polylines[$i] = $loop; + if ($polyline->is_valid && $polyline->first_point->coincides_with($polyline->last_point)) { # since medial_axis() now returns only Polyline objects, detect loops here - my $loop = Slic3r::ExtrusionLoop->new; - $loop->append(Slic3r::ExtrusionPath->new(polyline => $polylines[$i], %path_args)); - $polylines[$i] = $loop; + push @entities, my $loop = Slic3r::ExtrusionLoop->new; + $loop->append(Slic3r::ExtrusionPath->new(polyline => $polyline, %path_args)); } else { - $polylines[$i] = Slic3r::ExtrusionPath->new(polyline => $polylines[$i], %path_args); + push @entities, Slic3r::ExtrusionPath->new(polyline => $polyline, %path_args); } } - return @polylines; + + return @entities; } sub prepare_fill_surfaces { From d46d9079a3c3105dc1ceb2ed060d7a0abeadd00f Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 3 Jan 2015 15:41:54 +0100 Subject: [PATCH 05/16] Fixed test after recent change of distance_to_line() semantics --- t/geometry.t | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/t/geometry.t b/t/geometry.t index d85c8bbcf..cec0ff320 100644 --- a/t/geometry.t +++ b/t/geometry.t @@ -182,7 +182,7 @@ my $polygons = [ { my $line = Slic3r::Line->new([0, 0], [20, 0]); is +Slic3r::Point->new(10, 10)->distance_to_line($line), 10, 'distance_to'; - is +Slic3r::Point->new(50, 10)->distance_to_line($line), 10, 'distance_to'; + is +Slic3r::Point->new(50, 0)->distance_to_line($line), 30, 'distance_to'; is +Slic3r::Point->new(0, 0)->distance_to_line($line), 0, 'distance_to'; is +Slic3r::Point->new(20, 0)->distance_to_line($line), 0, 'distance_to'; is +Slic3r::Point->new(10, 0)->distance_to_line($line), 0, 'distance_to'; From 3b09377a43c29b57aa7c3fde0d58b4a3db808993 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sat, 3 Jan 2015 15:48:53 +0100 Subject: [PATCH 06/16] Export single object as STL from its contextual menu. #2479 --- lib/Slic3r/GUI/MainFrame.pm | 4 ++-- lib/Slic3r/GUI/Plater.pm | 17 +++++++++++++++++ 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/MainFrame.pm b/lib/Slic3r/GUI/MainFrame.pm index 4cd4db706..b873177f3 100644 --- a/lib/Slic3r/GUI/MainFrame.pm +++ b/lib/Slic3r/GUI/MainFrame.pm @@ -201,10 +201,10 @@ sub _init_menubar { $self->_append_menu_item($self->{plater_menu}, "Export G-code...", 'Export current plate as G-code', sub { $plater->export_gcode; }); - $self->_append_menu_item($self->{plater_menu}, "Export STL...", 'Export current plate as STL', sub { + $self->_append_menu_item($self->{plater_menu}, "Export plate as STL...", 'Export current plate as STL', sub { $plater->export_stl; }); - $self->_append_menu_item($self->{plater_menu}, "Export AMF...", 'Export current plate as AMF', sub { + $self->_append_menu_item($self->{plater_menu}, "Export plate as AMF...", 'Export current plate as AMF', sub { $plater->export_amf; }); diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 2517cd893..82b46adcf 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1124,6 +1124,19 @@ sub export_stl { Slic3r::thread_cleanup() if $Slic3r::have_threads; } +sub export_object_stl { + my $self = shift; + + my ($obj_idx, $object) = $self->selected_object; + return if !defined $obj_idx; + + my $model_object = $self->{model}->objects->[$obj_idx]; + + my $output_file = $self->_get_export_file('STL') or return; + Slic3r::Format::STL->write_file($output_file, $model_object->mesh, binary => 1); + $self->statusbar->SetStatusText("STL file exported to $output_file"); +} + sub export_amf { my $self = shift; @@ -1543,6 +1556,10 @@ sub object_menu { $frame->_append_menu_item($menu, "Settings…", 'Open the object editor dialog', sub { $self->object_settings_dialog; }); + $menu->AppendSeparator(); + $frame->_append_menu_item($menu, "Export object as STL…", 'Export this single object as STL file', sub { + $self->export_object_stl; + }); return $menu; } From 504cbd89dba9f210c3a27682bdd9b8dac11b8032 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 11:46:58 +0100 Subject: [PATCH 07/16] Fix bug in admesh code that causes random binary STL files not to be read correctly on Windows. #2461 --- xs/src/admesh/stlinit.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/xs/src/admesh/stlinit.c b/xs/src/admesh/stlinit.c index 67c43e86f..a7ab2b6d2 100644 --- a/xs/src/admesh/stlinit.c +++ b/xs/src/admesh/stlinit.c @@ -77,8 +77,8 @@ stl_count_facets(stl_file *stl, char *file) { if (stl->error) return; - /* Open the file */ - stl->fp = fopen(file, "r"); + /* Open the file in binary mode first */ + stl->fp = fopen(file, "rb"); if(stl->fp == NULL) { error_msg = (char*) malloc(81 + strlen(file)); /* Allow 80 chars+file size for message */ @@ -104,9 +104,6 @@ stl_count_facets(stl_file *stl, char *file) { for(s = 0; s < sizeof(chtest); s++) { if(chtest[s] > 127) { stl->stats.type = binary; - /* close and reopen with binary flag (needed on Windows) */ - fclose(stl->fp); - stl->fp = fopen(file, "rb"); break; } } @@ -137,6 +134,9 @@ stl_count_facets(stl_file *stl, char *file) { } /* Otherwise, if the .STL file is ASCII, then do the following */ else { + /* Reopen the file in text mode (for getting correct newlines on Windows) */ + freopen(file, "r", stl->fp); + /* Find the number of facets */ j = 0; for(i = 0; i < file_size ; i++) { From 510b472b519509db77fa98bd46f48410161341a1 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 13:11:05 +0100 Subject: [PATCH 08/16] Gradient background for 3D view --- lib/Slic3r/GUI/PreviewCanvas.pm | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm index f48240392..18fe75f8d 100644 --- a/lib/Slic3r/GUI/PreviewCanvas.pm +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -28,6 +28,7 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init bed_shape bed_triangles bed_grid_lines + background origin _mouse_pos _hover_volume_idx @@ -60,6 +61,7 @@ sub new { my $self = $class->SUPER::new($parent, -1, Wx::wxDefaultPosition, Wx::wxDefaultSize, 0, "", [WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 16, 0]); + $self->background(1); $self->_quat((0, 0, 0, 1)); $self->_stheta(45); $self->_sphi(45); @@ -580,7 +582,7 @@ sub Resize { return unless $self->GetContext; $self->_dirty(0); - + $self->SetCurrent($self->GetContext); glViewport(0, 0, $x, $y); @@ -693,6 +695,30 @@ sub Render { glFinish(); glEnable(GL_LIGHTING); } + + # draw fixed background + if ($self->background) { + glPushMatrix(); + glLoadIdentity(); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + + glBegin(GL_QUADS); + glColor3f(0.0,0.0,0.0); + glVertex2f(-1.0,-1.0); + glVertex2f(1,-1.0); + glColor3f(10/255,98/255,144/255); + glVertex2f(1, 1); + glVertex2f(-1.0, 1); + glEnd(); + glPopMatrix(); + + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + } + # draw objects $self->draw_volumes; From 694268d6c71243812f87818c49ae38824ae7635e Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 13:17:20 +0100 Subject: [PATCH 09/16] Fix incomplete grid in 3D preview --- lib/Slic3r/GUI/PreviewCanvas.pm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm index 18fe75f8d..fc2763ff2 100644 --- a/lib/Slic3r/GUI/PreviewCanvas.pm +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -8,7 +8,7 @@ use OpenGL qw(:glconstants :glfunctions :glufunctions :gluconstants); use base qw(Wx::GLCanvas Class::Accessor); use Math::Trig qw(asin); use List::Util qw(reduce min max first); -use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scale unscale); +use Slic3r::Geometry qw(X Y Z MIN MAX triangle_normal normalize deg2rad tan scale unscale scaled_epsilon); use Slic3r::Geometry::Clipper qw(offset_ex intersection_pl); use Wx::GLCanvas qw(:all); @@ -329,7 +329,9 @@ sub set_bed_shape { for (my $y = $bed_bb->y_min; $y <= $bed_bb->y_max; $y += scale 10) { push @lines, Slic3r::Polyline->new([$bed_bb->x_min,$y], [$bed_bb->x_max,$y]); } - @lines = @{intersection_pl(\@lines, [ @$expolygon ])}; + # clip with a slightly grown expolygon because our lines lay on the contours and + # may get erroneously clipped + @lines = @{intersection_pl(\@lines, [ @{$expolygon->offset(+scaled_epsilon)} ])}; my @points = (); foreach my $polyline (@lines) { push @points, map {+ unscale($_->x), unscale($_->y), GROUND_Z } @$polyline; #)) From 84c30c1cf59d6a9e3d6c61ed5235dde8aca37a79 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 13:32:00 +0100 Subject: [PATCH 10/16] Nicer bed appearance --- lib/Slic3r/GUI/PreviewCanvas.pm | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm index fc2763ff2..4f856b523 100644 --- a/lib/Slic3r/GUI/PreviewCanvas.pm +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -42,7 +42,7 @@ __PACKAGE__->mk_accessors( qw(_quat _dirty init use constant TRACKBALLSIZE => 0.8; use constant TURNTABLE_MODE => 1; -use constant GROUND_Z => 0.02; +use constant GROUND_Z => -0.02; use constant SELECTED_COLOR => [0,1,0,1]; use constant HOVER_COLOR => [0.8,0.8,0,1]; use constant COLORS => [ [1,1,0], [1,0.5,0.5], [0.5,1,0.5], [0.5,0.5,1] ]; @@ -721,9 +721,6 @@ sub Render { glPopMatrix(); } - # draw objects - $self->draw_volumes; - # draw ground and axes glDisable(GL_LIGHTING); my $z0 = 0; @@ -732,26 +729,29 @@ sub Render { # draw ground my $ground_z = GROUND_Z; if ($self->bed_triangles) { + glDisable(GL_DEPTH_TEST); + glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnableClientState(GL_VERTEX_ARRAY); - glColor4f(0.6, 0.7, 0.5, 0.3); + glColor4f(0.8, 0.6, 0.5, 0.4); glNormal3d(0,0,1); glVertexPointer_p(3, $self->bed_triangles); glDrawArrays(GL_TRIANGLES, 0, $self->bed_triangles->elements / 3); glDisableClientState(GL_VERTEX_ARRAY); - glDisable(GL_BLEND); + glEnable(GL_DEPTH_TEST); # draw grid - glTranslatef(0, 0, 0.02); glLineWidth(3); - glColor3f(0.95, 0.95, 0.95); + glColor4f(0.2, 0.2, 0.2, 0.4); glEnableClientState(GL_VERTEX_ARRAY); glVertexPointer_p(3, $self->bed_grid_lines); glDrawArrays(GL_LINES, 0, $self->bed_grid_lines->elements / 3); glDisableClientState(GL_VERTEX_ARRAY); + + glDisable(GL_BLEND); } my $volumes_bb = $self->volumes_bounding_box; @@ -802,6 +802,9 @@ sub Render { glEnable(GL_LIGHTING); + # draw objects + $self->draw_volumes; + glFlush(); $self->SwapBuffers(); From 6438bfc3cb618ed061dfeea2e3b0fbffdc7f32c5 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 13:36:14 +0100 Subject: [PATCH 11/16] Draw bed contours with grid linewidth --- lib/Slic3r/GUI/PreviewCanvas.pm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/Slic3r/GUI/PreviewCanvas.pm b/lib/Slic3r/GUI/PreviewCanvas.pm index 4f856b523..ffa7c61b7 100644 --- a/lib/Slic3r/GUI/PreviewCanvas.pm +++ b/lib/Slic3r/GUI/PreviewCanvas.pm @@ -332,6 +332,12 @@ sub set_bed_shape { # clip with a slightly grown expolygon because our lines lay on the contours and # may get erroneously clipped @lines = @{intersection_pl(\@lines, [ @{$expolygon->offset(+scaled_epsilon)} ])}; + + # append bed contours + foreach my $line (map @{$_->lines}, @$expolygon) { + push @lines, $line->as_polyline; + } + my @points = (); foreach my $polyline (@lines) { push @points, map {+ unscale($_->x), unscale($_->y), GROUND_Z } @$polyline; #)) From af1b705563ae2433b32868c19cb0dfbd3dab4130 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 15:30:31 +0100 Subject: [PATCH 12/16] Increase HTTP timeout for Octoprint upload. #2481 --- lib/Slic3r/GUI/Plater.pm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 82b46adcf..63f1685b8 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1088,7 +1088,7 @@ sub send_gcode { $self->statusbar->StartBusy; my $ua = LWP::UserAgent->new; - $ua->timeout(10); + $ua->timeout(180); my $res = $ua->post( "http://" . $self->{config}->octoprint_host . "/api/files/local", From 0775960b9f87cc573b0f2f5d6cdaf043fedc0d96 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 19:20:13 +0100 Subject: [PATCH 13/16] Minor reordering of options --- lib/Slic3r/GUI/Tab.pm | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/Slic3r/GUI/Tab.pm b/lib/Slic3r/GUI/Tab.pm index 7f5df07a0..d3e7ccd35 100644 --- a/lib/Slic3r/GUI/Tab.pm +++ b/lib/Slic3r/GUI/Tab.pm @@ -973,11 +973,6 @@ sub build { $optgroup->append_single_option_line('z_offset'); } - { - my $optgroup = $page->new_optgroup('Firmware'); - $optgroup->append_single_option_line('gcode_flavor'); - $optgroup->append_single_option_line('use_relative_e_distances'); - } { my $optgroup = $page->new_optgroup('Capabilities'); { @@ -1038,6 +1033,11 @@ sub build { $optgroup->append_line($host_line); $optgroup->append_single_option_line('octoprint_apikey'); } + { + my $optgroup = $page->new_optgroup('Firmware'); + $optgroup->append_single_option_line('gcode_flavor'); + $optgroup->append_single_option_line('use_relative_e_distances'); + } { my $optgroup = $page->new_optgroup('Advanced'); $optgroup->append_single_option_line('use_firmware_retraction'); From 6c7c089fc4d88166c25a69a054fc79273e953313 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 19:29:34 +0100 Subject: [PATCH 14/16] Disable the "Export G-code" and "Send to print" buttons when other actions are pending --- lib/Slic3r/GUI/Plater.pm | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/lib/Slic3r/GUI/Plater.pm b/lib/Slic3r/GUI/Plater.pm index 63f1685b8..951a4f30b 100644 --- a/lib/Slic3r/GUI/Plater.pm +++ b/lib/Slic3r/GUI/Plater.pm @@ -1001,6 +1001,9 @@ sub export_gcode { $self->on_export_completed($result); } + # this updates buttons status + $self->object_list_changed; + return $self->{export_gcode_output_file}; } @@ -1080,6 +1083,9 @@ sub on_export_completed { $self->send_gcode if $send_gcode; $self->{send_gcode_file} = undef; + + # this updates buttons status + $self->object_list_changed; } sub send_gcode { @@ -1377,6 +1383,11 @@ sub object_list_changed { $self->{"btn_$_"}->$method for grep $self->{"btn_$_"}, qw(reset arrange export_gcode export_stl send_gcode); + if ($self->{export_gcode_output_file} || $self->{send_gcode_file}) { + $self->{btn_export_gcode}->Disable; + $self->{btn_send_gcode}->Disable; + } + if ($self->{htoolbar}) { $self->{htoolbar}->EnableTool($_, $have_objects) for (TB_RESET, TB_ARRANGE); From 92e896c4d1513dd3354cc6a05c98d158e4bca6cd Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 19:32:05 +0100 Subject: [PATCH 15/16] Prettify infill pattern labels --- xs/src/libslic3r/PrintConfig.cpp | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index 2ca83c15e..ecd8e88ba 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -126,11 +126,11 @@ PrintConfigDef::build_def() { Options["external_fill_pattern"].enum_values.push_back("hilbertcurve"); Options["external_fill_pattern"].enum_values.push_back("archimedeanchords"); Options["external_fill_pattern"].enum_values.push_back("octagramspiral"); - Options["external_fill_pattern"].enum_labels.push_back("rectilinear"); - Options["external_fill_pattern"].enum_labels.push_back("concentric"); - Options["external_fill_pattern"].enum_labels.push_back("hilbertcurve (slow)"); - Options["external_fill_pattern"].enum_labels.push_back("archimedeanchords (slow)"); - Options["external_fill_pattern"].enum_labels.push_back("octagramspiral (slow)"); + Options["external_fill_pattern"].enum_labels.push_back("Rectilinear"); + Options["external_fill_pattern"].enum_labels.push_back("Concentric"); + Options["external_fill_pattern"].enum_labels.push_back("Hilbert Curve"); + Options["external_fill_pattern"].enum_labels.push_back("Archimedean Chords"); + Options["external_fill_pattern"].enum_labels.push_back("Octagram Spiral"); Options["external_fill_pattern"].aliases.push_back("solid_fill_pattern"); Options["external_perimeter_extrusion_width"].type = coFloatOrPercent; @@ -293,14 +293,14 @@ PrintConfigDef::build_def() { Options["fill_pattern"].enum_values.push_back("hilbertcurve"); Options["fill_pattern"].enum_values.push_back("archimedeanchords"); Options["fill_pattern"].enum_values.push_back("octagramspiral"); - Options["fill_pattern"].enum_labels.push_back("rectilinear"); - Options["fill_pattern"].enum_labels.push_back("line"); - Options["fill_pattern"].enum_labels.push_back("concentric"); - Options["fill_pattern"].enum_labels.push_back("honeycomb"); - Options["fill_pattern"].enum_labels.push_back("3D honeycomb"); - Options["fill_pattern"].enum_labels.push_back("hilbertcurve"); - Options["fill_pattern"].enum_labels.push_back("archimedeanchords"); - Options["fill_pattern"].enum_labels.push_back("octagramspiral"); + Options["fill_pattern"].enum_labels.push_back("Rectilinear"); + Options["fill_pattern"].enum_labels.push_back("Line"); + Options["fill_pattern"].enum_labels.push_back("Concentric"); + Options["fill_pattern"].enum_labels.push_back("Honeycomb"); + Options["fill_pattern"].enum_labels.push_back("3D Honeycomb"); + Options["fill_pattern"].enum_labels.push_back("Hilbert Curve"); + Options["fill_pattern"].enum_labels.push_back("Archimedean Chords"); + Options["fill_pattern"].enum_labels.push_back("Octagram Spiral"); Options["first_layer_acceleration"].type = coFloat; Options["first_layer_acceleration"].label = "First layer"; From a6f3e6bfdb22379a3cc793056947e3ac74c885c6 Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Sun, 4 Jan 2015 19:32:59 +0100 Subject: [PATCH 16/16] Mark Vibration Limit as deprecated. #2483 --- xs/src/libslic3r/PrintConfig.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/xs/src/libslic3r/PrintConfig.cpp b/xs/src/libslic3r/PrintConfig.cpp index ecd8e88ba..e4847a570 100644 --- a/xs/src/libslic3r/PrintConfig.cpp +++ b/xs/src/libslic3r/PrintConfig.cpp @@ -946,7 +946,7 @@ PrintConfigDef::build_def() { Options["use_relative_e_distances"].cli = "use-relative-e-distances!"; Options["vibration_limit"].type = coFloat; - Options["vibration_limit"].label = "Vibration limit"; + Options["vibration_limit"].label = "Vibration limit (deprecated)"; Options["vibration_limit"].tooltip = "This experimental option will slow down those moves hitting the configured frequency limit. The purpose of limiting vibrations is to avoid mechanical resonance. Set zero to disable."; Options["vibration_limit"].sidetext = "Hz"; Options["vibration_limit"].cli = "vibration-limit=f";