Algorithm-ClusterPoints
view release on metacpan or search on metacpan
lib/Algorithm/ClusterPoints.pm view on Meta::CPAN
package Algorithm::ClusterPoints;
our $VERSION = '0.08';
use strict;
use warnings;
use constant sqr2 => sqrt(2);
use constant isqr2 => 1/sqr2;
use POSIX qw(floor ceil);
use List::Util qw(max min);
use Carp;
use Data::Dumper;
my $packing = ($] >= 5.008 ? 'w*' : 'V*');
sub new {
@_ & 1 or croak 'Usage: Algorithm::ClusterPoints->new(%options)';
my ($class, %opts) = @_;
my $dimension = delete $opts{dimension};
$dimension = 2 unless defined $dimension;
$dimension < 1 and croak "positive dimension required";
my $radius = delete $opts{radius};
my $minimum_size = delete $opts{minimum_size};
my $ordered = delete $opts{ordered};
my $scales = delete $opts{scales};
my $dimensional_groups = delete $opts{dimensional_groups};
%opts and croak "unknown constructor option(s) '".join("', '", sort keys %opts)."'";
my $self = bless { radius => 1.0,
minimum_size => 1,
ordered => 0,
dimension => $dimension,
coords => [ map [], 1..$dimension ],
scales => [ map 1, 1..$dimension ],
dimensional_groups => [[0..$dimension-1]],
}, $class;
$self->radius($radius) if defined $radius;
$self->minimum_size($minimum_size) if defined $minimum_size;
$self->ordered($ordered) if defined $ordered;
if (defined $scales) {
ref $scales eq 'ARRAY' or croak 'ARRAY reference expected for "scales" option';
$self->scales(@$scales);
}
if (defined $dimensional_groups) {
ref $dimensional_groups eq 'ARRAY' or croak 'ARRAY reference expected for "dimensional_groups" option';
$self->dimensional_groups(@$dimensional_groups);
}
$self;
}
sub add_point {
my $self = shift;
my $dimension = $self->{dimension};
@_ % $dimension and croak 'coordinates list size is not a multiple of the problem dimension';
delete $self->{_clusters};
my $ix = @{$self->{coords}[0]};
while (@_) {
push @$_, shift
for (@{$self->{coords}});
}
$ix;
}
*add_points = \&add_point;
sub point_coords {
@_ == 2 or croak 'Usage: $clp->point_coords($index)';
my ($self, $ix) = @_;
my $top = $#{$self->{coords}[0]};
croak "point index $ix out of range [0, $top]"
if ($ix > $top or $ix < 0);
return $self->{coords}[0][$ix]
if $self->{dimension} == 1;
wantarray or croak 'method requires list context';
map $_->[$ix], @{$self->{coords}};
}
sub reset { delete shift->{_clusters} }
sub radius {
@_ > 2 and croak 'Usage: $clp->radius([$new_radius])';
my $self = shift;
if (@_) {
my $radius = shift;
$radius > 0.0 or croak 'positive radius required';
$self->{radius} = $radius;
delete $self->{_clusters};
}
( run in 0.828 second using v1.01-cache-2.11-cpan-39bf76dae61 )