Create *::Geometry::nearest_point_index to speed up shortest_path method.

This fix gives a further 10% speedup on simcop2387's coaster.
This commit is contained in:
Mark Hindess 2012-06-19 18:15:08 +01:00
parent 62eb41b967
commit f61a1f5a07
2 changed files with 23 additions and 24 deletions

View file

@ -29,26 +29,19 @@ sub shortest_path {
my @paths = (); my @paths = ();
my $start_at; my $start_at;
my $endpoints = [ map $_->endpoints, @my_paths ]; my $endpoints = [ map $_->endpoints, @my_paths ];
CYCLE: while (@my_paths) { while (@my_paths) {
# find nearest point # find nearest point
$start_at = $start_near my $start_index = $start_near
? Slic3r::Point->new(Slic3r::Geometry::nearest_point($start_near, $endpoints)) ? Slic3r::Geometry::nearest_point_index($start_near, $endpoints)
: $self->endpoints->[0]; : 0;
# loop through paths to find the one that starts or ends at the point found my $path_index = int($start_index/2);
PATH: for (my $i = 0; $i <= $#my_paths; $i++) { if ($start_index%2) { # index is end so reverse to make it the start
if ($start_at->id eq $my_paths[$i]->points->[0]->id) { $my_paths[$path_index]->reverse;
push @paths, splice @my_paths, $i, 1;
} elsif ($start_at->id eq $my_paths[$i]->points->[-1]->id) {
$my_paths[$i]->reverse;
push @paths, splice @my_paths, $i, 1;
} else {
next PATH;
}
splice @$endpoints, $i*2, 2;
$start_near = $paths[-1]->points->[-1];
next CYCLE;
} }
push @paths, splice @my_paths, $path_index, 1;
splice @$endpoints, $path_index*2, 2;
$start_near = $paths[-1]->points->[-1];
} }
return @paths; return @paths;
} }

View file

@ -239,17 +239,23 @@ sub polygon_lines {
sub nearest_point { sub nearest_point {
my ($point, $points) = @_; my ($point, $points) = @_;
my $index = nearest_point_index(@_);
return $points->[$index];
}
sub nearest_point_index {
my ($point, $points) = @_;
my ($nearest_point, $distance) = (); my ($nearest_point_index, $distance) = ();
foreach my $p (@$points) { for my $i (0..$#$points) {
my $d = distance_between_points($point, $p); my $d = distance_between_points($point, $points->[$i]);
if (!defined $distance || $d < $distance) { if (!defined $distance || $d < $distance) {
$nearest_point = $p; $nearest_point_index = $i;
$distance = $d; $distance = $d;
return $p if $distance < epsilon; return $i if $distance < epsilon;
} }
} }
return $nearest_point; return $nearest_point_index;
} }
# given a segment $p1-$p2, get the point at $distance from $p1 along segment # given a segment $p1-$p2, get the point at $distance from $p1 along segment