Convert lat/lon to pixels and back

AmITheRWord picture AmITheRWord · Aug 5, 2010 · Viewed 18.6k times · Source

I'm using google maps in my application, and I have a webserver with a databse filled with lat/lon values. I want to mark them on the map, but I also want to cluster them together if they are within a certain pixel-distance of eachother.

I figure if I retrieve all my points from the database, I should be able to do something like this (pseudocode):

clusters[];
while(count(points)) {
    cluster[];
    point = points.pop();
    boundingbox = pixelsToBB(point, pixeldistance, zoomlevel);
    query = "select * from database where lat > boundingbox.minlat 
             and lat < boundingbox.maxlat and lng > boundingbox.minlng
             and lng < boundingbox.maxlng";
    for (result in executedquery) {
        cluster[] += result;
        points.remove(result);
    }
    clusters[] += cluster;
}

pixelsToBB(point, distance, zoomlevel) {
    center = convertXY(point, zoomlevel);
    maxlng = convertToLng(center.X, distance, zoomlevel);
    minlng = convertToLng(center.X, -distance, zoomlevel);
    minlat = convertToLat(center.Y, -distance, zoomlevel);
    maxlat = convertToLat(center.Y, distance, zoomlevel);
    return boundingbox(maxlng, maxlat, minlng, minlat);
}

What would my pixelsToBB function need to do with the zoomlevel? OR rather what would my convertToXY, convertToLng and convertToLat need to do? Am I thinking about this the right way, or are there any better ways to do it? I'm not even sure what to search for, so if it's been asked before I'm sorry.

Answer

user3638471 picture user3638471 · Sep 6, 2015

Using Google Maps API v3:

var latLng = // your position object here
var projection = map.getProjection();
var bounds = map.getBounds();
var topRight = projection.fromLatLngToPoint(bounds.getNorthEast());
var bottomLeft = projection.fromLatLngToPoint(bounds.getSouthWest());
var scale = Math.pow(2, map.getZoom());
var worldPoint = projection.fromLatLngToPoint(latLng);
return [Math.floor((worldPoint.x - bottomLeft.x) * scale), Math.floor((worldPoint.y - topRight.y) * scale)];