Thursday, August 28, 2008

Google Maps HeatMap now correctly reprojected

I posted some weeks ago my first experiment on HeatMaps over Google Maps for Flash. It was well received by the community of google maps developers and several asked for the code. I did not published it ten because there were still some things I did not understand and somehow were just magic and I had to tweak. The biggest problem was that the heatmap actually was not correctly overlaying in the map, it was clearly a Projection problem. I was plotting the coordinates in an image without reprojecting them to the Mercator projection used by google Maps.

Ok, now I have solved this by using the GoogleMapUtility.php class in the server after getting the latitudes and longitudes of my points from the database.

The final result can be viewed here (source view enabled)

This is how the map would look like without reprojection:

And this is how it looks projected:

If you are overlaying a little heatmap over a small area, a city for example, you dont have to worry about reprojecting as there is not much difference. But like in this case, there is no other way.

The projection takes place on the server on this method:

public function getMercatorCoords() {
$conn = pg_connect($this->conn_string);
$query = "select latitude,longitude from my_table";
$result = pg_query($conn, $query);

$dataX = array();
$dataY = array();

while ($row = pg_fetch_row($result)) {
$lat = $row[0];
$lng = $row[1];
$po = GoogleMapUtility::toZoomedPixelCoords($lat,$lng,0);

$dataY[] = $po->y;
$dataX[] = $po->x;
$res = array();
$res["dataX"] = $dataX;
$res["dataY"] = $dataY;
return $res;
The GoogleMapUtility.php class can be found here. I am not sure who developed it but is widely available all over the web.

In this class I set the Tile Size to be 360, but it could had been more or less anything as long as in the Flex side then you use the same size for creating the Sprite (check the flex source code for more details).

What I would really like is to be able to do this reprojection on Flex as normally I just transfer coordinates to the client and then represent it in different ways, heatmap, grids, markers, etc.
I will try to port the GoogleMapUtility class soon to AS3 and publish it here.

I am using this code already in the widget I am developing for GBIF. It is only a small area and I dont have much data, but I am happy with it.


FlexCarto said...

the reprojection is from wgs84 to google mercator. So in my opnion, you can use Proj4 to convert the data at the client side.

Javier de la Torre said...

Hi. Is there a port of Proj4 to AS3?
I could aso have ported the PHP class that I use for reprojection to AS3 quite easily, but did not take the time. But if you have something available that would be great.

IanW said...

Hi Javier,

I'm also struggling with the issues you had with regards to reprojection. Downside is that I have to keep the server-side as lightwight as possible, so no PHP if possible.

Did you ever get around to porting GoogleMapUtility to AS3 so we can do this client-side ? If so, I would love to see it.

I've been through everything I can think of to plot my image correctly, even got down to slicing images into 1 pixel high strips, and using groundOverlay on those. That actually works fine apart from they are not drawn pixel perfect, so you get lines or gaps where they are drawn (can send you source).



Javier de la Torre said...

Hi Ian,

Nope, I havent ported the GoogleMapUtility to AS3. But in a project that I am working right now I might have to do it.

I think it should be easier actually to port this than actually implementing a slicing mechanism as you did. You could of course also fill the gaps in your solution, and that would probably be faster than reprojecting pixel by pixels as I am pretending to do...

If I get the chance to work on this issue I will post on the blog for sure.


Flex-Mumbler said...

Thank you Javier,

Since I posted, Pamela Fox at Google has confirmed that issue 644, which you originally posted, has been accepted and will make it into the next release of the API for Flash. Yay!!

Just hope that comes in time for you and I.

Thank you again.


Hyder said...

I would really like to see that GoogleMapUtility AS3 port too! :D

I tried to do it myself, but Math boggles me. Moreso, AS3 doesn't support many hyperbolic functions.

d-Media said...

Great work! We're trying to integrate it here, but what i miss in documentation is how de lat en lng should look, double or int?

Tim Robertson said...

I think they are doubles. E.g.:

'lat' => -41.28648,
'lng' => 174.776217,