Jump to content

Ramer-Douglas-Peucker line simplification: Difference between revisions

Added Perl example
m (moved the reference Wikipedia link to the task's preamble instead of the bottom of the task (as a footnote).)
(Added Perl example)
Line 701:
{{out}}
<pre>@[(x: 0.0, y: 0.0), (x: 2.0, y: -0.1), (x: 3.0, y: 5.0), (x: 7.0, y: 9.0), (x: 9.0, y: 9.0)]</pre>
 
=={{header|Perl}}==
{{trans|Perl 6}}
<lang perl>use List::MoreUtils qw(firstidx minmax);
 
my $epsilon = 1;
 
sub norm {
my(@list) = @_;
my($sum);
$sum += $_**2 for @list;
sqrt($sum)
}
 
sub perpendicular_distance {
local *start = shift @_; local *end = shift @_; local *point = shift @_;
return 0 if $start[0]==$point[0] && $start[1]==$point[1]
or $end[0]==$point[0] && $end[1]==$point[1];
my ( $dx, $dy) = ( $end[0]-$start[0], $end[1]-$start[1]);
my ($dpx, $dpy) = ($point[0]-$start[0],$point[1]-$start[1]);
my $t = norm($dx, $dy);
$dx /= $t;
$dy /= $t;
norm($dpx - $dx*($dx*$dpx + $dy*$dpy), $dpy - $dy*($dx*$dpx + $dy*$dpy));
}
 
sub Ramer_Douglas_Peucker {
my(@points) = @_;
return @points if @points == 2;
my(@d);
push @d, perpendicular_distance(@points[0, -1, $_]) for 0..@points-1;
my(undef,$dmax) = minmax @d;
my($index) = firstidx { $_ == $dmax } @d;
if ($dmax > $epsilon) {
my @lo = Ramer_Douglas_Peucker( @points[0..$index]);
my @hi = Ramer_Douglas_Peucker( @points[$index..$#points]);
return @lo[0..@lo-2], @hi;
}
@points[0, -1];
}
 
$result .= '(' . join(' ', @$_) . ') '
for Ramer_Douglas_Peucker( [0,0],[1,0.1],[2,-0.1],[3,5],[4,6],[5,7],[6,8.1],[7,9],[8,9],[9,9] );
print "$result\n";</lang>
{{out}}
<pre>(0 0) (2 -0.1) (3 5) (7 9) (9 9)</pre>
 
=={{header|Perl 6}}==
2,392

edits

Cookies help us deliver our services. By using our services, you agree to our use of cookies.