2011-09-01 19:06:28 +00:00
|
|
|
package Slic3r::Polyline;
|
|
|
|
use Moose;
|
|
|
|
|
|
|
|
has 'lines' => (
|
|
|
|
traits => ['Array'],
|
|
|
|
is => 'rw',
|
|
|
|
isa => 'ArrayRef[Slic3r::Line]',
|
|
|
|
default => sub { [] },
|
|
|
|
handles => {
|
|
|
|
add_line => 'push',
|
|
|
|
},
|
|
|
|
);
|
|
|
|
|
|
|
|
after 'add_line' => sub {
|
|
|
|
my $self = shift;
|
|
|
|
|
|
|
|
# add a weak reference to this polyline in line objects
|
|
|
|
# (avoid circular refs)
|
|
|
|
$self->lines->[-1]->polyline($self);
|
|
|
|
};
|
|
|
|
|
|
|
|
sub BUILD {
|
|
|
|
my $self = shift;
|
|
|
|
$_->polyline($self) for @{ $self->lines };
|
|
|
|
}
|
|
|
|
|
|
|
|
sub id {
|
|
|
|
my $self = shift;
|
2011-09-02 19:10:20 +00:00
|
|
|
return join '-', map($_->id, $self->ordered_points(1));
|
2011-09-01 19:06:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sub new_from_points {
|
|
|
|
my $class = shift;
|
|
|
|
my (@points) = @_;
|
|
|
|
|
|
|
|
# we accept Point objects or arrayrefs with point coordinates
|
|
|
|
@points = map {
|
|
|
|
ref $_ eq 'ARRAY'
|
|
|
|
? Slic3r::Point->new('x' => $_->[0], 'y' => $_->[1])
|
|
|
|
: $_
|
|
|
|
} @points;
|
|
|
|
|
2011-09-04 10:04:01 +00:00
|
|
|
my $polyline = $class->new;
|
2011-09-01 19:06:28 +00:00
|
|
|
my $previous_point;
|
|
|
|
$previous_point = $points[-1] if $class eq 'Slic3r::Polyline::Closed';
|
|
|
|
foreach my $point (@points) {
|
|
|
|
if ($previous_point) {
|
|
|
|
my $line = Slic3r::Line->new(a => $previous_point, b => $point);
|
|
|
|
$polyline->add_line($line);
|
|
|
|
}
|
|
|
|
$previous_point = $point;
|
|
|
|
}
|
|
|
|
|
|
|
|
return $polyline;
|
|
|
|
}
|
|
|
|
|
|
|
|
sub points {
|
|
|
|
my $self = shift;
|
|
|
|
my %points = ();
|
|
|
|
$points{$_} = $_ for map $_->points, @{ $self->lines };
|
|
|
|
return values %points;
|
|
|
|
}
|
|
|
|
|
2011-09-02 19:10:20 +00:00
|
|
|
sub ordered_points {
|
|
|
|
my $self = shift;
|
|
|
|
my ($as_objects) = @_;
|
|
|
|
my $points = [];
|
|
|
|
|
|
|
|
#printf "\n\n==> Number of lines: %d\n", scalar @{ $self->lines };
|
|
|
|
my @lines = @{ $self->lines };
|
|
|
|
while (@lines && @$points < @{ $self->lines }) {
|
|
|
|
#printf "\nNumber of points: %d\n", scalar @{ $points };
|
|
|
|
my @temp = @lines;
|
|
|
|
@lines = ();
|
|
|
|
foreach my $line (@temp) {
|
|
|
|
#printf "Line: %s\n", $line->id;
|
|
|
|
my $point;
|
|
|
|
if (!@$points) {
|
|
|
|
# make sure we start from a point not connected to another segment if any
|
|
|
|
push @$points, sort { @{$a->lines} <=> @{$b->lines} } $line->points;
|
|
|
|
next;
|
|
|
|
} elsif ($line->has_endpoint($points->[-1])) {
|
|
|
|
$point = +(grep $points->[-1] ne $_, $line->points)[0];
|
|
|
|
}
|
|
|
|
if (!$point) {
|
|
|
|
#printf " no point found, retrying\n";
|
|
|
|
push @lines, $line;
|
|
|
|
next;
|
|
|
|
}
|
|
|
|
#printf " adding point %s\n", $point->id;
|
|
|
|
push @$points, $point;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pop @$points
|
|
|
|
if $self->isa('Slic3r::Polyline::Closed') && $points->[0]->coincides_with($points->[-1]);
|
|
|
|
|
|
|
|
return @$points if $as_objects;
|
|
|
|
|
|
|
|
$points = [ map [ $_->x, $_->y ], @$points ]; #]
|
|
|
|
return $points;
|
|
|
|
}
|
|
|
|
|
2011-09-01 19:06:28 +00:00
|
|
|
1;
|