Astro-Coords

 view release on metacpan or  search on metacpan

lib/Astro/Coords/Angle.pm  view on Meta::CPAN

package Astro::Coords::Angle;

=head1 NAME

Astro::Coords::Angle - Representation of an angle

=head1 SYNOPSIS

  use Astro::Coords::Angle;

  $ang = new Astro::Coords::Angle( 45.5, units => 'deg' );
  $ang = new Astro::Coords::Angle( "45:30:00", units => 'sexagesimal' );

  $rad = $ang->radians;
  $deg = $ang->degrees;
  $asec = $ang->arcsec;
  $amin = $ang->arcmin;
  $string = $ang->string;

=head1 DESCRIPTION

Helper class for C<Astro::Coords> to represent an angle. Methods are
provided for parsing angles in sexagesimal format and for returning
angles in any desired format.

=cut

use 5.006;
use strict;
use warnings;
use warnings::register;
use Carp;

use Scalar::Util qw/ looks_like_number /;
use Astro::PAL;

# Overloading
use overload
  '""' => "stringify",
  '0+' => "numify",
  fallback => 1;

# Package Global variables
our $VERSION = '0.23';

=head1 METHODS

=head2 Constructor

=over 4

=item B<new>

Construct a new C<Angle> object. Must be called with an angle as first
argument. Optional hash arguments can be supplied to specify, for example,
the units of the supplied angle.

  $ang = new Astro::Coords::Angle( $angle,
                                   units => "degrees" );

Supported options are:

  units      - units of the supplied string or number
  range      - restricted range of the angle

Supported units are:

 sexagesimal - A string of format either dd:mm:ss or "dd mm ss"
               "dms" separators are also supported.
 degrees     - decimal degrees
 radians     - radians
 arcsec      - arc seconds (abbreviated form is 'as')
 arcmin      - arc minutes (abbreviated form is 'am')

The units can be abbreviated to the first 3 characters.

If the units are not supplied the default is to assume "sexagesimal"
if the supplied string contains spaces or colons or the characters
"d", "m" or "s", "degrees" if the supplied number is greater than 2*PI
(6.28), and "radians" for all other values. Negative angles are supported.

The options for range are documented in the C<range> method.

If the angle can not be decoded (if a string), the constructor will fail.

=cut

sub new {
  my $proto = shift;
  my $class = ref($proto) || $proto;

  croak "Constructor for object of class $class must be called with an argument" unless @_;

  # first argument is the angle

lib/Astro/Coords/Angle.pm  view on Meta::CPAN

    my $nstrt = 1;
    ($nstrt, $output, my $j) = Astro::PAL::palDafin( $input, $nstrt );
    $output = undef unless $j == 0;

    if ($j == -1) {
      warnings::warnif "In coordinate '$input' the degrees do not look right";
    } elsif ($j == -2) {
      warnings::warnif "In coordinate '$input' the minutes field is out of range";
    } elsif ($j == -3) {
      warnings::warnif "In coordinate '$input' the seconds field is out of range (0-59.9)";
    } elsif ($j == 1) {
      warnings::warnif "Unable to find plausible coordinate in string '$input'";
    }

  } elsif ($units =~ /^d/) {
    # Degrees decimal
    $output = $input * Astro::PAL::DD2R;

  } elsif ($units =~ /^arcs/ || $units eq 'as') {
    # Arcsec
    $output = $input * Astro::PAL::DAS2R;

  } elsif ($units =~ /^arcm/ || $units eq 'am') {
    # Arcmin
    $output = $input * Astro::PAL::DAS2R * 60 ;

  } else {
    # Already in radians
    $output = $input;
  }

  return $output;
}

=item B<_guess_units>

Given a string or number, tries to guess the units.  Default is to
assume "sexagesimal" if the supplied string does not look like a
number to perl, "degrees" if the supplied number is greater than 2*PI
(6.28), and "radians" for all other values.

  $units = $class->_guess_units( $input );

Returns undef if the input does not look at all plausible or is undef
itself.

Arcsec or arcmin can not be determined with this routine.

=cut

sub _guess_units {
  my $self = shift;
  my $input = shift;
  return undef if !defined $input;

  # Now if we have a space, colon or alphabetic character
  # then we have a real string and assume sexagesimal.
  # Use pre-defined character classes
  my $units;
  # if it does not look like a number choose sexagesimal
  if (!looks_like_number($input)) {
    $units = "sexagesimal";
  } elsif ($input > Astro::PAL::D2PI) {
    $units = "degrees";
  } else {
    $units = "radians";
  }

  return $units;
}

=item B<_r2f>

Routine to convert angle in radians to a formatted array
of numbers in order of sign, deg, min, sec, frac.

  @retval = $ang->_r2f( $ndp );

Note that the number of decimal places is an argument.

=cut

sub _r2f {
  my $self = shift;
  my $res = shift;

  warnings::warnif("More than 9 dp requested ($res), result from palDr2af likely to overflow in fractional part") if $res > 9;

  my ($sign, @dmsf) = Astro::PAL::palDr2af($res, $self->radians);
  return ($sign, @dmsf);
}

=back

=end __PRIVATE_METHODS__

=head1 AUTHOR

Tim Jenness E<lt>t.jenness@cpan.orgE<gt>

=head1 COPYRIGHT

Copyright (C) 2004-2005 Tim Jenness. All Rights Reserved.

This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation; either version 3 of the License, or (at your option) any later
version.

This program is distributed in the hope that it will be useful,but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
Place,Suite 330, Boston, MA  02111-1307, USA

=cut

1;



( run in 2.387 seconds using v1.01-cache-2.11-cpan-140bd7fdf52 )