diff --git a/lib/Slic3r/ExPolygon.pm b/lib/Slic3r/ExPolygon.pm index 1fa75bb99..9bda96205 100644 --- a/lib/Slic3r/ExPolygon.pm +++ b/lib/Slic3r/ExPolygon.pm @@ -10,24 +10,6 @@ use Math::Geometry::Voronoi; use Slic3r::Geometry qw(X Y A B point_in_polygon same_line epsilon); use Slic3r::Geometry::Clipper qw(union_ex JT_MITER); -sub is_valid { - my $self = shift; - return (!first { !$_->is_valid } @$self) - && $self->contour->is_counter_clockwise - && (!first { $_->is_counter_clockwise } @{$self->holes}); -} - -# returns false if the expolygon is too tight to be printed -sub is_printable { - my $self = shift; - my ($width) = @_; - - # try to get an inwards offset - # for a distance equal to half of the extrusion width; - # if no offset is possible, then expolygon is not printable. - return @{Slic3r::Geometry::Clipper::offset($self, -$width / 2)} ? 1 : 0; -} - sub wkt { my $self = shift; return sprintf "POLYGON(%s)", diff --git a/lib/Slic3r/Geometry.pm b/lib/Slic3r/Geometry.pm index 6a54fa55d..7f231efc5 100644 --- a/lib/Slic3r/Geometry.pm +++ b/lib/Slic3r/Geometry.pm @@ -692,17 +692,18 @@ sub _line_intersection2 { # 2D sub bounding_box { my ($points) = @_; - - my @x = (undef, undef); - my @y = (undef, undef); - for (@$points) { - $x[MIN] = $_->[X] if !defined $x[MIN] || $_->[X] < $x[MIN]; - $x[MAX] = $_->[X] if !defined $x[MAX] || $_->[X] > $x[MAX]; - $y[MIN] = $_->[Y] if !defined $y[MIN] || $_->[Y] < $y[MIN]; - $y[MAX] = $_->[Y] if !defined $y[MAX] || $_->[Y] > $y[MAX]; + use XXX; ZZZ "not" if ref($points->[0]) eq 'ARRAY'; + my @x = map $_->x, @$points; + my @y = map $_->y, @$points; #,, + my @bb = (undef, undef, undef, undef); + for (0..$#x) { + $bb[X1] = $x[$_] if !defined $bb[X1] || $x[$_] < $bb[X1]; + $bb[X2] = $x[$_] if !defined $bb[X2] || $x[$_] > $bb[X2]; + $bb[Y1] = $y[$_] if !defined $bb[Y1] || $y[$_] < $bb[Y1]; + $bb[Y2] = $y[$_] if !defined $bb[Y2] || $y[$_] > $bb[Y2]; } - return ($x[0], $y[0], $x[-1], $y[-1]); + return @bb[X1,Y1,X2,Y2]; } sub bounding_box_center { diff --git a/lib/Slic3r/Polygon.pm b/lib/Slic3r/Polygon.pm index 7241491bf..ae1a8cefd 100644 --- a/lib/Slic3r/Polygon.pm +++ b/lib/Slic3r/Polygon.pm @@ -68,28 +68,6 @@ sub subdivide { } } -# returns false if the polygon is too tight to be printed -sub is_printable { - my $self = shift; - my ($width) = @_; - - # try to get an inwards offset - # for a distance equal to half of the extrusion width; - # if no offset is possible, then polyline is not printable. - # we use flow_width here because this has to be consistent - # with the thin wall detection in Layer->make_surfaces, - # otherwise we could lose surfaces as that logic wouldn't - # detect them and we would be discarding them. - my $p = $self->clone; - $p->make_counter_clockwise; - return @{Slic3r::Geometry::Clipper::offset([$p], -$width / 2)} ? 1 : 0; -} - -sub is_valid { - my $self = shift; - return @$self >= 3; -} - # for cw polygons this will return convex points! sub concave_points { my $self = shift; diff --git a/lib/Slic3r/Print.pm b/lib/Slic3r/Print.pm index 0eb04092a..455544275 100644 --- a/lib/Slic3r/Print.pm +++ b/lib/Slic3r/Print.pm @@ -302,7 +302,7 @@ sub bounding_box { [ $copy->[X] + $object->size->[X], $copy->[Y] + $object->size->[Y] ]; } } - return Slic3r::Geometry::BoundingBox->new_from_points(\@points); + return Slic3r::Geometry::BoundingBox->new_from_points([ map Slic3r::Point->new(@$_), @points ]); } sub size { diff --git a/lib/Slic3r/Print/Object.pm b/lib/Slic3r/Print/Object.pm index b5c0d2eec..bfbf0d420 100644 --- a/lib/Slic3r/Print/Object.pm +++ b/lib/Slic3r/Print/Object.pm @@ -3,7 +3,7 @@ use Moo; use List::Util qw(min max sum first); use Slic3r::ExtrusionPath ':roles'; -use Slic3r::Geometry qw(Z PI scale unscale deg2rad rad2deg scaled_epsilon chained_path_points); +use Slic3r::Geometry qw(X Y Z PI scale unscale deg2rad rad2deg scaled_epsilon chained_path_points); use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex offset offset_ex offset2); use Slic3r::Surface ':types'; @@ -128,7 +128,7 @@ sub bounding_box { my $self = shift; # since the object is aligned to origin, bounding box coincides with size - return Slic3r::Geometry::BoundingBox->new_from_points([ [0,0], $self->size ]); + return Slic3r::Geometry::BoundingBox->new_from_points([ map Slic3r::Point->new(@$_[X,Y]), [0,0], $self->size ]); } sub slice { diff --git a/xs/src/ExPolygon.cpp b/xs/src/ExPolygon.cpp index 33d71b497..ce1ad307d 100644 --- a/xs/src/ExPolygon.cpp +++ b/xs/src/ExPolygon.cpp @@ -40,6 +40,16 @@ ExPolygon::area() const return a; } +bool +ExPolygon::is_valid() const +{ + if (!this->contour.is_valid() || !this->contour.is_counter_clockwise()) return false; + for (Polygons::const_iterator it = this->holes.begin(); it != this->holes.end(); ++it) { + if (!(*it).is_valid() || (*it).is_counter_clockwise()) return false; + } + return true; +} + SV* ExPolygon::to_SV() { const unsigned int num_holes = this->holes.size(); diff --git a/xs/src/ExPolygon.hpp b/xs/src/ExPolygon.hpp index 62f919ead..fa4cbbe20 100644 --- a/xs/src/ExPolygon.hpp +++ b/xs/src/ExPolygon.hpp @@ -20,6 +20,7 @@ class ExPolygon void translate(double x, double y); void rotate(double angle, Point* center); double area() const; + bool is_valid() const; }; typedef std::vector ExPolygons; diff --git a/xs/src/Polygon.cpp b/xs/src/Polygon.cpp index fc3f54f57..78b4b63b3 100644 --- a/xs/src/Polygon.cpp +++ b/xs/src/Polygon.cpp @@ -92,4 +92,10 @@ Polygon::make_clockwise() return false; } +bool +Polygon::is_valid() const +{ + return this->points.size() >= 3; +} + } diff --git a/xs/src/Polygon.hpp b/xs/src/Polygon.hpp index dcab04059..da913df19 100644 --- a/xs/src/Polygon.hpp +++ b/xs/src/Polygon.hpp @@ -20,6 +20,7 @@ class Polygon : public MultiPoint { bool is_counter_clockwise() const; bool make_counter_clockwise(); bool make_clockwise(); + bool is_valid() const; }; typedef std::vector Polygons; diff --git a/xs/t/04_expolygon.t b/xs/t/04_expolygon.t index 8e14e589c..15f6924cf 100644 --- a/xs/t/04_expolygon.t +++ b/xs/t/04_expolygon.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 20; +use Test::More tests => 21; use constant PI => 4 * atan2(1, 1); @@ -23,6 +23,7 @@ my $hole_in_square = [ # cw my $expolygon = Slic3r::ExPolygon->new($square, $hole_in_square); +ok $expolygon->is_valid, 'is_valid'; is ref($expolygon->pp), 'ARRAY', 'expolygon pp is unblessed'; is_deeply $expolygon->pp, [$square, $hole_in_square], 'expolygon roundtrip'; diff --git a/xs/t/06_polygon.t b/xs/t/06_polygon.t index cf81c5e46..5bbdcb4a2 100644 --- a/xs/t/06_polygon.t +++ b/xs/t/06_polygon.t @@ -4,7 +4,7 @@ use strict; use warnings; use Slic3r::XS; -use Test::More tests => 12; +use Test::More tests => 13; my $square = [ # ccw [100, 100], @@ -14,6 +14,7 @@ my $square = [ # ccw ]; my $polygon = Slic3r::Polygon->new(@$square); +ok $polygon->is_valid, 'is_valid'; is_deeply $polygon->pp, $square, 'polygon roundtrip'; is ref($polygon->arrayref), 'ARRAY', 'polygon arrayref is unblessed'; diff --git a/xs/xsp/ExPolygon.xsp b/xs/xsp/ExPolygon.xsp index ed64ba8c1..e4eabe943 100644 --- a/xs/xsp/ExPolygon.xsp +++ b/xs/xsp/ExPolygon.xsp @@ -20,6 +20,7 @@ void scale(double factor); void translate(double x, double y); double area(); + bool is_valid(); %{ ExPolygon* diff --git a/xs/xsp/Polygon.xsp b/xs/xsp/Polygon.xsp index 7b8578d8b..78a1e2edc 100644 --- a/xs/xsp/Polygon.xsp +++ b/xs/xsp/Polygon.xsp @@ -27,6 +27,7 @@ bool is_counter_clockwise(); bool make_counter_clockwise(); bool make_clockwise(); + bool is_valid(); %{ Polygon*