Astro-Coords
view release on metacpan or search on metacpan
lib/Astro/Coords.pm view on Meta::CPAN
# our start time
# calculate the required times
my $mtime;
if ($event == 1 || $event == -1) {
# previous or next
$mtime = $self->_calc_mtime( $reftime, $event );
# Reset the clock
$self->datetime( $oldtime );
} elsif ($event == 0) {
# nearest requires both
my $prev = $self->_calc_mtime( $reftime, -1 );
my $next = $self->_calc_mtime( $reftime, 1 );
# Reset the clock (before we possibly croak)
$self->datetime( $oldtime );
# calculate the diff
if (defined $prev && defined $next) {
my $prev_diff = abs( $reftime->epoch - $prev->epoch );
my $next_diff = abs( $reftime->epoch - $next->epoch );
if ($prev_diff < $next_diff) {
$mtime = $prev;
} else {
$mtime = $next;
}
} elsif (defined $prev) {
$mtime = $prev;
} elsif (defined $next) {
$mtime = $next;
} else {
croak "Should not occur in meridian_time\n";
}
} else {
croak "Unrecognized value for event: $event\n";
}
return $mtime;
}
sub _calc_mtime {
my $self = shift;
my ($reftime, $event ) = @_;
# event must be 1 or -1
if (!defined $event || ($event != 1 && $event != -1)) {
croak "Event must be either +1 or -1";
}
# do we have DateTime objects
my $dtime = $self->_isdt();
# Somewhere to store the previous time so we can make sure things
# are iterating nicely
my $prevtime;
# The current best guess of the meridian time
my $mtime;
# Number of times we want to loop before aborting
my $max = 10;
# Tolerance for good convergence
my $tol = 1;
# Increment (in hours) to jump forward each loop
# Need to make sure we lock onto the correct transit so I'm
# wary of jumping forward by exactly 24 hours
my $inc = 12 * $event;
$inc /= 2 if (defined $self->name && lc($self->name) eq 'moon');
# Loop until mtime is greater than the reftime
# and (mtime - prevtime) is smaller than a second
# and we have not looped more than $max times
# There is probably an analytical solution. The problem is that
# the apparent RA depends on the current time yet the apparent RA
# varies with time
my $count = 0;
print "Looping..............".$reftime->datetime."\n" if $DEBUG;
while ( $count <= $max ) {
$count++;
if (defined $mtime) {
$prevtime = _clone_time( $mtime );
$self->datetime( $mtime );
}
$mtime = $self->_local_mtcalc();
print "New meridian time: ".$mtime->datetime ."\n" if $DEBUG;
# make sure we are going the correct way
# since we are enforced to only find a transit in the direction
# governed by "event"
# Calculate the difference in epoch seconds before the current
# object reference time and the calculate transit time.
# Use ->epoch rather than overload since I'm having problems
# with Duration objects
my $diff = $reftime->epoch - $mtime->epoch;
$diff *= $event; # make the comparison correct sense
if ($diff > 0) {
print "Need to offset....[diff = $diff sec]\n" if $DEBUG;
# this is an earlier transit time
# Need to keep jumping forward until we lock on to a meridian
# time that ismore recent than the ref time
if ($dtime) {
$mtime->add( hours => ($count * $inc));
} else {
$mtime = $mtime + ($count * $inc * Time::Seconds::ONE_HOUR);
}
}
# End loop if the difference between meridian time and calculated
# previous time is less than the acceptable tolerance
if (defined $prevtime && defined $mtime) {
last if (abs($mtime->epoch - $prevtime->epoch) <= $tol);
}
}
( run in 2.611 seconds using v1.01-cache-2.11-cpan-75ffa21a3d4 )