Ported Polygon->is_valid() and ExPolygon->is_valid()

This commit is contained in:
Alessandro Ranellucci 2013-08-26 23:27:51 +02:00
parent da0b85c0d9
commit fe42427a54
13 changed files with 37 additions and 54 deletions

View File

@ -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 qw(X Y A B point_in_polygon same_line epsilon);
use Slic3r::Geometry::Clipper qw(union_ex JT_MITER); 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 { sub wkt {
my $self = shift; my $self = shift;
return sprintf "POLYGON(%s)", return sprintf "POLYGON(%s)",

View File

@ -692,17 +692,18 @@ sub _line_intersection2 {
# 2D # 2D
sub bounding_box { sub bounding_box {
my ($points) = @_; my ($points) = @_;
use XXX; ZZZ "not" if ref($points->[0]) eq 'ARRAY';
my @x = (undef, undef); my @x = map $_->x, @$points;
my @y = (undef, undef); my @y = map $_->y, @$points; #,,
for (@$points) { my @bb = (undef, undef, undef, undef);
$x[MIN] = $_->[X] if !defined $x[MIN] || $_->[X] < $x[MIN]; for (0..$#x) {
$x[MAX] = $_->[X] if !defined $x[MAX] || $_->[X] > $x[MAX]; $bb[X1] = $x[$_] if !defined $bb[X1] || $x[$_] < $bb[X1];
$y[MIN] = $_->[Y] if !defined $y[MIN] || $_->[Y] < $y[MIN]; $bb[X2] = $x[$_] if !defined $bb[X2] || $x[$_] > $bb[X2];
$y[MAX] = $_->[Y] if !defined $y[MAX] || $_->[Y] > $y[MAX]; $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 { sub bounding_box_center {

View File

@ -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! # for cw polygons this will return convex points!
sub concave_points { sub concave_points {
my $self = shift; my $self = shift;

View File

@ -302,7 +302,7 @@ sub bounding_box {
[ $copy->[X] + $object->size->[X], $copy->[Y] + $object->size->[Y] ]; [ $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 { sub size {

View File

@ -3,7 +3,7 @@ use Moo;
use List::Util qw(min max sum first); use List::Util qw(min max sum first);
use Slic3r::ExtrusionPath ':roles'; 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 use Slic3r::Geometry::Clipper qw(diff diff_ex intersection intersection_ex union union_ex
offset offset_ex offset2); offset offset_ex offset2);
use Slic3r::Surface ':types'; use Slic3r::Surface ':types';
@ -128,7 +128,7 @@ sub bounding_box {
my $self = shift; my $self = shift;
# since the object is aligned to origin, bounding box coincides with size # 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 { sub slice {

View File

@ -40,6 +40,16 @@ ExPolygon::area() const
return a; 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* SV*
ExPolygon::to_SV() { ExPolygon::to_SV() {
const unsigned int num_holes = this->holes.size(); const unsigned int num_holes = this->holes.size();

View File

@ -20,6 +20,7 @@ class ExPolygon
void translate(double x, double y); void translate(double x, double y);
void rotate(double angle, Point* center); void rotate(double angle, Point* center);
double area() const; double area() const;
bool is_valid() const;
}; };
typedef std::vector<ExPolygon> ExPolygons; typedef std::vector<ExPolygon> ExPolygons;

View File

@ -92,4 +92,10 @@ Polygon::make_clockwise()
return false; return false;
} }
bool
Polygon::is_valid() const
{
return this->points.size() >= 3;
}
} }

View File

@ -20,6 +20,7 @@ class Polygon : public MultiPoint {
bool is_counter_clockwise() const; bool is_counter_clockwise() const;
bool make_counter_clockwise(); bool make_counter_clockwise();
bool make_clockwise(); bool make_clockwise();
bool is_valid() const;
}; };
typedef std::vector<Polygon> Polygons; typedef std::vector<Polygon> Polygons;

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 20; use Test::More tests => 21;
use constant PI => 4 * atan2(1, 1); 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); 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 ref($expolygon->pp), 'ARRAY', 'expolygon pp is unblessed';
is_deeply $expolygon->pp, [$square, $hole_in_square], 'expolygon roundtrip'; is_deeply $expolygon->pp, [$square, $hole_in_square], 'expolygon roundtrip';

View File

@ -4,7 +4,7 @@ use strict;
use warnings; use warnings;
use Slic3r::XS; use Slic3r::XS;
use Test::More tests => 12; use Test::More tests => 13;
my $square = [ # ccw my $square = [ # ccw
[100, 100], [100, 100],
@ -14,6 +14,7 @@ my $square = [ # ccw
]; ];
my $polygon = Slic3r::Polygon->new(@$square); my $polygon = Slic3r::Polygon->new(@$square);
ok $polygon->is_valid, 'is_valid';
is_deeply $polygon->pp, $square, 'polygon roundtrip'; is_deeply $polygon->pp, $square, 'polygon roundtrip';
is ref($polygon->arrayref), 'ARRAY', 'polygon arrayref is unblessed'; is ref($polygon->arrayref), 'ARRAY', 'polygon arrayref is unblessed';

View File

@ -20,6 +20,7 @@
void scale(double factor); void scale(double factor);
void translate(double x, double y); void translate(double x, double y);
double area(); double area();
bool is_valid();
%{ %{
ExPolygon* ExPolygon*

View File

@ -27,6 +27,7 @@
bool is_counter_clockwise(); bool is_counter_clockwise();
bool make_counter_clockwise(); bool make_counter_clockwise();
bool make_clockwise(); bool make_clockwise();
bool is_valid();
%{ %{
Polygon* Polygon*