File Coverage

blib/lib/Astro/Coords/Planet.pm
Criterion Covered Total %
statement 70 84 83.3
branch 16 22 72.7
condition 3 6 50.0
subroutine 20 24 83.3
pod 14 14 100.0
total 123 150 82.0


line stmt bran cond sub pod time code
1             package Astro::Coords::Planet;
2              
3              
4             =head1 NAME
5              
6             Astro::Coords::Planet - coordinates relating to planetary motion
7              
8             =head1 SYNOPSIS
9              
10             $c = new Astro::Coords::Planet( 'uranus' );
11              
12             =head1 DESCRIPTION
13              
14             This class is used by C<Astro::Coords> for handling coordinates
15             for planets..
16              
17             =cut
18              
19 19     19   11710489 use 5.006;
  19         98  
20 19     19   133 use strict;
  19         45  
  19         748  
21 19     19   295 use warnings;
  19         74  
  19         720  
22 19     19   111 use Carp;
  19         42  
  19         1837  
23              
24             our $VERSION = '0.21';
25              
26 19     19   926 use Astro::PAL ();
  19         6312  
  19         492  
27 19     19   656 use Astro::Coords::Angle;
  19         57  
  19         622  
28 19     19   105 use base qw/ Astro::Coords /;
  19         121  
  19         2861  
29              
30 19     19   151 use overload '""' => "stringify";
  19         51  
  19         111  
31              
32             our @PLANETS = qw/ sun mercury venus moon mars jupiter saturn
33             uranus neptune /;
34              
35             # invert the planet for lookup
36             my $i = 0;
37             our %PLANET = map { $_, $i++ } @PLANETS;
38              
39             =head1 METHODS
40              
41              
42             =head2 Constructor
43              
44             =over 4
45              
46             =item B<new>
47              
48             Instantiate a new object using the supplied options.
49              
50             $c = new Astro::Coords::Planet( 'mars' );
51              
52             Returns undef on error.
53              
54             =cut
55              
56             sub new {
57 511     511 1 1018 my $proto = shift;
58 511   33     2098 my $class = ref($proto) || $proto;
59              
60 511         1125 my $planet = lc(shift);
61              
62 511 50       1384 return undef unless defined $planet;
63              
64             # Check that we have a valid planet
65 511 50       1465 return undef unless exists $PLANET{$planet};
66              
67 511         2420 bless { planet => $planet,
68             diameter => undef,
69             }, $class;
70              
71             }
72              
73              
74              
75             =back
76              
77             =head2 Class Methods
78              
79             =over 4
80              
81             =item B<planets>
82              
83             Retuns a list of supported planet names.
84              
85             @planets = Astro::Coords::Planet->planets();
86              
87             =cut
88              
89             sub planets {
90 1     1 1 668 return @PLANETS;
91             }
92              
93             =back
94              
95             =head2 Accessor Methods
96              
97             =over 4
98              
99             =item B<planet>
100              
101             Returns the name of the planet.
102              
103             =cut
104              
105             sub planet {
106 28432     28432 1 39434 my $self = shift;
107 28432         3740343 return $self->{planet};
108             }
109              
110             =item B<name>
111              
112             For planets, the name is always just the planet name.
113              
114             =cut
115              
116             sub name {
117 17495     17495 1 24734 my $self = shift;
118 17495         27953 return $self->planet;
119             }
120              
121             =back
122              
123             =head1 General Methods
124              
125             =over 4
126              
127             =item B<array>
128              
129             Return back 11 element array with first element containing the planet
130             name.
131              
132             This method returns a standardised set of elements across all
133             types of coordinates.
134              
135             =cut
136              
137             sub array {
138 1     1 1 4 my $self = shift;
139 1         4 return ($self->planet, undef, undef,
140             undef, undef, undef, undef, undef, undef, undef, undef);
141             }
142              
143             =item B<type>
144              
145             Returns the generic type associated with the coordinate system.
146             For this class the answer is always "RADEC".
147              
148             This is used to aid construction of summary tables when using
149             mixed coordinates.
150              
151             It could be done using isa relationships.
152              
153             =cut
154              
155             sub type {
156 8     8 1 41 return "PLANET";
157             }
158              
159             =item B<stringify>
160              
161             Stringify overload. Simple returns the name of the planet
162             in capitals.
163              
164             =cut
165              
166             sub stringify {
167 3     3 1 166 my $self = shift;
168 3         25 return uc($self->planet());
169             }
170              
171             =item B<summary>
172              
173             Return a one line summary of the coordinates.
174             In the future will accept arguments to control output.
175              
176             $summary = $c->summary();
177              
178             =cut
179              
180             sub summary {
181 0     0 1 0 my $self = shift;
182 0         0 my $name = $self->name;
183 0 0       0 $name = '' unless defined $name;
184 0         0 return sprintf("%-16s %-12s %-13s PLANET",$name,'','');
185             }
186              
187             =item B<diam>
188              
189             Returns the apparent angular planet diameter from the most recent calculation
190             of the apparent RA/Dec.
191              
192             $diam = $c->diam();
193              
194             Returns the answer as a C<Astro::Coords::Angle> object. Note that this
195             number is not updated automatically. (so don't change the time and expect
196             to get the correct answer without first asking for a ra/dec calculation).
197              
198             =cut
199              
200             sub diam {
201 10933     10933 1 15983 my $self = shift;
202 10933 50       26100 if (@_) {
203 10933         15427 my $d = shift;
204 10933         32725 $self->{diam} = new Astro::Coords::Angle( $d, units => 'rad' );
205             }
206 10933         18678 return $self->{diam};
207             }
208              
209             =item B<apparent>
210              
211             Return the apparent RA and Dec as two C<Astro::Coords::Angle> objects for the current
212             coordinates and time.
213              
214             ($ra_app, $dec_app) = $self->apparent();
215              
216             =cut
217              
218             sub apparent {
219 10941     10941 1 16921 my $self = shift;
220              
221 10941         21872 my ($ra_app, $dec_app) = $self->_cache_read( "RA_APP", "DEC_APP" );
222              
223             # Need to calculate it
224 10941 100 66     25972 if (!defined $ra_app || !defined $dec_app) {
225              
226 10933         25732 my $tel = $self->telescope;
227 10933 100       36082 my $long = (defined $tel ? $tel->long : 0.0 );
228 10933 100       84144 my $lat = (defined $tel ? $tel->lat : 0.0 );
229              
230 10933         81554 ($ra_app, $dec_app, my $diam) = Astro::PAL::palRdplan($self->_mjd_tt, $PLANET{$self->planet},
231             $long, $lat );
232              
233             # Store the diameter
234 10933         49729 $self->diam( $diam );
235              
236             # Convert to angle objects
237 10933         25903 $ra_app = new Astro::Coords::Angle::Hour($ra_app, units => 'rad', range => '2PI');
238 10933         25471 $dec_app = new Astro::Coords::Angle($dec_app, units => 'rad');
239              
240             # store in cache
241 10933         32189 $self->_cache_write( "RA_APP" => $ra_app, "DEC_APP" => $dec_app );
242             }
243              
244 10941         28137 return ($ra_app, $dec_app);
245             }
246              
247             =item B<rv>
248              
249             Radial velocity of the planet relative to the Earth geocentre.
250              
251             =cut
252              
253             sub rv {
254 0     0 1 0 croak "Not yet implemented planetary radial velocities";
255             }
256              
257             =item B<vdefn>
258              
259             Velocity definition. Always 'RADIO'.
260              
261             =cut
262              
263             sub vdefn {
264 0     0 1 0 return 'RADIO';
265             }
266              
267             =item B<vframe>
268              
269             Velocity reference frame. Always 'GEO'.
270              
271             =cut
272              
273             sub vframe {
274 0     0 1 0 return 'GEO';
275             }
276              
277             =item B<apply_offset>
278              
279             Overrided method to warn if C<Astro::Coords::apply_offset> is
280             called on this subclass.
281              
282             =cut
283              
284             sub apply_offset {
285 1     1 1 26 my $self = shift;
286 1         12 warn "apply_offset: applying offset to planet position for a specific time.\n";
287 1         20 return $self->SUPER::apply_offset(@_);
288             }
289              
290             =back
291              
292             =begin __PRIVATE_METHODS__
293              
294             =over 4
295              
296             =item B<_default_horizon>
297              
298             Internal helper method for C<rise_time> and C<set_time>. Returns the
299             default horizon. For the sun returns Astro::Coords::SUN_RISE_SET. For
300             the Moon returns:
301              
302             -( 0.5666 deg + moon radius + moon's horizontal parallax )
303              
304             34 arcmin 15-17 arcmin 55-61 arcmin = 4 - 12 arcmin
305              
306             [see the USNO pages at: http://aa.usno.navy.mil/faq/docs/RST_defs.html]
307              
308             For all other planets returns 0.
309              
310             Note that the moon calculation requires that the date stored in the object
311             is close to the date for which the rise/set time is required.
312              
313             The USNO web page is quite confusing on the definition for the moon since
314             in one place it implies that the moonrise occurs when the centre of the moon
315             is above the horizon by 5-10 arcminutes (the above calculation) but on the
316             moon data page comparing moonrise with tables for a specific day indicates a
317             moonrise of -48 arcminutes.
318              
319             =cut
320              
321             sub _default_horizon {
322 44     44   98 my $self = shift;
323 44         92 my $name = lc($self->name);
324              
325 44 100       135 if ($name eq 'sun') {
    50          
326 14         42 return &Astro::Coords::SUN_RISE_SET;
327             } elsif ($name eq 'moon') {
328 30         73 return (-0.8 * Astro::PAL::DD2R);
329             # See http://aa.usno.navy.mil/faq/docs/RST_defs.html
330 0         0 my $refterm = 0.5666 * Astro::PAL::DD2R; # atmospheric refraction
331              
332             # Get the moon radius
333 0         0 $self->_apparent();
334 0         0 my $radius = $self->diam() / 2;
335              
336             # parallax - assume 57 arcminutes for now
337 0         0 my $parallax = (57 * 60) * Astro::PAL::DAS2R;
338              
339 0         0 print "Refraction: $refterm Radius: $radius Parallax: $parallax\n";
340              
341 0         0 return ( -1 * ( $refterm + $radius - $parallax ) );
342             } else {
343 0         0 return 0;
344             }
345             }
346              
347             =item B<_sidereal_period>
348              
349             Returns the length of the source's "day" in seconds.
350              
351             =cut
352              
353             sub _sidereal_period {
354 1054     1054   1612 my $self = shift;
355 1054         2699 my $name = lc($self->name);
356              
357 1054 100       3351 if ($name eq 'sun') {
    100          
358 141         477 return 24 * 3600;
359             } elsif ($name eq 'moon') {
360 141         371 return 24 * 3600 * (1 + 1 / 29.53059);
361             }
362             else {
363 772         2049 $self->SUPER::_sidereal_period();
364             }
365             }
366              
367             =back
368              
369             =end __PRIVATE_METHODS__
370              
371             =head1 NOTES
372              
373             Usually called via C<Astro::Coords>.
374              
375             =head1 REQUIREMENTS
376              
377             C<Astro::PAL> is used for all internal astrometric calculations.
378              
379             =head1 AUTHOR
380              
381             Tim Jenness E<lt>t.jenness@cpan.orgE<gt>
382              
383             =head1 COPYRIGHT
384              
385             Copyright (C) 2001-2005 Particle Physics and Astronomy Research Council.
386             All Rights Reserved.
387              
388             This program is free software; you can redistribute it and/or modify it under
389             the terms of the GNU General Public License as published by the Free Software
390             Foundation; either version 3 of the License, or (at your option) any later
391             version.
392              
393             This program is distributed in the hope that it will be useful,but WITHOUT ANY
394             WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
395             PARTICULAR PURPOSE. See the GNU General Public License for more details.
396              
397             You should have received a copy of the GNU General Public License along with
398             this program; if not, write to the Free Software Foundation, Inc., 59 Temple
399             Place,Suite 330, Boston, MA 02111-1307, USA
400              
401             =cut
402              
403             1;