view release on metacpan or search on metacpan
Astro::Coord::ECI::TLE 0.012:
* Correct behavior when Scalar::Util::dualvar not present.
Astro::Coord::ECI::TLE::Iridium 0.005:
* Use max() and min() from Astro::Coord::ECI::Utils.
Astro::Coord::ECI::Utils 0.009:
* Added looks_like_number(), max(), min(), defaulting to the
Scalar::Util or List::Util implementations if possible, but
providing our own if not.
* Clarify load_module() documentation.
bin/satpass 0.017:
* Use looks_like_number() and max() from Astro::Coord::ECI::Utils.
* Recode _load_module to use Astro::Coord::ECI::Utils::load_module.
* Fix clipboard code to fail gracefully if Scalar::Util::weaken
is unavailable.
t/{moon,sun}.t:
* Skip singleton test if Scalar::Util::refaddr not available.
inc/My/Module/Meta.pm view on Meta::CPAN
my ( undef, @extra ) = @_; # Invocant unused
## if ( ! $self->distribution() ) {
## }
return +{
'Carp' => 0,
'Clone' => 0,
'Data::Dumper' => 0,
'Exporter' => 5.64,
'IO::File' => 0,
'POSIX' => 0,
'Scalar::Util' => 1.22, # For looks_like_number
'Time::Local' => 0,
base => 0,
constant => 0,
if => 0,
strict => 0,
warnings => 0,
@extra,
};
}
lib/Astro/Coord/ECI.pm view on Meta::CPAN
The algorithm is from W. S. Smart's "Text-Book on Spherical Astronomy",
as reported in Jean Meeus' "Astronomical Algorithms", 2nd Edition,
Chapter 28, page 185.
=cut
sub equation_of_time {
my ( $self, $time ) = @_;
if ( looks_like_number( $self ) ) {
( $self, $time ) = ( __PACKAGE__, $self );
}
defined $time
or $time = $self->dynamical();
my $epsilon = $self->obliquity( $time );
my $y = tan($epsilon / 2);
$y *= $y;
# The following algorithm is from Meeus, chapter 25, page, 163 ff.
lib/Astro/Coord/ECI.pm view on Meta::CPAN
Note that precisions greater than 4 are not defined by the standard.
This method extends the system by alternating letters (base 24) with
digits (base 10), but this is unsupported since the results will change,
possibly without notice, if the standard is extended in a manner
incompatible with this implementation.
Conversion of latitudes and longitudes to Maidenhead Grid is subject to
truncation error, perhaps more so since latitude and longitude are
specified in radians. An attempt has been made to minimize this by using
Perl's stringification of numbers to ensure that something that looks
like C<42> is not handled as C<41.999999999385>. This probably amounts
to shifting some grid squares very slightly to the north-west, but in
practice it seems to give better results for points on the boundaries of
the grid squares.
=item $coord->maidenhead( $maidenhead_loc, $height );
This method sets the geodetic location in the Maidenhead Locator System.
Height above the reference ellipsoid is not part of the system, but is
accepted anyway, in kilometers, defaulting to 0.
lib/Astro/Coord/ECI.pm view on Meta::CPAN
Edition, Chapter 22, pages 143ff. The conversion from universal to
dynamical time comes from chapter 10, equation 10.2 on page 78.
=cut
use constant E0BASE => (21.446 / 60 + 26) / 60 + 23;
sub obliquity {
my ( $self, $time ) = @_;
if ( looks_like_number( $self ) ) {
( $self, $time ) = ( __PACKAGE__, $self );
}
defined $time
or $time = $self->dynamical();
my $T = jcent2000 ($time); # Meeus (22.1)
my ( undef, $delta_epsilon ) = $self->nutation( $time );
my $epsilon0 = deg2rad( ( ( 0.001813 * $T - 0.00059 ) * $T - 46.8150 )
lib/Astro/Coord/ECI.pm view on Meta::CPAN
## horizon => sub { return $_[0]->get( 'horizon' ); },
height => sub { return $_[0]->dip(); },
);
sub _set_almanac_horizon {
my ( $hash, $attr, $value ) = @_;
defined $value
or $value = 0; # Default
if ( $special{$value} ) {
$hash->{"_$attr"} = $special{$value};
} elsif ( looks_like_number( $value )
&& $value >= - PIOVER2 # Not -PIOVER2 to avoid warning under 5.10.1.
&& $value <= PIOVER2
) {
$hash->{"_$attr"} = sub { return $_[0]->get( $attr ) };
} else {
croak "'$value' is an invalid value for '$attr'";
}
$hash->{$attr} = $value;
return SET_ACTION_NONE;
}
lib/Astro/Coord/ECI.pm view on Meta::CPAN
{
my %dflt = (
twilight => CIVIL_TWILIGHT,
);
# Any attribute specified as angle above or below the horizon.
sub _set_elevation {
my ( $self, $name, $value ) = @_;
defined $value
or $value = ( $dflt{$name} || 0 ); # Default
looks_like_number( $value )
and $value >= - PIOVER2 # Not -PIOVER2 to avoid warning under 5.10.1.
and $value <= PIOVER2
or croak "'$value' is an invalid value for '$name'";
$self->{$name} = $value;
return SET_ACTION_NONE;
}
}
sub _set_station {
my ( $hash, $attr, $value ) = @_;
lib/Astro/Coord/ECI.pm view on Meta::CPAN
# r = sin Theta cos Phi x + sin Theta sin Phi y + cos Theta z
# theta = cos Theta cos Phi x + cos Theta sin Phi y - sin Theta z
# phi = - sin Phi x + cos phi y
#
# and
#
# x = sin Theta cos Phi r + cos Theta cos Phi theta - sin Phi phi
# y = sin Theta sin Phi r + cos Theta sin Phi theta - cos Phi phi
# z = cos Theta r - sin Theta theta
#
# It looks to me like I get the Theta convention I'm using by
# replacing sin Theta with cos Theta and cos Theta by sin Theta
# (because Dr. Cornelius takes 0 as the positive Z axis whereas
# I take zero as the X-Y plane) and changing the sign of theta
# (since Dr. Cornelius' Theta increases in the negative Z
# direction, whereas mine increases in the positive Z
# direction).
#
# The document was found at http://plaza.obu.edu/corneliusk/
# which is the page for Dr. Kevin Cornelius' Mathematical
# Physics (PHYS 4053) course at Ouachita Baptist University in
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
use warnings;
our $VERSION = '0.133';
use base qw{ Astro::Coord::ECI Exporter };
use Astro::Coord::ECI::Utils qw{ :params :ref :greg_time deg2rad distsq
dynamical_delta embodies find_first_true fold_case
__format_epoch_time_usec
format_space_track_json_time gm_strftime load_module local_strftime
looks_like_number max min
mod2pi PI PIOVER2 rad2deg SECSPERDAY TWOPI thetag
__default_station
@CARP_NOT
};
use Carp qw{carp croak confess};
use Data::Dumper;
use IO::File;
use POSIX qw{ ceil floor fmod modf };
use Scalar::Util ();
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
# object unmodified, with the arguments
# being the object, the name of the attribute,
# and the new value of the attribute. The code
# must make the needed changes to the attribute, and
# return 0 or 1, interpreted as above.
my %attrib = (
backdate => 0,
effective => sub {
my ($self, $name, $value) = @_;
if ( defined $value && ! looks_like_number( $value ) ) {
if ( $value =~ m{ \A ([0-9]+) / ([0-9]+) / ([0-9]+) : ([0-9]+) :
([0-9]+ (?: [.] [0-9]* )? ) \z }smx ) {
$value = greg_time_gm( 0, 0, 0, 1, 0,
__tle_year_to_Gregorian_year( $1 + 0 ) ) + (
(($2 - 1) * 24 + $3) * 60 + $4) * 60 + $5;
} else {
carp "Invalid effective date '$value'";
$value = undef;
}
}
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
illum => \&_set_illum,
launch_year => \&_set_intldes_part,
launch_num => \&_set_intldes_part,
launch_piece => \&_set_intldes_part,
object_type => \&_set_object_type,
ordinal => \&_set_optional_unsigned_integer_no_reinit,
originator => 0,
pass_threshold => sub {
my ($self, $name, $value) = @_;
not defined $value
or looks_like_number( $value )
or carp "Invalid $name '$value'";
$self->{$name} = $value;
return 0;
},
reblessable => sub {
my $doit = !$_[0]{$_[1]} && $_[2] && $_[0]->get ('id');
$_[0]{$_[1]} = $_[2];
$doit and $_[0]->rebless ();
return 0;
},
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
Otherwise it is derived from the common name using an algorithm similar
to the one used by the Space Track web site. This algorithm will not
work if the common name is not available, or if it does not conform to
the Space Track naming conventions. Known or suspected differences from
the algorithm described at the bottom of the Satellite Box Score page
include:
* The C<Astro::Coord::ECI::TLE> algorithm is not case-sensitive. The
Space Track algorithm appears to assume all upper-case.
* The C<Astro::Coord::ECI::TLE> algorithm looks for words (that is,
alphanumeric strings delimited by non-alphanumeric characters), whereas
the Space Track documentation seems to say it just looks for substrings.
However, implementing the documented algorithm literally results in OID
20479 'DEBUT (ORIZURU)' being classified as debris, whereas Space Track
returns it in response to a query for name 'deb' that excludes debris.
The possible returns are:
C<< BODY_TYPE_UNKNOWN => dualvar( 0, 'unknown' ) >> if the value of the
C<name> attribute is C<undef>, or if it is empty or contains only
white space.
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
local $_ = undef; # while (<>) ... does not localize $_.
while ( <$fh> ) {
chomp;
m/ \A \s* (?: \# | \z ) /smx
and next; # Extension to syntax.
$parse_info->{pad} > length
and $_ = sprintf '%-*s', $parse_info->{pad}, $_;
# Perl 5.8 and below require an explicit buffer to unpack.
my ( $id, $mag ) = unpack $parse_info->{template}, $_;
$mag =~ s/ \s+ //smxg;
looks_like_number( $mag )
or next;
$mag{ _normalize_oid( $id ) } = $mag + $parse_info->{mag_offset};
}
close $fh;
%magnitude_table = %mag;
};
my %cmd_def = (
add => sub {
my ( $id, $mag ) = @_;
defined $id
and $id =~ m/ \A [0-9]+ \z /smx
and defined $mag
and looks_like_number( $mag )
or croak 'magnitude_table add needs an OID and a magnitude';
$magnitude_table{ _normalize_oid( $id ) } = $mag;
return;
},
adjust => sub {
my ( $adj ) = @_;
if ( defined $adj ) {
looks_like_number( $adj )
or croak 'magnitude_table adjust needs a floating point number';
$magnitude_adjust = $adj;
return;
} else {
return $magnitude_adjust;
}
},
clear => sub {
%magnitude_table = ();
return;
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
},
magnitude => sub {
my ( $tbl ) = @_;
HASH_REF eq ref $tbl
or croak 'magnitude_table magnitude needs a hash ref';
my %mag;
foreach my $key ( keys %{ $tbl } ) {
my $val = $tbl->{$key};
$key =~ m/ \A [0-9]+ \z /smx
or croak "OID '$key' must be numeric";
looks_like_number( $val )
or croak "Magnitude '$val' must be numeric";
$mag{ _normalize_oid( $key ) } = $val;
}
%magnitude_table = %mag;
return;
},
molczan => sub {
my ( $file_name, $mag_factor ) = @_;
$parse_file->( $file_name, $mag_factor, {
mag_offset => 0,
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
# Unsupported, experimental, and subject to change or retraction without
# notice. The intent is to provide a way for the Astro::App::Satpass2
# 'list' command to pick an appropriate template to format each line of
# the listing based on the object being listed.
sub __list_type {
my ( $self ) = @_;
return $self->{inertial} ? 'inertial' : 'fixed';
}
# _looks_like_real
#
# This returns a boolean which is true if the input looks like a real
# number and is false otherwise. It is based on looks_like_number, but
# excludes things like NaN, and Inf.
sub _looks_like_real {
my ( $number ) = @_;
looks_like_number( $number )
or return;
$number =~ m/ \A nan \z /smxi
and return;
$number =~ m/ \A [+-]? inf (?: inity )? \z /smxi
and return;
return 1;
}
# *equinox_dynamical = \&Astro::Coord::ECI::equinox_dynamical;
lib/Astro/Coord/ECI/TLE.pm view on Meta::CPAN
}
# _set_optional_float_no_reinit
#
# This acts as a mutator for any attribute whose value is either undef
# or a floating-point number, and which does not cause the model to be
# renitialized when its value changes. We disallow NaN.
sub _set_optional_float_no_reinit {
my ( $self, $name, $value ) = @_;
if ( defined $value && ! _looks_like_real( $value ) ) {
carp "Invalid $name '$value'; must be a float or undef";
$value = undef;
}
$self->{$name} = $value;
return 0;
}
# _set_optional_unsigned_integer_no_reinit
#
# This acts as a mutator for any attribute whose value is either undef
lib/Astro/Coord/ECI/Utils.pm view on Meta::CPAN
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,
lib/Astro/Coord/ECI/Utils.pm view on Meta::CPAN
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;
script/satpass view on Meta::CPAN
eod
}
}
}
sub _set_almanac_horizon {
my ( $name, $value ) = @_;
$value = _parse_angle( $value );
Astro::Coord::ECI->new( almanac_horizon => $value );
$parm{$name} = $value;
$parm{"_$name"} = looks_like_number( $value ) ?
deg2rad( $value ) :
$value;
return;
}
sub _set_angle {
my ( $name, $value ) = @_;
$parm{$name} = _parse_angle( $value );
$parm{"_$name"} = deg2rad( $value );
return;
script/satpass view on Meta::CPAN
'astronomical', or a unique abbreviation thereof, or a number
of degrees the geometric center of the sun is below the
horizon.
eod
$parm{$_[0]} = $_[1];
$parm{_twilight} = - deg2rad (abs ($angle));
}
}
sub _set_tz {
if ($_[1] || looks_like_number ($_[1])) {
$ENV{TZ} = $parm{$_[0]} = $_[1];
$parm{perltime} and _parse_time_absolute_use_perltime()
or _parse_time_absolute_init( $_[1] );
} else {
$parm{$_[0]} = undef;
delete $ENV{TZ};
$parm{perltime} and _parse_time_absolute_use_perltime()
or _parse_time_absolute_init();
}
}
script/satpass view on Meta::CPAN
pc => PARSEC,
);
sub _parse_distance {
my ($string, $dfdist) = @_;
my $dfunits = $dfdist =~ s/([[:alpha:]]+)$// ? $1 : 'km';
my $units = lc ($string =~ s/([[:alpha:]]+)$// ? $1 : $dfunits);
$units{$units} or die <<eod;
Error - Units of '$units' are unknown.
eod
looks_like_number ($string) or die <<eod;
Error - '$string' is not a number.
eod
$string * $units{$units};
}
} # end of BEGIN block
# $time = _parse_time ($string, $default)
# Parses a time string in any known format. Strings with a
# leading "+" or "-" are assumed to be relative to the last
script/satpass view on Meta::CPAN
$psr->parse ($data);
}
# $quoted = _quoter ($string)
# Quotes and escapes the input string if and as necessary for parser.
sub _quoter {
my $string = shift;
return $string if looks_like_number ($string);
return "''" unless $string;
return $string unless $string =~ m/[\s'"]/;
$string =~ s/([\\'])/\\$1/g;
return "'$string'";
}
# $string = _rad2hms ($angle)
# Converts the given angle in radians to hours, minutes, and
# seconds (of right ascension, presumably)
script/satpass view on Meta::CPAN
sub _sub_arg {
my ($name, $dflt, $args) = @_;
$dflt = '' unless defined $dflt;
my $ctrl = $dflt =~ s/^(\W)// ? $1 : '-';
my $val = $name !~ m/\D/ ? $args->[$name - 1] :
exists $mutator{$name} ? $parm{$name} : $ENV{$name};
my $rslt;
if ($ctrl eq '+') {
$rslt = defined $val ? $dflt : '';
}
elsif ($val || looks_like_number $val) {
$rslt = $val;
}
elsif ($ctrl eq '-') {
$rslt = $dflt;
}
elsif ($ctrl eq '=') {
if ($name !~ m/\D/) {
$args->[$name - 1] = $dflt;
$rslt = $dflt;
}
script/satpass view on Meta::CPAN
=item geocode_ca
satpass> geocode_ca location
B<Notice:> This command is unsupported as of satpass 0.021, and
probably will not work anyway, since geocoder.ca has started
requiring registration to use its free port.
This command attempts to look up the given location (either street
address or street intersection) at L<http://geocoder.ca/>. The results
of the lookup are displayed. If no location is specified, it looks up
the value of the L<location|/location> parameter.
If exactly one valid result is returned, the latitude and longitude
of the observer are set to the returned values, and the name of
the location of the observer is set to the location passed to the
command.
If the location contains whitespace, it must be quoted. Example:
satpass> geocode_ca '80 wellington st ottawa on'
script/satpass view on Meta::CPAN
satpass> geocode_pw location
Palau is handled by L<geocode_us|/geocode_us>.
=item geocode_us
satpass> geocode_us location
This command attempts to look up the given location (either street
address or street intersection) in Open Street Maps. The results
of the lookup are displayed. If no location is specified, it looks up
the value of the L<location|/location> parameter.
If exactly one valid result is returned, the latitude and longitude
of the observer are set to the returned values, and the name of
the location of the observer is set to the canonical name of the
location as returned by Open Street Maps. Also, the height command is
implicitly invoked to attempt to acquire the height above sea level
provided the L<autoheight|/autoheight> parameter is true.
In addition to the usual qualifiers, this command supports the -height