Thoughts by Techxplorer

Thoughts on my experiences with technology

Managing markers with the Same Coordinates in a Google Map

By: Sam UL

[update]

Updated: Monday, 8 Feb 2010.

Further testing over the weekend has revealed that 100 metres is too much inaccuracy and so the random changes to the coordinates has been decreased to 10 metres, simply by adding another 0 to the denominator. For example 1500 becomes 15000

[/update]

Yesterday I posted about the work I’m doing for the AusStage project and the development of map based interface to event and venue data. One of the issues with this data is that there can be multiple venue records in the data with the same geographic coordinates. Most often this is caused by a venue changing its name over time.

Google Earth has a way of dealing with placemarks with the same coordinates by grouping them together under one placemark which, when clicked, will expand the placemarks out around a central point. This type of functionality isn’t available in Google Maps.

To workaround the issue of markers with the same coordinate in the Google Map I introduced a small algorithm in my code. This algorithm detects when markers with the same coordinates and adds a randomly generated number to the coordinates. The number that is generated equates to at most 100 meters latitude and longitude. This is relatively easy to implement as coordinates stored in the AusStage database use the Decimal Degrees method of expressing coordinates which is also what Google Maps uses.

In the initial testing this has proven to be enough distance to separate the markers without introducing too much inaccuracy. For example in one test case one marker was placed in the middle of the building while the duplicate was placed on the map within the outer walls of the building.

The code that I use currently looks like this:

// get the coordinates
var hash = points[i].getAttribute("lat") + points[i].getAttribute("lng");
hash = hash.replace(".","").replace(",", "").replace("-","");

// check to see if we've seen this hash before
if(coords[hash] == null) {
  // get coordinate object
  var latlng = new GLatLng(parseFloat(points[i].getAttribute("lat")), parseFloat(points[i].getAttribute("lng")));

  // store an indicator that we've seen this point before
  coords[hash] = 1;
} else {

  // add some randomness to this point
  var lat = parseFloat(points[i].getAttribute("lat")) + (Math.random() -.5) / 1500;
  var lng = parseFloat(points[i].getAttribute("lng")) + (Math.random() -.5) / 1500;

  // get the coordinate object
  var latlng = new GLatLng(lat.toFixed(6), lng.toFixed(6));
}

This code snippet is replaces line 29 in the first code snippet that I posted yesterday.

The key lines are:

  • Lines 02 – 03 which get the coordinates and strip them down to a series of digits to use a key
  • Line 06 checks to see if the key has been used before
  • If the key hasn’t been used before lines 08 creates a GLatLng object using the coordinates as they are and line 11 uses the key to store a simple value in the coords object
  • If the key has been been used before lines 15 and 16 add the random amount to the coordinates separating this coordinate from the first coordinate by up to 100m on the map

This is the easiest and most efficient way of working around the issue.

The photo “Do Not Duplicate” was uploaded to Flickr by Sam UL and used under the terms of a Creative Commons License.

Category: Thoughts