CGI-Wiki-Plugin-Locator-UK
view release on metacpan or search on metacpan
lib/CGI/Wiki/Plugin/Locator/UK.pm view on Meta::CPAN
my @others = $locator->find_within_distance( node => "Albion",
metres => 200 );
=head1 METHODS
=over 4
=item B<new>
my $locator = CGI::Wiki::Plugin::Locator::UK->new;
=cut
sub new {
my ($class, @args) = @_;
my $self = {};
bless $self, $class;
return $self;
}
=item B<coordinates>
my ($x, $y) = $locator->coordinates( node => "Jerusalem Tavern" );
Returns the OS x and y co-ordinates stored as metadata last time the
node was written.
=cut
sub coordinates {
my ($self, %args) = @_;
my $store = $self->datastore;
# This is the slightly inefficient but neat and tidy way to do it -
# calling on as much existing stuff as possible.
my %node_data = $store->retrieve_node( $args{node} );
my %metadata = %{$node_data{metadata}};
return ($metadata{os_x}[0], $metadata{os_y}[0]);
}
=item B<distance>
# Find the straight-line distance between two nodes, in kilometres.
my $distance = $locator->distance( from_node => "Jerusalem Tavern",
to_node => "Calthorpe Arms" );
# Or in metres between a node and a point.
my $distance = $locator->distance(from_os_x => 531467,
from_os_y => 183246,
to_node => "Duke of Cambridge",
unit => "metres" );
# Or specify the point via latitude and longitude.
my $distance = $locator->distance(from_lat => 51.53,
from_long => -0.1,
to_node => "Duke of Cambridge",
unit => "metres" );
Defaults to kilometres if C<unit> is not supplied or is not recognised.
Recognised units at the moment: C<metres>, C<kilometres>.
Returns C<undef> if one of the endpoints does not exist, or does not
have both co-ordinates defined. The C<node> specification of an
endpoint overrides the x/y co-ords if both specified (but don't do
that).
B<Note:> Works to the nearest metre. Well, actually, calls C<int> and
rounds down, but if anyone cares about that they can send a patch.
=cut
sub distance {
my ($self, %args) = @_;
$args{unit} ||= "kilometres";
my (@from, @to);
if ( $args{from_node} ) {
@from = $self->coordinates( node => $args{from_node} );
} elsif ( $args{from_os_x} and $args{from_os_y} ) {
@from = @args{ qw( from_os_x from_os_y ) };
} elsif ( $args{from_lat} and $args{from_long} ) {
my $point = Geography::NationalGrid::GB->new(
Latitude => $args{from_lat},
Longitude => $args{from_long},
);
@from = ( $point->easting, $point->northing );
}
if ( $args{to_node} ) {
@to = $self->coordinates( node => $args{to_node} );
} elsif ( $args{to_os_x} and $args{to_os_y} ) {
@to = @args{ qw( to_os_x to_os_y ) };
}
return undef unless ( $from[0] and $from[1] and $to[0] and $to[1] );
my $metres = int( sqrt( ($from[0] - $to[0])**2
+ ($from[1] - $to[1])**2 ) + 0.5 );
if ( $args{unit} eq "metres" ) {
return $metres;
} else {
return $metres/1000;
}
}
=item B<find_within_distance>
# Find all the things within 200 metres of a given place.
my @others = $locator->find_within_distance( node => "Albion",
metres => 200 );
# Or within 200 metres of a given location.
my @things = $locator->find_within_distance( os_x => 530774,
os_y => 182260,
metres => 200 );
Units currently understood: C<metres>, C<kilometres>. If both C<node>
and C<os_x>/C<os_y> are supplied then C<node> takes precedence. Croaks
if insufficient start point data supplied.
=cut
( run in 1.176 second using v1.01-cache-2.11-cpan-e1769b4cff6 )