'Smooths' a set of points by (recursively) cutting off corners.
#!/usr/bin/perl =pod =head1 Chaikin Spline Algorithm @points = chaikin ([x1,y1],[x2,y2],...,[xn,yn]); or... @points = chaikin (points => \@AofA, [weight => 3, depth => 0, closed +=> 0]); Implements the Chaikin algorithm for smoothing polygons. This takes a set of points and cuts off corners, adding two new points + for each corner. For instance, a single 'run' (depth=0) would turn this . . into . . . . this . . . . . . ` . .` Futher iterations (depth > 0) make the curve smoother. The weight determines where the 'split' happens. The default (3) split +s the line into quarters, and places new points at 1/4 and 3/4 the le +ngth. Increasing the weight increases the 'tightness' of the curve (a weight + of 5 creating new points at 1/6 and 5/6, for example). If the closed flag is set, a final set of points tending back to the f +irst is added. =cut sub chaikin { my %opt = @_; my @po = (defined $opt{points}) ? @{$opt{points}} : @_; my $w = $opt{weight} || 3; my $div = 1 / ($w + 1); my @dest = $po[0]; foreach my $p (0..$#po-1) { push @dest,[map {(($w * $po[$p][$_]) + $po[$p+1][$_]) * $div } + (0..1)]; push @dest,[map {($po[$p][$_] + ($w * $po[$p+1][$_])) * $div } + (0..1)]; } if ($opt{closed}) { push @dest,[map {(($w * $po[$#po][$_]) + $po[0][$_]) * $div } +(0..1)]; push @dest,[map {($po[$#po][$_] + ($w * $po[0][$_])) * $div } +(0..1)]; } else { push @dest,$po[$#po]; } if ($opt{depth}--) { @dest = chaikin(points=>\@dest,depth=>$opt{depth},weight=>$w,c +losed=>$opt{closed}); } @dest; }