From 5d6fd7f4d95e1f442fb5fce78b436204d7974fda Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Thu, 29 Aug 2013 01:36:42 +0200 Subject: [PATCH] Optimizations for better usage of XS code --- lib/Slic3r/ExPolygon.pm | 2 +- lib/Slic3r/ExtrusionLoop.pm | 5 ----- lib/Slic3r/ExtrusionPath.pm | 5 ----- lib/Slic3r/ExtrusionPath/Collection.pm | 2 +- lib/Slic3r/Fill.pm | 2 +- lib/Slic3r/Fill/Honeycomb.pm | 4 ++-- lib/Slic3r/Fill/Rectilinear.pm | 13 +++++++------ lib/Slic3r/GCode.pm | 19 ++++++++++++------- lib/Slic3r/GCode/MotionPlanner.pm | 4 ++-- lib/Slic3r/Layer/Region.pm | 4 ++-- lib/Slic3r/Line.pm | 8 -------- lib/Slic3r/Polyline.pm | 2 +- xs/src/ExtrusionEntity.cpp | 6 ++++++ xs/src/ExtrusionEntity.hpp | 1 + xs/src/Line.cpp | 6 ++++++ xs/src/Line.hpp | 1 + xs/src/MultiPoint.cpp | 6 ++++++ xs/src/MultiPoint.hpp | 1 + xs/t/09_polyline.t | 5 ++++- xs/xsp/ExtrusionPath.xsp | 2 ++ xs/xsp/Line.xsp | 2 ++ xs/xsp/Polyline.xsp | 10 ++++++++++ 22 files changed, 68 insertions(+), 42 deletions(-) diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index e4dd15266..2fe281e47 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -210,7 +210,7 @@ sub medial_axis { # cleanup $polyline = Slic3r::Geometry::douglas_peucker($polyline, $width / 7); - if (Slic3r::Geometry::same_point($polyline->[0], $polyline->[-1])) { + if (Slic3r::Geometry::same_point($polyline->first_point, $polyline->last_point)) { next if @$polyline == 2; push @result, Slic3r::Polygon->new(@$polyline[0..$#$polyline-1]); } else { diff --git a/lib/Slic3r/ExtrusionLoop.pm b/lib/Slic3r/ExtrusionLoop.pm index 4fb5ce79c..2cf90c8d5 100644 --- a/lib/Slic3r/ExtrusionLoop.pm +++ b/lib/Slic3r/ExtrusionLoop.pm @@ -13,11 +13,6 @@ sub split_at { ); } -sub first_point { - my $self = shift; - return $self->polygon->[0]; -} - sub make_counter_clockwise { my $self = shift; if (!$self->polygon->is_counter_clockwise) { diff --git a/lib/Slic3r/ExtrusionPath.pm b/lib/Slic3r/ExtrusionPath.pm index 0740f750f..03e35cf68 100644 --- a/lib/Slic3r/ExtrusionPath.pm +++ b/lib/Slic3r/ExtrusionPath.pm @@ -65,11 +65,6 @@ sub points { return $self->polyline; } -sub last_point { - my $self = shift; - return $self->polyline->[-1]; -} - sub is_perimeter { my $self = shift; return $self->role == EXTR_ROLE_PERIMETER diff --git a/lib/Slic3r/ExtrusionPath/Collection.pm b/lib/Slic3r/ExtrusionPath/Collection.pm index e144941e6..3be58d306 100644 --- a/lib/Slic3r/ExtrusionPath/Collection.pm +++ b/lib/Slic3r/ExtrusionPath/Collection.pm @@ -33,7 +33,7 @@ sub chained_path { } push @paths, splice @my_paths, $path_index, 1; splice @$endpoints, $path_index*2, 2; - $start_near = $paths[-1][-1]; + $start_near = $paths[-1]->last_point; } return @paths; } diff --git a/lib/Slic3r/Fill.pm b/lib/Slic3r/Fill.pm index cc1485ea3..9a6be280b 100644 --- a/lib/Slic3r/Fill.pm +++ b/lib/Slic3r/Fill.pm @@ -194,7 +194,7 @@ sub make_fill { flow_spacing => $params->{flow_spacing} || (warn "Warning: no flow_spacing was returned by the infill engine, please report this to the developer\n"), ), @polylines, ); - push @fills_ordering_points, $polylines[0][0]; + push @fills_ordering_points, $polylines[0]->first_point; } # add thin fill regions diff --git a/lib/Slic3r/Fill/Honeycomb.pm b/lib/Slic3r/Fill/Honeycomb.pm index a2a1b0580..0f91f5ae2 100644 --- a/lib/Slic3r/Fill/Honeycomb.pm +++ b/lib/Slic3r/Fill/Honeycomb.pm @@ -101,10 +101,10 @@ sub fill_surface { foreach my $path ($collection->chained_path) { if (@paths) { # distance between first point of this path and last point of last path - my $distance = $paths[-1][-1]->distance_to($path->[0]); + my $distance = $paths[-1]->last_point->distance_to($path->first_point); if ($distance <= $m->{hex_width}) { - $paths[-1]->append(@$path); + $paths[-1]->append_polyline($path); next; } } diff --git a/lib/Slic3r/Fill/Rectilinear.pm b/lib/Slic3r/Fill/Rectilinear.pm index 161b8db63..259df5a05 100644 --- a/lib/Slic3r/Fill/Rectilinear.pm +++ b/lib/Slic3r/Fill/Rectilinear.pm @@ -42,7 +42,7 @@ sub fill_surface { my $x_max = $bounding_box->x_max + scaled_epsilon; my @vertical_lines = (); while ($x <= $x_max) { - my $vertical_line = Slic3r::Line->new([$x, $bounding_box->y_max], [$x, $bounding_box->y_min]); + my $vertical_line = [ [$x, $bounding_box->y_max], [$x, $bounding_box->y_min] ]; if ($is_line_pattern && $i % 2) { $vertical_line->[A][X] += $line_oscillation; $vertical_line->[B][X] -= $line_oscillation; @@ -60,7 +60,7 @@ sub fill_surface { my @polylines = map Slic3r::Polyline->new(@$_), @{ Boost::Geometry::Utils::multi_polygon_multi_linestring_intersection( [ map $_->pp, @{$expolygon->offset_ex($line_spacing*0.05)} ], - [ map $_->pp, @vertical_lines ], + [ @vertical_lines ], ) }; # connect lines @@ -82,13 +82,14 @@ sub fill_surface { foreach my $polyline ($collection->chained_path) { if (@polylines) { - my $last_point = $polylines[-1][-1]->pp; - my @distance = map abs($polyline->[0][$_] - $last_point->[$_]), (X,Y); + my $first_point = $polyline->first_point; + my $last_point = $polylines[-1]->last_point; + my @distance = map abs($first_point->$_ - $last_point->$_), qw(x y); # TODO: we should also check that both points are on a fill_boundary to avoid # connecting paths on the boundaries of internal regions - if ($can_connect->(@distance) && $expolygon_off->encloses_line(Slic3r::Line->new($last_point, $polyline->[0]), $tolerance)) { - $polylines[-1]->append(@$polyline); + if ($can_connect->(@distance) && $expolygon_off->encloses_line(Slic3r::Line->new($last_point, $first_point), $tolerance)) { + $polylines[-1]->append_polyline($polyline); next; } } diff --git a/lib/Slic3r/GCode.pm b/lib/Slic3r/GCode.pm index 054b7db30..e32121409 100644 --- a/lib/Slic3r/GCode.pm +++ b/lib/Slic3r/GCode.pm @@ -274,9 +274,11 @@ sub extrude_path { # go to first point of extrusion path my $gcode = ""; - my $first_point = $path->first_point; - $gcode .= $self->travel_to($first_point, $path->role, "move to first $description point") - if !defined $self->last_pos || !$self->last_pos->coincides_with($first_point); + { + my $first_point = $path->first_point; + $gcode .= $self->travel_to($first_point, $path->role, "move to first $description point") + if !defined $self->last_pos || !$self->last_pos->coincides_with($first_point); + } # compensate retraction $gcode .= $self->unretract; @@ -330,9 +332,10 @@ sub extrude_path { $E = $self->extruder->extrude($e * $line_length) if $e; # compose G-code line + my $point = $line->b; $gcode .= sprintf "G1 X%.3f Y%.3f", - ($line->[B]->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], - ($line->[B]->y * &Slic3r::SCALING_FACTOR) + $self->shift_y - $self->extruder->extruder_offset->[Y]; #** + ($point->x * &Slic3r::SCALING_FACTOR) + $self->shift_x - $self->extruder->extruder_offset->[X], + ($point->y * &Slic3r::SCALING_FACTOR) + $self->shift_y - $self->extruder->extruder_offset->[Y]; #** $gcode .= sprintf(" %s%.5f", $self->config->extrusion_axis, $E) if $E; $gcode .= " F$local_F" @@ -344,8 +347,10 @@ sub extrude_path { # only include F in the first line $local_F = 0; } - $self->wipe_path(Slic3r::Polyline->new(reverse @{$path->points})) - if $self->enable_wipe; + if ($self->enable_wipe) { + $self->wipe_path($path->polyline); + $self->wipe_path->reverse; + } } $gcode .= ";_BRIDGE_FAN_END\n" if $path->is_bridge; $self->last_pos($path->last_point); diff --git a/lib/Slic3r/GCode/MotionPlanner.pm b/lib/Slic3r/GCode/MotionPlanner.pm index e4f8e14bd..71a178ecc 100644 --- a/lib/Slic3r/GCode/MotionPlanner.pm +++ b/lib/Slic3r/GCode/MotionPlanner.pm @@ -80,8 +80,8 @@ sub BUILD { for my $i (0 .. $#outer) { foreach my $line ($outer[$i]->lines) { my $dist = $line->length; - $edges->{$line->[A]}{$line->[B]} = $dist; - $edges->{$line->[B]}{$line->[A]} = $dist; + $edges->{$line->a}{$line->b} = $dist; + $edges->{$line->b}{$line->a} = $dist; } } diff --git a/lib/Slic3r/Layer/Region.pm b/lib/Slic3r/Layer/Region.pm index c4df3caf9..0c48ee7b9 100644 --- a/lib/Slic3r/Layer/Region.pm +++ b/lib/Slic3r/Layer/Region.pm @@ -589,8 +589,8 @@ sub _detect_bridge_direction { # remove any line not having both endpoints within anchors @clipped_lines = grep { my $line = $_; - !(first { $_->encloses_point_quick($line->[A]) } @$anchors) - && !(first { $_->encloses_point_quick($line->[B]) } @$anchors); + !(first { $_->encloses_point_quick($line->a) } @$anchors) + && !(first { $_->encloses_point_quick($line->b) } @$anchors); } @clipped_lines; # sum length of bridged lines diff --git a/lib/Slic3r/Line.pm b/lib/Slic3r/Line.pm index e79b86350..4e42ebdcf 100644 --- a/lib/Slic3r/Line.pm +++ b/lib/Slic3r/Line.pm @@ -37,14 +37,6 @@ sub point_on_left { return Slic3r::Geometry::point_is_on_left_of_segment($point, $self); } -sub midpoint { - my $self = shift; - return Slic3r::Point->new( - ($self->[A][X] + $self->[B][X]) / 2, - ($self->[A][Y] + $self->[B][Y]) / 2, - ); -} - sub grow { my $self = shift; return Slic3r::Polyline->new(@$self[0,1,0])->grow(@_); diff --git a/lib/Slic3r/Polyline.pm b/lib/Slic3r/Polyline.pm index 6ed0c2ce1..7633f315f 100644 --- a/lib/Slic3r/Polyline.pm +++ b/lib/Slic3r/Polyline.pm @@ -192,7 +192,7 @@ sub chained_path { } push @paths, splice @my_paths, $path_index, 1; splice @$endpoints, $path_index*2, 2; - $start_near = $paths[-1][-1]; + $start_near = $paths[-1]->last_point; } return @paths; } diff --git a/xs/src/ExtrusionEntity.cpp b/xs/src/ExtrusionEntity.cpp index e8b586446..fe857d253 100644 --- a/xs/src/ExtrusionEntity.cpp +++ b/xs/src/ExtrusionEntity.cpp @@ -14,6 +14,12 @@ ExtrusionPath::first_point() const return &(this->polyline.points.front()); } +const Point* +ExtrusionPath::last_point() const +{ + return &(this->polyline.points.back()); +} + ExtrusionPath* ExtrusionLoop::split_at_index(int index) { diff --git a/xs/src/ExtrusionEntity.hpp b/xs/src/ExtrusionEntity.hpp index c85293be6..2302ad52b 100644 --- a/xs/src/ExtrusionEntity.hpp +++ b/xs/src/ExtrusionEntity.hpp @@ -39,6 +39,7 @@ class ExtrusionPath : public ExtrusionEntity Polyline polyline; void reverse(); const Point* first_point() const; + const Point* last_point() const; }; class ExtrusionLoop : public ExtrusionEntity diff --git a/xs/src/Line.cpp b/xs/src/Line.cpp index e7b5da558..22d5131db 100644 --- a/xs/src/Line.cpp +++ b/xs/src/Line.cpp @@ -36,6 +36,12 @@ Line::length() const return this->a.distance_to(&(this->b)); } +Point* +Line::midpoint() const +{ + return new Point ((this->a.x + this->b.x) / 2.0, (this->a.y + this->b.y) / 2.0); +} + void Line::from_SV(SV* line_sv) { diff --git a/xs/src/Line.hpp b/xs/src/Line.hpp index 0006e929d..af88bf76e 100644 --- a/xs/src/Line.hpp +++ b/xs/src/Line.hpp @@ -23,6 +23,7 @@ class Line void rotate(double angle, Point* center); void reverse(); double length() const; + Point* midpoint() const; }; typedef std::vector Lines; diff --git a/xs/src/MultiPoint.cpp b/xs/src/MultiPoint.cpp index 76cd9454c..94dcc44dd 100644 --- a/xs/src/MultiPoint.cpp +++ b/xs/src/MultiPoint.cpp @@ -38,6 +38,12 @@ MultiPoint::first_point() const return &(this->points.front()); } +const Point* +MultiPoint::last_point() const +{ + return &(this->points.back()); +} + void MultiPoint::from_SV(SV* poly_sv) { diff --git a/xs/src/MultiPoint.hpp b/xs/src/MultiPoint.hpp index 3bbdcc690..030bca643 100644 --- a/xs/src/MultiPoint.hpp +++ b/xs/src/MultiPoint.hpp @@ -20,6 +20,7 @@ class MultiPoint void rotate(double angle, Point* center); void reverse(); const Point* first_point() const; + const Point* last_point() const; }; } diff --git a/xs/t/09_polyline.t b/xs/t/09_polyline.t index 6fd81fa9c..0528f50b3 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 => 4; +use Test::More tests => 5; my $points = [ [100, 100], @@ -24,4 +24,7 @@ is_deeply [ map $_->pp, @$lines ], [ [ [200, 100], [200, 200] ], ], 'polyline lines'; +$polyline->append_polyline($polyline->clone); +is_deeply $polyline->pp, [ @$points, @$points ], 'append_polyline'; + __END__ diff --git a/xs/xsp/ExtrusionPath.xsp b/xs/xsp/ExtrusionPath.xsp index b4e03c199..7e52ac00c 100644 --- a/xs/xsp/ExtrusionPath.xsp +++ b/xs/xsp/ExtrusionPath.xsp @@ -18,6 +18,8 @@ %code{% RETVAL = THIS->polyline.lines(); %}; Point* first_point() %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(*(THIS->first_point())); %}; + Point* last_point() + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(*(THIS->last_point())); %}; %{ ExtrusionPath* diff --git a/xs/xsp/Line.xsp b/xs/xsp/Line.xsp index 8dc8943ea..a28fce9da 100644 --- a/xs/xsp/Line.xsp +++ b/xs/xsp/Line.xsp @@ -21,6 +21,8 @@ void scale(double factor); void translate(double x, double y); double length(); + Point* midpoint() + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = THIS->midpoint(); %}; %{ Line* diff --git a/xs/xsp/Polyline.xsp b/xs/xsp/Polyline.xsp index 427c6d0d8..9779801f5 100644 --- a/xs/xsp/Polyline.xsp +++ b/xs/xsp/Polyline.xsp @@ -21,6 +21,8 @@ Lines lines(); Point* first_point() %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(*(THIS->first_point())); %}; + Point* last_point() + %code{% const char* CLASS = "Slic3r::Point"; RETVAL = new Point(*(THIS->last_point())); %}; %{ Polyline* @@ -44,6 +46,14 @@ Polyline::append(...) THIS->points.push_back(p); } +void +Polyline::append_polyline(polyline) + Polyline* polyline; + CODE: + for (Points::const_iterator it = polyline->points.begin(); it != polyline->points.end(); ++it) { + THIS->points.push_back((*it)); + } + void Polyline::rotate(angle, center_sv) double angle;