Image-Maps-Plot-FromLatLong
view release on metacpan or search on metacpan
FromLatLong.pm view on Meta::CPAN
package Image::Maps::Plot::FromLatLong; # where in the world are London.pm members?
our $VERSION = 0.12;
our $DATE = "Thu 17 November 18:50 2004";
use 5.006;
use strict;
use warnings;
use Image::Magick;
use File::Basename;
use Data::Dumper;
use Config;
=head1 NAME
Image::Maps::Plot::FromLatLong - plots points on Mercator Projection world/regional map
=head1 SYNOPSIS
use Image::Maps::Plot::FromLatLong;
# Get ready
$m = new Image::Maps::Plot::FromLatLong (
MAP=>"THE WORLD",
PATH=>"C:/out.html", # Extension is irrelevant
FONT=>"C:/winnt/fonts/arial.ttf",
);
# Now, Create an HTML page with images:
$m->create_html;
# Or just the image
$m->create_imagefile;
# Or get a reference to an image blob:
$m->get_blob;
# Create HTML pages of all maps in the db, with index
my $m = new Image::Maps::Plot::FromLatLong(
FONT=>'c:/winnt/fonts/arial.ttf',
);
$m->all("C:/");
# Add a map
$Image::Maps::Plot::FromLatLong::MAPS{"LONDON AREA"} = {
FILE => 'C:\PhotoWebServer\Perl\site\lib\Image\Maps\Plot\london_bourghs.jpg',
DIM => [650,640],
SPOTSIZE => 5,
ANCHOR_PIXELS => [447,397], # Greenwich on the pixel map
ANCHOR_LATLON => [51.466,0], # Greenwich lat/lon
ANCHOR_NAME => 'Greenwich',
ANCHOR_PLACE => 'Observatory',
ONEMILE => 19.5, # 1 km = .6 miles (10km=180px = 10miles=108px)
};
# Add a user to the db
$m->load_db (".earth.dat");
$m->add_entry ('Ike Elben Goddard','Hungary','H-1165');
$m->save_db (".aliyah.dat");
# Create map content on the fly:
$maker = new Image::Maps::Plot::FromLatLong(
MAP => "THE WORLD",
FONT=>'c:/winnt/fonts/arial.ttf',
PATH => "/Two.foo",
DBFILE => undef,
LOCATIONS => {
'Lee' => {
FromLatLong.pm view on Meta::CPAN
$self->{PATH} = $path.$name;
$self->{IMGPATH} = $name.'.jpg';
# Try to load the image into our object
die "There is no option for a map of $self->{MAP}" if not exists $MAPS{$self->{MAP}};
if (not -e $MAPS{$self->{MAP}}->{FILE}){
warn "No map for $self->{MAP} at $MAPS{$self->{MAP}}->{FILE}: $!" ;
return undef;
}
$self->_load_map or die "Could not read map from $MAPS{$self->{MAP}}->{FILE}: $!";
$self->_populate;
return $self->_save;
}
=head1 METHOD create_blob
Creates an image and return a reference to it's BLOB.
Requires that the C<PATH> field be set (see L<CONSTRUCTOR>).
=cut
sub create_blob { my $self=shift;
if ($self->{PATH}){
my ($name,$path,$suffix) = fileparse($self->{PATH},'(\.[^.]*)?$' );
$self->{PATH} = $path.$name;
$self->{IMGPATH} = $name.'.jpg';
}
# Try to load the image into our object
if (not exists $MAPS{$self->{MAP}}){
warn "There is no option for a map of $self->{MAP}";
return undef;
}
if (not -e $MAPS{$self->{MAP}}->{FILE}){
warn "No map for $self->{MAP}: $!" ;
return undef;
}
if (not $self->_load_map){
warn "Could not read map from $MAPS{$self->{MAP}}->{FILE}: $!";
return undef;
}
$self->_populate;
return \$self->{IM}->ImageToBlob();
}
#
# Just loads the map specified in the FILE field of MAP array
# field specified by the calling object's MAP field.
#
sub _load_map { my $self=shift;
$self->{IM} = Image::Magick->new;
my $err = $self->{IM}->Read($MAPS{$self->{MAP}}->{FILE});
warn "Load map error: $err ($!)" if $err;
return $err? undef:1;
}
=head1 METHOD all (base_path,base_url,title, blurb)
A method that produces all available maps, and an index page with thumbnails.
It accepts four arguments, a path at which files can be built,
a filename prefix (see L<"new">), a title, and blurb to add beneath the list of hyperlinks to the maps.
If no base path is supplied, the C<PATH> field is used.
An index page will be produced, linking to the following files for each map:
=over 4
m_C<MAPNAME>.jpg
m_C<MAPNAME>_t.jpg
m_C<MAPNAME>.html
=back
where MAPNAME is ... the name of the map. The C<m_> prefix is held in the instance variable C<FNPREFIX>.
You may also wish to look at and adjust the instance variable C<CREATIONTXT>.
=cut
sub all { my ($caller, $fpath,$fnprefix,$title,$blurb) = (@_);
die "'all' is now a method!" if not ref $caller;
$fpath = $caller->{PATH} unless $fpath;
die "Please supply a PATH directory (first argument)" if not defined $fpath;
die "No such directory as suppiled: $fpath" unless -d $fpath;
if ($fpath !~ /(\/|\\)$/){$fpath.="/";}
$fnprefix = '' if not defined $fnprefix;
if (not defined $title) {
$title = "London.pm";
}
if (not defined $blurb) {
$blurb =
"These maps were created on ".(scalar localtime)." by ".__PACKAGE__;
$blurb .=", available on <A href='http://search.cpan.org'>CPAN</A>, from data last updated on $DATE."
."<P>Maps originate either from the CIA (who placed them in the public domain), or unknown sources (defunct personal pages on the web)."."<BR><HR><P><SMALL>Copyright (C) <A href='mailto:lGoddard\@CPAN.Org'>Lee Goddard</A> 2001 - available under the...
};
my $self = bless {};
$self->{HTML} = '';
$self->_add_html_top("$title Maps Index");
$self->{HTML} .= "<H1>$title Maps<HR></H1>\n";
foreach my $map (keys %MAPS){
$map =~ /(\w+)$/;
die "Error making filename: didn't match regex" if not defined $1;
$_ = __PACKAGE__;
my $mapmaker = new (__PACKAGE__,{
MAP=>$map,
PATH=>$fpath.$fnprefix.$1,
FONT=>$caller->{FONT},
THUMB_SIZE => $caller->{THUMB_SIZE},
FromLatLong.pm view on Meta::CPAN
die "Passed bad filepath to create_thumbnail <$path>: $!" if not defined $path or not -e $path;
$size = $self->{THUMB_SIZE} if not defined $size;
$size = 75 if not defined $size;
# Create the thumbnail from it, where the biggest side is 50 px
my $outpath = $path;
$outpath =~ s/\.jpg$/_t.jpg/;
my $thumb = Image::Thumbnail->new(
inputpath => $path,
size => $size,
outputpath => $outpath,
CHAT => $self->{chat},
create => 1,
);
return ($thumb->{x},$thumb->{y});
}
#
# Make @LAT and @LON to get length of a degree
#
sub _make_latlon {
LAT:{
my $i = 0;
foreach (@_LAT){
for my $j (0..4){
last LAT if $i+$j>90;
$LAT[$i+$j] = $_;
}
$i += 5;
}
}
LON:{
my $i = 0;
foreach (@_LON){
for my $j (0..4){
last LON if $i+$j>90;
$LON[$i+$j] = $_;
}
$i += 5;
}
}
}
=head1 ADDING MAPS
A future version may allow you to pass map data to the constructor.
In the meantime, adding maps is not in itself a big deal, perl-wise. Add a new key to
the C<%MAPS> hash, with the value of an anonymous hash with the content listed below.
=over 4
=item FILE
scalar file name of Mercator Projection map.
=item DIM
anon array of dimensions of map in pixels [x,y].
You could create DIM on the fly using C<Image::Magick>, but there's probably no point, as you're
almost certainly going to have to edit the map to align it with longitude and latitude
(if you find a stock of public-domain maps that are already aligned, please drop
the author a line).
=item SPOTSIZE
scalar number for the size of the map-marker spots, in pixels
=item ANCHOR_PIXELS
anon array of the pixel location of the arbitrary anchor pont [x,y]
=item ANCHOR_LATLON
anon array of the latitude/longitude of the arbitrary anchor pont [x,y]
=item ANCHOR_NAME
scalar name of the anchor, when marked on map
=item ANCHOR_PLACE
scalar place name of the anchor, when marked on map
=item ONEMILE
scalar representation of 1 mile in pixels
=back
=head1 NOTES ON LATITUDE AND LONGITUDE
After L<http://www.mapblast.com/myblast/helpFaq.mb#2|http://www.mapblast.com/myblast/helpFaq.mb#2>:
=over 4
Zero degrees latitude is the equator, with the North pole at 90 degrees latitude and the South pole at -90 degrees latitude.
one degree is approximately 69 miles. Greenwich, England is at 51.466 degrees north of the equator.
Zero degrees longitude goes through Greenwich, England.
Again, Each 69 miles from this meridian represents approximately 1 degree of longitude.
East/West is plus/minus respectively.
=back
Actually, latitude and longitude vary depending upon the degree in hand:
see L<The Compton Encyclopdedia|http://www.comptons.com/encyclopedia/ARTICLES/0100/01054720_A.html#P17> for more information.
=head1 CAVEATS
The exmaple map, london_postcodes.jpg, is inaccurate.
Whilst degrees of latitude are accurate to two decimal places, Degrees of
longitude are taken to be 69 miles: this isn't quite right - see
L<NOTES ON LATITUDE AND LONGITUDE>. This will be adjusted in a later version.
All images must be JPEGs - PNG or other support could easily be added.
=head1 REVSIONS
=over 4
=item 1.2
Corrected a slight mis-positioning of points.
Replaced GD with Image::Magick as I was seeing terrible JPEG output
with GD.
Replaced support for non-maintained C<Image::GD::Thumbnail> with
C<Image::Thumbnail>; evaluate a require of this at run time rather
than using the apparently still shakey pragmas.
Added methods to create just images and to return references to image blobs.
=item 1.0
Don't remember.
=item 0.25
Clean IMG path and double-header bugs
=item 0.23
Added more documentation; escaping of href text
=item 0.22
Added thumbnail images to index page
=back
=head1 SEE ALSO
perl(1); L<Image::Magick|http://www.ImageMagick.org> (C<http://www.ImageMagick.org>); L<File::Basename>; L<Acme::Pony>; L<Data::Dumper>; L<WWW::MapBlast>; L<Image::Thumbnail>
=head1 THANKS
Thanks to the London.pm group for their test data and insipration, to Leon for his patience with all that mess on the list, to Philip Newton for his frankly amazing knowledge of international postcodes.
Thanks also to the CIA, L<About.com|http://wwww.about.com>, L<The University of Texas|http://www.lib.utexas.edu/maps>,
and L<The Ordnance Survey|http://www.ordsvy.gov.uk/freegb/index.htm#maps>
for their public-domain maps.
=head1 AUTHOR
Lee Goddard <lgoddard -at- cpan -point- org>
=head1 COPYRIGHT
Copyright (C) Lee Goddard, 2001. All Rights Reserved.
This module is supplied and may be used under the same terms as Perl itself.
The public domain maps provided with this distribution are the property of their respective copyright holders.
=cut
1;
__END__
matlab:
axesm('mapprojection','mercator'); displaym( worldhi(mask));
( run in 0.604 second using v1.01-cache-2.11-cpan-600a1bdf6e4 )