view release on metacpan or search on metacpan
perl Makefile.PL
make
make test
make install
This should run on perl5 and later. It might run on perl4.
Hard dependencies:
Math::Polygon
b/build-data.pl view on Meta::CPAN
#!/usr/bin/perl
$|=1;
use strict;
use Geo::ShapeFile;
use Math::Polygon;
use Data::Dumper;
use lib "../lib";
use lib "lib";
use Geo::Location::TimeZone;
# This is a hacky script to generate the data used by Geo::Location::TimeZone.
# It essentially uses brute force. It is run by the package maintainer, and
# not as part of unpacking the package.
# The steps taken are:
# 1) Read in list of centroid points and matching names.
b/build-data.pl view on Meta::CPAN
# list. Lets start looping.
for ( my $s = 1 ; $s <= $lshape->num_parts ; $s++ ){
my @points = ();
# Store the points in a local array.
foreach my $point( $lshape->get_part( $s ) ){
push @points, [$point->X, $point->Y];
}
# Create the polygon.
my $poly = Math::Polygon->new( @points );
# What is the bounding box for this?
my ($xmin, $ymin, $xmax, $ymax) = $poly->bbox;
# Change those into 15 degree chunks.
$xmin = &close15( $xmin );
$ymin = &close15( $ymin );
$xmax = &close15( $xmax );
$ymax = &close15( $ymax );
b/build-data.pl view on Meta::CPAN
if( $trimX || $trimY ){
$curoff--;
}
}
if( $diddel ){
print STDERR "Removed $diddel points leaving " . scalar @masspoints . " \n";
# Recreate the poly using the
# reduced set of points.
# print STDERR "Recreating the polygon: " . join( ",", @masspoints ) . " X\n";
$newpoly = Math::Polygon->new( @masspoints );
}
}
# Save this zone if something different
# is found, and the polygon has a bit of area.
my $tarea = 0;
if( $szone ne $usezone || $forceuse ){
$tarea = $newpoly->area();
if( $tarea > 0 ){
b/build-data.pl view on Meta::CPAN
}
}elsif( $doneX ){
print OUTPUT "\t\t# Grid $xc:$yc ; " . $recheck{"$xc"}{"$yc"} . " records\n";
print OUTPUT "\t\t\"$yc\" => {\n";
my $maxarea = -1;
my $maxname = undef;
foreach my $rkey( sort keys %{$data{"$xc"}{"$yc"}} ){
next if( $rkey eq "o" );
if( ! defined( $data{"$xc"}{"$yc"}{"$rkey"}{"a"} ) ){
my $newpoly = Math::Polygon->new( @{$data{"$xc"}{"$yc"}{"$rkey"}{"p"}} );
$data{"$xc"}{"$yc"}{"$rkey"}{"a"} = $newpoly->area();
}
if( $data{"$xc"}{"$yc"}{"$rkey"}{"a"} > $maxarea || $maxarea == -1 ){
$maxarea = $data{"$xc"}{"$yc"}{"$rkey"}{"a"};
$maxname = $rkey;
}
}
# Decide what the default timezone is.
if( defined( $maxname ) ){
my @bbox = &expandbox( $xc, $yc );
my @points = ();
push @points, [$bbox[0],$bbox[1]];
push @points, [$bbox[2],$bbox[3]];
my $npoly = Math::Polygon->new( @points );
# If there is only one polygon, and the area
# is less than the bounding box, then we
# need to retain it in the output.
if( $maxarea < $npoly->area && $recheck{"$xc"}{"$yc"} > 1 ){
# Need to output the timezones found
# on the object that we're not putting
# in as def_zs.
foreach my $foundzs( keys %{$data{"$xc"}{"$yc"}{"$maxname"}} ){
next unless( $foundzs =~ /^z/ );
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
The names of the timezones returned are according to the 'posix' directory
of the author's zoneinfo directory. Some of these are usable with the
L<DateTime::TimeZone> library.
=cut
package Geo::Location::TimeZone;
use strict;
use Math::Polygon;
use vars qw/$VERSION/;
$VERSION = "0.1";
=head1 METHODS
=head2 new
This creates a new object.
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
# Work through the 'f' string, taking
# 12 bytes at a time until it is all
# gone.
}
# new wants a list of [x,y],[x,y] . how can I
# get that from a list of [x,y,x,y,x,y] ? Not
# easily. Better to incur the expense in
# build-data.
my $poly = Math::Polygon->new( @{$dataref->{'data'}{"$lonoff"}{"$latoff"}{"$kkey"}{"p"}} );
# print STDERR "Random number $kkey with data for " . $args{"lon"} . " and " . $args{"lat"} . " poly has " . $poly->nrPoints . " points X - " . $dataref->{'data'}{"$lonoff"}{"$latoff"}{"$kkey"}{"z"} . " X\n";
if( $poly->contains( [ $args{"lon"}, $args{"lat"} ] ) ){
my $curarea = $poly->area;
if( $smallarea != - 1 ){
if( $curarea < $smallarea ){
$smallarea = $curarea;
$smallname = $kkey;
}
}else{
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
}
return( $retval );
}
# 0.2 stuff
# =head2 do_pack
#
# This is a helper routine used in the compression of GeoData so the overall
# size of the child libraries is kept low. It takes a %hash of arguments,
# comprising either of a Math::Polygon object as 'poly', or a lat/lon pair
# as 'lat' and 'lon' (decimal degrees). It returns a single binary string
# representing the data stored.
#
# Each point supplied is converted to two shorts and two longs, in 'network'
# byte order, for a total of 12 bytes per point. Clueful people will note
# that pack() does not support signed shorts and longs, and will read the
# comments in the library code next.
#
# =cut
#
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
# (increments of 180 for lat, 360 for lon).
sub do_pack {
my $self = shift;
my %args = ( @_ );
my $retstr = undef;
# If we have a polygon to deal with.
if( defined( $args{"poly"} ) ){
# Walk through the points that are returned, and call ourselves
# again on each point. Math::Polygon returns points in X,Y
# order, but since this is a Geo-related application, the
# data is stored in lat,lon order.
foreach my $point( $args{"poly"}->points ){
$retstr .= $self->do_pack( lat => ${$point}[1], lon => ${$point}[0] );
}
}elsif( defined( $args{"lat"} ) && defined( $args{"lon"} ) ){
# Push them into positive space so we can store them as
# unsigned numbers.
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
# =item string
#
# The binary string to unpack. This should be a multiple of 12 bytes.
#
# =item return
#
# How to return the data. Possible return types are 'latlon', which will
# return a @list of the latitude and longitude, 'point', which will return
# a @list of X and Y values, 'listpoints', which will return a @list of
# points (each a sub-@list), and 'poly' which will return a prepared
# Math::Polygon object. Note that the 'latlon' and 'point' returns will only
# process the first 12 bytes.
#
# =over
#
# =cut
sub do_unpack {
my $self = shift;
my %args = ( @_ );
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
}elsif( $latlon ){
push @retlist, $latwhole, $lonwhole;
}else{
push @retlist, $lonwhole, $latwhole;
}
}
# Decide what to return.
if( $dopoly ){
$retobj = Math::Polygon->new( @retlist );
return( $retobj );
}else{
return( @retlist );
}
}
=head1 AUTHOR
Bruce Campbell, 2007. See http://cpan.zerlargal.org/Geo::Location::TimeZone
lib/Geo/Location/TimeZone.pm view on Meta::CPAN
=cut
# The master data for this library lives in a hash called 'data' in
# sub libraries. The hash is 4-levels,
# consisting of lonoff, latoff, random-key, and finally,
# 'p' (for poly),'z' (for zone), and 'c' (for copyright)
# lonoff and latoff are the result of putting the lat/lon into 15 degree
# increments, from -12 to 12, and -6 to 6.
# random-key is just that; a random-key.
# The 'p'oly is a @list of X,Y values that Math::Polygon likes for input.
# The 'z'one is a text string that DateTime::TimeZone hopefully likes.
# The 'c'opyright is a text string by which people can lookup where the
# data came from.
# The script which generates this data is in b/build-data.pl
1;