NAME
Geo::Heatmap - generate a density map (aka heatmap) overlay layer for Google Maps, see the www directory in the distro how it works
see the script directory for creating a scale
for a real life example see
http://www.trust-box.at/dev/gm/GoogleMapsHeatmap/www/GoogleMapsHeatmap.html
for Dokumentation see
HOMEPAGE
http://www.trust-box.at/googlemaps-geoheatmap/
REQUIRES
Moose
CHI
Imager
METHODS
tile
tile();
return the tile image in png format
ATTRIBUTES
debug
cache
logfile
return_points
zoom_scale
palette
USAGE
Create a Heatmap layer for GoogleMaps
The HTML part
<head>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
<style type="text/css">
html { height: 100% }
body { height: 100%; margin: 0; padding: 0 }
#map-canvas { height: 100% }
</style>
<script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=&sensor=true">
</script>
<script type="text/javascript">
var overlayMaps = [{
getTileUrl: function(coord, zoom) {
return "hm.fcgi?tile="+coord.x+"+"+coord.y+"+"+zoom;
},
tileSize: new google.maps.Size(256, 256),
isPng: true,
opacity: 0.4
}];
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(48.2130, 16.375),
zoom: 9
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
var overlayMap = new google.maps.ImageMapType(overlayMaps[0]);
map.overlayMapTypes.setAt(0,overlayMap);
}
google.maps.event.addDomListener(window, 'load', initialize);
</script>
</head>
<body>
<div id="map-canvas"/>
</body>
The (f)cgi part
#!/usr/bin/env perl
use strict;
use FCGI;
use DBI;
use CHI;
use FindBin qw/$Bin/;
use lib "$Bin/../lib";
use Geo::Heatmap;
#my $cache = CHI->new( driver => 'Memcached::libmemcached',
# servers => [ "127.0.0.1:11211" ],
# namespace => 'GoogleMapsHeatmap',
#);
my $cache = CHI->new( driver => 'File',
root_dir => '/tmp/GoogleMapsHeatmap'
);
our $dbh = DBI->connect("dbi:Pg:dbname=gisdb", 'gisdb', 'gisdb', {AutoCommit => 0});
my $request = FCGI::Request();
while ($request->Accept() >= 0) {
my $env = $request->GetEnvironment();
my $p = $env->{'QUERY_STRING'};
my ($tile) = ($p =~ /tile=(.+)/);
$tile =~ s/\+/ /g;
# package needs a CHI Object for caching
# a Function Reference to get LatLOng within a Google Tile
# maximum number of points per zoom level
my $ghm = Geo::Heatmap->new();
$ghm->palette('palette.store');
$ghm->zoom_scale( {
1 => 298983,
2 => 177127,
3 => 104949,
4 => 90185,
5 => 70338,
6 => 37742,
7 => 28157,
8 => 12541,
9 => 3662,
10 => 1275,
11 => 417,
12 => 130,
13 => 41,
14 => 18,
15 => 10,
16 => 6,
17 => 2,
18 => 0,
} );
sub get_points {
my $r = shift;
my $sth = $dbh->prepare( qq(select ST_AsEWKT(geom) from geodata
where geom &&
ST_SetSRID(ST_MakeBox2D(ST_Point($r->{LATN}, $r->{LNGW}),
ST_Point($r->{LATS}, $r->{LNGE})
),4326))
);
$sth->execute();
my @p;
while (my @r = $sth->fetchrow) {
my ($x, $y) = ($r[0] =~/POINT\((.+?) (.+?)\)/);
push (@p, [$x ,$y]);
}
$sth->finish;
return \@p;
}
You need a color palette (one is included) to encode values to colors, in Storable Format as an arrayref of arrayrefs eg
[50] = [34, 45, 56]
which means that a normalized value of 50 would lead to an RGB color of 34% red , 45% blue, 56% green.
- zoom_scale
-
The maximum number of points for a given google zoom scale. You would be able to extract to values from the denisity log or derive them from your data in some cunning way
- cache
-
You need some caching for the tiles otherwise the map would be quite slow. Use a CHI object with the cache you like
- return_points
-
A function reference which expects a single hashref as a parameter which defines two LAT/LONG points to get all data points within this box:
$r->{LATN}, $r->{LNGW}), $r->{LATS}, $r->{LNGE}
The function has to return an arrayref of arrayrefs of the points within the box
- tile
-
Returns the rendered image
REPOSITORY
https://github.com/MarkHofstetter/GoogleMapsHeatmap
AUTHOR
Mark Hofstetter <hofstettm@cpan.org>
Thanks to
brian d foy
Marcel Gruenauer
David Steinbrunner
TODO
- put more magic in calculation of zoom scales
- make more things configurable
- add even more tests
COPYRIGHT AND LICENSE
This software is copyright (c) 2013 by Mark Hofstetter
This is free software; you can redistribute it and/or modify it under the same terms as the Perl 5 programming language system itself.