Geo::Sun - Calculates the Geodetic Position of the Sun over the Surface of the Earth


Geo-Sun documentation Contained in the Geo-Sun distribution.

Index


Code Index:

NAME

Top

Geo::Sun - Calculates the Geodetic Position of the Sun over the Surface of the Earth

SYNOPSIS

Top

  use Geo::Sun;
  my $gs=Geo::Sun->new;                              #isa Geo::Sun
  my $point=$gs->set_datetime(DateTime->now)->point; #Full OO interface
  printf "Point isa %s\n", ref($point);              #isa GPS::Point
  printf "Latitude: %s, Longitude: %s\n", $point->latlon;

DESCRIPTION

Top

The Geo::Sun package calculates the position of the Sun over the Earth. The user method point_dt takes a DateTime object as a parameter and returns a GPS::Point which is the point on the earth where the Sun is directly over at the given time.

The Geo::Sun package is a wrapper around Astro::Coord::ECI::Sun with a user friendly interface.

USAGE

Top

  use Geo::Sun;
  my $gs=Geo::Sun->new;
  printf "Lat: %s, Lon: %s\n", $gs->point->latlon;

CONSTRUCTOR

Top

new

  my $gs=Geo::Sun->new;

METHODS

Top

point

Returns a GPS::Point for the location of the sun at the current datetime.

  my $point=$gs->point;
  my $point=$gs->set_datetime(DateTime->now)->point;

point_dt

Set the current datetime and returns a GPS::Point

  my $point=$gs->point_dt($datetime);

Implemented as

  my $point=$gs->set_datetime($datetime)->point;

datetime

Sets or returns the current datetime which is a DateTime object. The default is DateTime->now.

set_datetime

Sets datetime returns self

METHODS (INTERNAL)

Top

point_recalculate

Recalculates the point when the DateTime is changed.

point_onchange

Override this method if you want to calculate something when the point changes

sun

Sets or returns the Astro::Coord::ECI::Sun object.

  my $sun=$gs->sun;

ellipsoid

Set or returns the Geo::Ellipsoids object.

  my $ellipsoid=$gs->ellipsoid;  #WGS84

BUGS

Top

Please send to the geo-perl email list.

SUPPORT

Top

Try the geo-perl email list.

LIMITATIONS

Top

Calculations are only good to about 3 decimal places.

AUTHOR

Top

    Michael R. Davis
    CPAN ID: MRDVT
    STOP, LLC
    domain=>stopllc,tld=>com,account=>mdavis
    http://www.stopllc.com/

COPYRIGHT

Top

SEE ALSO

Top


Geo-Sun documentation Contained in the Geo-Sun distribution.
package Geo::Sun;
use strict;
use warnings;
use Astro::Coord::ECI::Sun;
use DateTime;
use Geo::Constants qw{PI};
use Geo::Functions qw{deg_rad};
use Geo::Ellipsoids;
use GPS::Point;

BEGIN {
    use vars qw($VERSION);
    $VERSION     = '0.04';
}

sub new {
  my $this = shift();
  my $class = ref($this) || $this;
  my $self = {};
  bless $self, $class;
  $self->initialize(@_);
  return $self;
}

sub initialize {
  my $self=shift;
  %$self=@_;
  $self->sun(Astro::Coord::ECI::Sun->new)
    unless ref($self->sun) eq "Astro::Coord::ECI::Sun";
  $self->ellipsoid(Geo::Ellipsoids->new)
    unless ref($self->ellipsoid) eq "Geo::Ellipsoids";
  if (defined $self->datetime) {
    $self->point_recalculate; #supports $gs->new(datetime=>$dt)
  } else {
    $self->datetime(DateTime->now)
  }
  $self->initialize2; #a hook if you need it
  return $self;
}

sub initialize2 {
  my $self=shift;
  return $self;
}

sub point {
  my $self=shift;
  return $self->{'point'};
}

sub point_dt {
  my $self=shift;
  return $self->set_datetime(@_)->point;
}

sub datetime {
  my $self = shift;
  if (@_) {
    $self->{"datetime"}=shift;
    $self->point_recalculate;
  }
  return $self->{"datetime"};
}

sub set_datetime {
  my $self=shift;
  $self->datetime(@_) if @_;
  return $self;
}

sub point_recalculate {
  my $self=shift;
  my $epoch=$self->datetime->clone->set_time_zone("UTC")->epoch;
  my ($psi, $lambda, $h) = $self->sun->universal($epoch)->geodetic;
  #speed is 2 pi distance from the polar axis to the surface
  #of the earth at latitude divided by 1 day (m/s)
  my $speed=2 * PI() * $self->ellipsoid->n_rad($psi) * cos($psi) / 24 / 60 / 60;
  $self->{'point'}=GPS::Point->new(
    time        => $self->sun->universal, #float seconds unix epoch (UTC)
    lat         => deg_rad($psi),         #signed decimal degrees
    lon         => deg_rad($lambda),      #signed decimal degrees
    alt         => $h * 1000,             #meters above the WGS-84 ellipsoid
    speed       => $speed, #is this right #meters/second (over ground)
    heading     => 270,  #need real value #degrees clockwise from North
    mode        => 3,                     #GPS mode 3-D
    tag         => "Geo::Sun",            #Name of the GPS message for data
  ); 
  $self->point_onchange; #a hook if you need it.
  return $self;
}

sub point_onchange {
  my $self=shift;
  return $self;
}

sub sun {
  my $self=shift;
  $self->{'sun'}=shift if @_;
  return $self->{'sun'};
}

sub ellipsoid {
  my $self = shift();
  $self->{'ellipsoid'}=shift if (@_);
  return $self->{'ellipsoid'};
}

1;