-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathSolEqu.pm
183 lines (114 loc) · 3.64 KB
/
SolEqu.pm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
package Astro::Montenbruck::SolEqu;
use strict;
use warnings;
use Exporter qw/import/;
use Readonly;
use Math::Trig qw/deg2rad/;
use Astro::Montenbruck::MathUtils qw/angle_c/;
use Astro::Montenbruck::Time::DeltaT qw/delta_t/;
use Astro::Montenbruck::Time qw/jd_cent $SEC_PER_DAY/;
use Astro::Montenbruck::Ephemeris::Planet::Sun;
use Astro::Montenbruck::NutEqu qw/mean2true/;
Readonly our $MARCH_EQUINOX => 0;
Readonly our $JUNE_SOLSTICE => 1;
Readonly our $SEPTEMBER_EQUINOX => 2;
Readonly our $DECEMBER_SOLSTICE => 3;
Readonly my $DELTA => 1e-4;
Readonly::Array our @SOLEQU_EVENTS => ($MARCH_EQUINOX, $JUNE_SOLSTICE, $SEPTEMBER_EQUINOX, $DECEMBER_SOLSTICE);
our @CONSTS = qw/$MARCH_EQUINOX $JUNE_SOLSTICE $SEPTEMBER_EQUINOX $DECEMBER_SOLSTICE @SOLEQU_EVENTS/;
our %EXPORT_TAGS = (
events => \@CONSTS,
all => [ @CONSTS, 'solequ' ]
);
our @EXPORT_OK = ( @{ $EXPORT_TAGS{all} } );
our $VERSION = 0.02;
sub solequ {
my ($year, $k) = @_;
# find approximate time in Julian Days
# k = 0 for March equinox,
# 1 for the Julne solstice
# 2 for the September equinox
# 3 for the December solstice
# print("k = $k, year = $year\n");
my $j = ($year + $k / 4) * 365.2422 + 1721141.3;
# print("j = $j\n");
my $k90 = $k * 90;
my $sun = Astro::Montenbruck::Ephemeris::Planet::Sun->new();
my $nut_func = mean2true(jd_cent($j));
my $x = -1000;
my $last_x;
do {
$last_x = $x;
my $t = jd_cent($j);
my @lbr = $sun->sunpos($t);
my $nut_func = mean2true($t);
($x) = $sun->apparent($t, \@lbr, $nut_func); # apparent geocentric ecliptical coordinates
$j += 58 * sin(deg2rad($k90 - $x));
# print("j = $j, x = $x, last_x = $last_x\n")
} until(angle_c($k90, $x) < $DELTA || $x == $last_x);
my $dt = delta_t($j);
$j -= $dt / $SEC_PER_DAY;
wantarray ? ($j, $x) : $j
}
1;
__END__
=pod
=encoding UTF-8
=head1 NAME
Astro::Montenbruck::SolEqu - Solstices and Equinoxes.
=head1 SYNOPSIS
use Astro::Montenbruck::SolEqu qw/:all/;
# find solstices and equinoxes for year 2020
for my $event (@SOLEQU_EVENTS)
{
my $jd = solequ(2020, $event);
# ...
}
=head1 DESCRIPTION
The times of he equinoxes and solstices are the instants when the apparent longiude
of the Sun is a multiple of B<90 degrees>.
Searches solstices and eqinoxes. Algorithms are based on
I<"Astronomical Formulae for Calculators"> by I<Jean Meeus>, I<Forth Edition>, I<Willmann-Bell, Inc., 1988>.
=head1 EXPORT
=head2 CONSTANTS
=head3 EVENTS
=over
=item * C<$MARCH_EQUINOX>
=item * C<$JUNE_SOLSTICE>
=item * C<$SEPTEMBER_EQUINOX>
=item * C<$DECEMBER_SOLSTICE>
=back
=head3 ARRAY OF THE EVENTS
=over
=item * C<@SOLEQU_EVENTS>
=back
Array of L<EVENTS> in proper order.
=head1 SUBROUTINES
=head2 solequ
Find Julian Day of solstice or equinox for a given year.
use Astro::Montenbruck::SolEqu qw/:all/;
my $jd = Astro::Montenbruck::Ephemeris::Sun->solequ($year, $k);
The result is accurate within I<5 minutes> of Universal Time.
=head3 Arguments
=over
=item 1.
number of a year (negative for B.C., astronomical)
=item 2.
type of event, defined by the constants (see L<Events>).
=back
=head3 Result
In scalar context retuns I<Standard Julian Day>.
In list context: array of:
=over
=item 1.
I<Standard Julian Day> and Sun's longitude, in arc-dgrees.
=item 2.
Sun's longitude, arc-dgrees.
=back
=head1 AUTHOR
Sergey Krushinsky, C<< <krushi at cpan.org> >>
=head1 COPYRIGHT AND LICENSE
Copyright (C) 2009-2022 by Sergey Krushinsky
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=cut