Ported Polygon->is_valid() and ExPolygon->is_valid()
This commit is contained in:
parent
da0b85c0d9
commit
fe42427a54
@ -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)",
|
||||||
|
@ -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 {
|
||||||
|
@ -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;
|
||||||
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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();
|
||||||
|
@ -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;
|
||||||
|
@ -92,4 +92,10 @@ Polygon::make_clockwise()
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Polygon::is_valid() const
|
||||||
|
{
|
||||||
|
return this->points.size() >= 3;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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';
|
||||||
|
|
||||||
|
@ -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';
|
||||||
|
@ -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*
|
||||||
|
@ -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*
|
||||||
|
Loading…
Reference in New Issue
Block a user