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"
</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
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.