From de9d5403e8865697acd2b4bd475881d8c3808b8e Mon Sep 17 00:00:00 2001 From: Alessandro Ranellucci Date: Fri, 22 Nov 2013 22:48:07 +0100 Subject: [PATCH] Finished porting convex_hull() to XS and removed dependency on Math::ConvexHull::MonotoneChain --- lib/Slic3r/Print.pm | 11 +++++------ xs/MANIFEST | 1 + xs/src/Geometry.cpp | 7 +++++++ xs/src/Point.cpp | 8 +++++++- xs/src/Point.hpp | 1 + 5 files changed, 21 insertions(+), 7 deletions(-) diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index aa865ad6c..a77f05542 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -176,7 +176,6 @@ sub validate { { my @points = map Slic3r::Point->new(@$_[X,Y]), map @{$_->vertices}, @{$self->objects->[$obj_idx]->meshes}; my $convex_hull = convex_hull(\@points); - use XXX; YYY ($convex_hull->pp); ($clearance) = @{offset([$convex_hull], scale $Slic3r::Config->extruder_clearance_radius / 2, 1, JT_ROUND)}; } for my $copy (@{$self->objects->[$obj_idx]->copies}) { @@ -590,7 +589,7 @@ sub make_skirt { return if @points < 3; # at least three points required for a convex hull # find out convex hull - my $convex_hull = convex_hull([ map $_->arrayref, @points ]); + my $convex_hull = convex_hull(\@points); my @extruded_length = (); # for each extruder @@ -606,7 +605,7 @@ sub make_skirt { my $distance = scale $Slic3r::Config->skirt_distance; for (my $i = $Slic3r::Config->skirts; $i > 0; $i--) { $distance += scale $spacing; - my $loop = Slic3r::Geometry::Clipper::offset([$convex_hull], $distance, 0.0001, JT_ROUND)->[0]; + my $loop = offset([$convex_hull], $distance, 0.0001, JT_ROUND)->[0]; $self->skirt->append(Slic3r::ExtrusionLoop->new( polygon => Slic3r::Polygon->new(@$loop), role => EXTR_ROLE_SKIRT, @@ -777,7 +776,7 @@ sub write_gcode { my @islands = (); foreach my $obj_idx (0 .. $#{$self->objects}) { my $convex_hull = convex_hull([ - map @{$_->contour->pp}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers}, + map @{$_->contour}, map @{$_->slices}, @{$self->objects->[$obj_idx]->layers}, ]); # discard layers only containing thin walls (offset would fail on an empty polygon) if (@$convex_hull) { @@ -797,13 +796,13 @@ sub write_gcode { # calculate wiping points if needed if ($self->config->ooze_prevention) { - my $outer_skirt = Slic3r::Polygon->new(@{convex_hull([ map $_->pp, map @$_, @{$self->skirt} ])}); + my $outer_skirt = convex_hull([ map @$_, @{$self->skirt} ]); my @skirts = (); foreach my $extruder (@{$self->extruders}) { push @skirts, my $s = $outer_skirt->clone; $s->translate(map scale($_), @{$extruder->extruder_offset}); } - my $convex_hull = Slic3r::Polygon->new(@{convex_hull([ map @$_, map $_->pp, @skirts ])}); + my $convex_hull = convex_hull([ map @$_, @skirts ]); $gcodegen->standby_points([ map $_->clone, map @$_, map $_->subdivide(scale 10), @{offset([$convex_hull], scale 3)} ]); } diff --git a/xs/MANIFEST b/xs/MANIFEST index 541ad30d5..9d2e3699e 100644 --- a/xs/MANIFEST +++ b/xs/MANIFEST @@ -36,6 +36,7 @@ src/PolylineCollection.hpp src/ppport.h src/Surface.cpp src/Surface.hpp +src/SurfaceCollection.cpp src/SurfaceCollection.hpp src/SVG.cpp src/SVG.hpp diff --git a/xs/src/Geometry.cpp b/xs/src/Geometry.cpp index d6526619c..050300e61 100644 --- a/xs/src/Geometry.cpp +++ b/xs/src/Geometry.cpp @@ -9,6 +9,9 @@ sort_points (Point a, Point b) return (a.x < b.x) || (a.x == b.x && a.y < b.y); } +/* This implementation is based on Steffen Mueller's work for + the Perl module Math::ConvexHull::MonotoneChain (available + on CPAN under the GPL terms) */ void convex_hull(Points points, Polygon &hull) { @@ -40,6 +43,10 @@ convex_hull(Points points, Polygon &hull) hull.points.push_back(*(out_hull[i])); } + // not sure why this happens randomly + if (hull.points.front().coincides_with(hull.points.back())) + hull.points.pop_back(); + free(out_hull); } diff --git a/xs/src/Point.cpp b/xs/src/Point.cpp index 6644cdb33..c8049c8d8 100644 --- a/xs/src/Point.cpp +++ b/xs/src/Point.cpp @@ -30,7 +30,13 @@ Point::rotate(double angle, Point* center) bool Point::coincides_with(const Point* point) const { - return this->x == point->x && this->y == point->y; + return this->coincides_with(*point); +} + +bool +Point::coincides_with(const Point &point) const +{ + return this->x == point.x && this->y == point.y; } int diff --git a/xs/src/Point.hpp b/xs/src/Point.hpp index 175c96c3b..cf0ec2163 100644 --- a/xs/src/Point.hpp +++ b/xs/src/Point.hpp @@ -20,6 +20,7 @@ class Point void scale(double factor); void translate(double x, double y); void rotate(double angle, Point* center); + bool coincides_with(const Point &point) const; bool coincides_with(const Point* point) const; int nearest_point_index(const Points points) const; Point* nearest_point(Points points) const;