CGI-Wiki-Plugin-Locator-UTM

 view release on metacpan or  search on metacpan

lib/CGI/Wiki/Plugin/Locator/UTM.pm  view on Meta::CPAN

}

=item B<coordinates>

  my ($zone, $x, $y) = $locator->coordinates( node => "King's Head" );
  
  my ($zone, $x, $y) = $locator->coordinates( lat => 51.507497,
  					     long => -0.271797);
  					     
Returns the UTM easting and northing co-ordinates. 
See L<Geo::Coordinates::UTM> for the meaning of the zone value.

=cut

sub coordinates {
    my ( $self, %args ) = @_;
    my ( $lat, $long, $zone, $east, $north );

    return @args{qw(zone easting northing)}
      if exists( $args{zone} )
      && exists( $args{easting} )
      && exists( $args{northing} );

    if ( exists $args{lat} ) {
        ( $lat, $long ) = @args{qw/lat long/};
    }
    else {
        my $store     = $self->datastore;
        my %node_data = $store->retrieve_node( $args{node} );
        $lat  = $node_data{metadata}{lat}[0];
        $long = $node_data{metadata}{long}[0];

        # Use UTM metadata if it is available
        $zone  = $node_data{metadata}{zone}[0];
        $east  = $node_data{metadata}{easting}[0];
        $north = $node_data{metadata}{northing}[0];
    }
    if ( !defined($zone) && !defined($east) && !defined($north) ) {
        return undef unless defined($lat) && defined($long);
        ( $zone, $east, $north ) =
          latlon_to_utm( $self->{ellipsoid}, $lat, $long );
    }
    ( $zone, $east, $north );
}

=item B<distance>

  # Find the straight-line distance between two nodes, in kilometres.
  my $distance = $locator->distance( from_node => "King's Head",
                                     to_node   => "Duke Of York" );

  # Or in metres between a node and a point.
  my $distance = $locator->distance(from_lat  => 51.507497,
                                    from_long => -0.271797,
				    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. 

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";

    # Split off the prefix from_ or to_
    my ( %from, %to );
    while ( my ( $arg, $val ) = each %args ) {
        $from{$1} = $val if $arg =~ /from_(.*)/;
        $to{$1}   = $val if $arg =~ /to_(.*)/;
    }

    my @from = $self->coordinates(%from);
    my @to   = $self->coordinates(%to);

    return undef unless ( $from[0] and $from[1] and $to[0] and $to[1] );

    croak("Locations are in different zones") unless $from[0] eq $to[0];

    my $metres =
      int( sqrt( ( $from[1] - $to[1] )**2 + ( $from[2] - $to[2] )**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( lat => 51.507497,
                                               long => -0.271797,
                                               metres => 200 );

Requires the node metadata to be stored in the database, in particular
zone, easting and northing.

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

sub find_within_distance {
    my ( $self, %args ) = @_;



( run in 2.349 seconds using v1.01-cache-2.11-cpan-9581c071862 )