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   10914215 use 5.006;
  19         73  
20 19     19   168 use strict;
  19         48  
  19         710  
21 19     19   268 use warnings;
  19         49  
  19         634  
22 19     19   133 use Carp;
  19         40  
  19         1734  
23              
24             our $VERSION = '0.20';
25              
26 19     19   712 use Astro::PAL ();
  19         4357  
  19         504  
27 19     19   673 use Astro::Coords::Angle;
  19         57  
  19         514  
28 19     19   114 use base qw/ Astro::Coords /;
  19         86  
  19         2805  
29              
30 19     19   138 use overload '""' => "stringify";
  19         37  
  19         119  
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 1167 my $proto = shift;
58 511   33     1949 my $class = ref($proto) || $proto;
59              
60 511         1225 my $planet = lc(shift);
61              
62 511 50       1371 return undef unless defined $planet;
63              
64             # Check that we have a valid planet
65 511 50       1482 return undef unless exists $PLANET{$planet};
66              
67 511         2419 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 673 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 41842 my $self = shift;
107 28432         3740584 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 25994 my $self = shift;
118 17495         27405 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 3 my $self = shift;
139 1         3 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 32 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 215 my $self = shift;
168 3         24 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 16797 my $self = shift;
202 10933 50       26287 if (@_) {
203 10933         15332 my $d = shift;
204 10933         33225 $self->{diam} = new Astro::Coords::Angle( $d, units => 'rad' );
205             }
206 10933         20046 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 15757 my $self = shift;
220              
221 10941         22015 my ($ra_app, $dec_app) = $self->_cache_read( "RA_APP", "DEC_APP" );
222              
223             # Need to calculate it
224 10941 100 66     26040 if (!defined $ra_app || !defined $dec_app) {
225              
226 10933         25093 my $tel = $self->telescope;
227 10933 100       35766 my $long = (defined $tel ? $tel->long : 0.0 );
228 10933 100       87599 my $lat = (defined $tel ? $tel->lat : 0.0 );
229              
230 10933         79773 ($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         52048 $self->diam( $diam );
235              
236             # Convert to angle objects
237 10933         27952 $ra_app = new Astro::Coords::Angle::Hour($ra_app, units => 'rad', range => '2PI');
238 10933         27024 $dec_app = new Astro::Coords::Angle($dec_app, units => 'rad');
239              
240             # store in cache
241 10933         35647 $self->_cache_write( "RA_APP" => $ra_app, "DEC_APP" => $dec_app );
242             }
243              
244 10941         29507 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 22 my $self = shift;
286 1         14 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   70 my $self = shift;
323 44         90 my $name = lc($self->name);
324              
325 44 100       109 if ($name eq 'sun') {
    50          
326 14         42 return &Astro::Coords::SUN_RISE_SET;
327             } elsif ($name eq 'moon') {
328 30         68 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   1608 my $self = shift;
355 1054         2303 my $name = lc($self->name);
356              
357 1054 100       3240 if ($name eq 'sun') {
    100          
358 141         374 return 24 * 3600;
359             } elsif ($name eq 'moon') {
360 141         345 return 24 * 3600 * (1 + 1 / 29.53059);
361             }
362             else {
363 772         2308 $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;