Update 27th March 2012:The Google Maps Geometry library now contains a containsLocation method which will achieve the same thing as detailed below. I’d recommend you use that instead.

Discovering whether a point on a map is inside a polygon can be very useful, especially now that modern browsers and phones are location aware. If you can tell if your user is within a specific boundary then you can present them with immediately relevant information. An example I have used is telling the user they are in the coverage area of a local business (Gascall).

Assuming you’ve already set up your map, the Google maps API allows you to create polygons using simple code.

var path = [ new google.maps.LatLng(51.73383267274113, -1.03271484375), new google.maps.LatLng(51.45400691005984, -1.4501953125), new google.maps.LatLng(51.83577752045251, -0.8843994140625)]; var polygon = new google.maps.Polygon({path:path, clickable:false}); polygon.setMap(map);

You can create a Google maps point from latitude/longitude values or the users location:

if (navigator.geolocation) { navigator.geolocation.getCurrentPosition(function(position) { var point = new google.maps.LatLng(position.coords.latitude, position.coords.longitude); }); }

## Determining if the point is inside the polygon

The google maps api does not already provide a method for checking points in polygons. Some research has already been done on this, but I couldn’t find a complete solution in Google maps api v3 that also catered for crossing 180 degrees longitude. I would have done a straight translation into Google maps api v3, but decided to actually try to understand what was going on.

After researching a bit I stumbled across the Ray-casting algorithm which will determine if an X-Y coordinate is inside a plotted shape. This will translate to latitude and longitude. The following extends the google.maps.polygon.prototype to use this algorithm. Simply include this code at a point in the code after google.maps has loaded:

google.maps.Polygon.prototype.Contains = function(point) { // ray casting alogrithm http://rosettacode.org/wiki/Ray-casting_algorithm var crossings = 0, path = this.getPath(); // for each edge for (var i=0; i < path.getLength(); i++) { var a = path.getAt(i), j = i + 1; if (j >= path.getLength()) { j = 0; } var b = path.getAt(j); if (rayCrossesSegment(point, a, b)) { crossings++; } } // odd number of crossings? return (crossings % 2 == 1); function rayCrossesSegment(point, a, b) { var px = point.lng(), py = point.lat(), ax = a.lng(), ay = a.lat(), bx = b.lng(), by = b.lat(); if (ay > by) { ax = b.lng(); ay = b.lat(); bx = a.lng(); by = a.lat(); } // alter longitude to cater for 180 degree crossings if (px < 0) { px += 360 }; if (ax < 0) { ax += 360 }; if (bx < 0) { bx += 360 }; if (py == ay || py == by) py += 0.00000001; if ((py > by || py < ay) || (px > Math.max(ax, bx))) return false; if (px < Math.min(ax, bx)) return true; var red = (ax != bx) ? ((by - ay) / (bx - ax)) : Infinity; var blue = (ax != px) ? ((py - ay) / (px - ax)) : Infinity; return (blue >= red); } };

Then to check a point:

var point = new google.maps.LatLng(52.05249047600099, -0.6097412109375); var polygon = new google.maps.Polygon({path:[INSERT_PATH_ARRAY_HERE]}); if (polygon.Contains(point)) { // point is inside polygon }

I hope this proves useful. Let me know if you have any suggestions/comments. Test page.