Astro-satpass
view release on metacpan or search on metacpan
lib/Astro/Coord/ECI/Utils.pm view on Meta::CPAN
my $Century = $NextCentury - 100;
# The above code is lifted verbatim from Time::Local 1.25.
use constant NOT_GREG =>
'%d not interpreted as Gregorian year by Time::Local::timegm';
# Adujst the year so that the Time::y2038 implementation of
# time_gm() and time_local() mirrors the Time::Local timegm() and
# timelocal() behavior. Kinda sorta.
sub _year_adjust_y2038 {
my ( $year ) = @_;
$year < 0
and return $year;
$year >= 1000
and return $year - 1900;
# The following line of code is lifted verbatim from Time::Local
# 1.25.
$year += ( $year > $Breakpoint ) ? $Century : $NextCentury;
return $year;
}
}
# Adjust a Gregorian year so that Time::Local timegm() and timelocal()
# return epochs in that year.
sub _year_adjust_greg {
my ( $year ) = @_;
return $year >= 1000 ? $year : $year - 1900;
}
our @CARP_NOT = qw{
Astro::Coord::ECI
Astro::Coord::ECI::Mixin
Astro::Coord::ECI::Moon
Astro::Coord::ECI::Star
Astro::Coord::ECI::Sun
Astro::Coord::ECI::TLE
Astro::Coord::ECI::TLE::Set
Astro::Coord::ECI::Utils
};
our @EXPORT;
my @all_external = ( qw{
AU $DATETIMEFORMAT $JD_GREGORIAN JD_OF_EPOCH LIGHTYEAR PARSEC
PERL2000 PI PIOVER2
SECSPERDAY SECS_PER_SIDERIAL_DAY SECS_PER_TROPICAL_YEAR
SPEED_OF_LIGHT TWOPI
ARRAY_REF CODE_REF HASH_REF SCALAR_REF
acos add_magnitudes asin
atmospheric_extinction date2epoch date2jd
decode_space_track_json_time deg2rad distsq dynamical_delta
embodies epoch2datetime find_first_true
fold_case __format_epoch_time_usec
format_space_track_json_time gm_strftime intensity_to_magnitude
jcent2000 jd2date jd2datetime jday2000 julianday
keplers_equation load_module local_strftime
looks_like_number max min mod2pi mod360
omega position_angle
rad2deg rad2dms rad2hms tan theta0 thetag vector_cross_product
vector_dot_product vector_magnitude vector_unitize __classisa
__default_station __instance __subroutine_deprecation
__sprintf
},
qw{ time_gm time_local }, @greg_time_routines );
our @EXPORT_OK = (
qw{ @CARP_NOT }, # Package-private, undocumented
@all_external,
);
my %deprecated_export = map { $_ => 1 } qw{
};
our %EXPORT_TAGS = (
all => \@all_external,
greg_time => \@greg_time_routines,
mainstream => [ grep { ! $deprecated_export{$_} } @all_external ],
params => [ qw{ __classisa __instance } ],
ref => [ grep { m/ [[:upper:]]+ _REF \z /smx } @all_external ],
time => [ qw{ gm_strftime local_strftime time_gm time_local },
@greg_time_routines ],
vector => [ grep { m/ \A vector_ /smx } @all_external ],
);
use constant AU => 149597870; # 1 astronomical unit, per
# Meeus, Appendix I pg 407.
use constant LIGHTYEAR => 9.4607e12; # 1 light-year, per Meeus,
# Appendix I pg 407.
use constant PARSEC => 30.8568e12; # 1 parsec, per Meeus,
# Appendix I pg 407.
use constant PERL2000 => greg_time_gm( 0, 0, 12, 1, 0, 2000 );
use constant PI => atan2 (0, -1);
use constant PIOVER2 => PI / 2;
use constant SECSPERDAY => 86400;
use constant SECS_PER_SIDERIAL_DAY => 86164.0905; # Appendix I, page 408.
# Meeus Appendix I
use constant SECS_PER_TROPICAL_YEAR => 365.242190 * SECSPERDAY;
use constant SPEED_OF_LIGHT => 299792.458; # KM/sec, per NIST.
### use constant SOLAR_RADIUS => 1392000 / 2; # Meeus, Appendix I, page 407.
use constant TWOPI => PI * 2;
use constant ARRAY_REF => ref [];
use constant CODE_REF => ref sub {};
use constant HASH_REF => ref {};
use constant SCALAR_REF => ref \0;
=item $angle = acos ($value)
This subroutine calculates the arc in radians whose cosine is the given
value.
=cut
sub acos {
abs ($_[0]) > 1 and confess <<eod;
Programming error - Trying to take the arc cosine of a number greater
than 1.
eod
lib/Astro/Coord/ECI/Utils.pm view on Meta::CPAN
my $prev;
# Meeus' equation 30.7, page 199.
{
$prev = $curr;
my $delta = ( $mean_anomaly + $eccentricity * sin( $curr
) - $curr ) / ( 1 - $eccentricity * cos $curr );
# Steele's correction, page 205
$curr = $curr + max( -.5, min( .5, $delta ) );
$precision < abs( $curr - $prev )
and redo;
}
return $curr;
}
=item $rslt = load_module ($module_name)
This convenience method loads the named module (using 'require'),
throwing an exception if the load fails. If the load succeeds, it
returns the result of the 'require' built-in, which is required to be
true for a successful load. Results are cached, and subsequent attempts
to load the same module simply give the cached results.
=cut
{ # Local symbol block. Oh, for 5.10 and state variables.
my %error;
my %rslt;
sub load_module {
my ($module) = @_;
exists $error{$module} and croak $error{$module};
exists $rslt{$module} and return $rslt{$module};
# I considered Module::Load here, but it appears not to support
# .pmc files. No, it's not an issue at the moment, but it may be
# if Perl 6 becomes a reality.
$rslt{$module} = eval "require $module"
or croak( $error{$module} = $@ );
return $rslt{$module};
}
} # End local symbol block.
=item print local_strftime( $format, $epoch, $places )
This subroutine takes as input a strftime-compatible format and an
epoch, and returns the local time, formatted per the format.
Optional argument C<$places> is the default number of decimal places for
seconds. If defined, it must be either C<''> or an unsigned integer.
You can also specify an optional C<'.d'> (where the 'd' is one or more
decimal digits) before any format specification that generates seconds.
Examples include C<'%.3S'> or C<'%.6T'>. Such a specification overrides
the C<$places> argument, if any.
=cut
sub local_strftime {
my ( $format, $epoch ) = _pre_strftime( @_ );
return POSIX::strftime( $format, localtime $epoch );
}
=item $boolean = looks_like_number ($string);
This subroutine returns true if the input looks like a number. It uses
Scalar::Util::looks_like_number if that is available, otherwise it uses
its own code, which is lifted verbatim from Scalar::Util 1.19, which in
turn leans heavily on perlfaq4.
=cut
unless (eval {require Scalar::Util; Scalar::Util->import
('looks_like_number'); 1}) {
no warnings qw{once};
*looks_like_number = sub {
local $_ = shift;
# checks from perlfaq4
return 0 if !defined($_) || ref($_);
return 1 if (/^[+-]?[0-9]+$/); # is a +/- integer
return 1 if (/^([+-]?)(?=[0-9]|\.[0-9])[0-9]*(\.[0-9]*)?([Ee]([+-]?[0-9]+))?$/); # a C float
return 1 if ($] >= 5.008 and /^(Inf(inity)?|NaN)$/i)
or ($] >= 5.006001 and /^Inf$/i);
return 0;
};
}
=item $maximum = max (...);
This subroutine returns the maximum of its arguments. If List::Util can
be loaded and 'max' imported, that's what you get. Otherwise you get a
pure Perl implementation.
=cut
unless (eval {require List::Util; List::Util->import ('max'); 1}) {
no warnings qw{once};
*max = sub {
my $rslt;
foreach (@_) {
defined $_ or next;
if (!defined $rslt || $_ > $rslt) {
$rslt = $_;
}
}
$rslt;
};
}
=item $minimum = min (...);
This subroutine returns the minimum of its arguments. If List::Util can
be loaded and 'min' imported, that's what you get. Otherwise you get a
pure Perl implementation.
=cut
unless (eval {require List::Util; List::Util->import ('min'); 1}) {
no warnings qw{once};
*min = sub {
my $rslt;
foreach (@_) {
defined $_ or next;
if (!defined $rslt || $_ < $rslt) {
$rslt = $_;
}
}
$rslt;
};
}
=item $theta = mod2pi ($theta)
This subroutine reduces the given angle in radians to the range 0 <=
( run in 1.473 second using v1.01-cache-2.11-cpan-99c4e6809bf )