Episerver 9 CertifiedMicrosoft Certified ProfessionalMicrosoft Certified Technology Specialist: .Net Framework 4, Web Applications

Determining if a point on a Google Map is in a particular polygon

!--StartFragment-->

I was tasked recently with a proof-of-concept piece for a client of ours, utilizing Google maps.
The task was to extend the current map they have, which contains markers on the map, plus polylines linking them together.

What was now required, is to split the surrounding area in 'zones', then be able to determine if a point on the map, landed in one or more zones.

The Map

At this point, we already have a Google map, with the marker points and polylines on, so half of the work is already done. The marker points and routes come in the form on a JSON object from a web service, so it was a case of extending the functionality of this to incorporate the zonal data.

The Zone Data

We were given some sample data in the form of ArcGIS data files, so the first task is to work out how to transform this data into something we could use that could integrate with what we have.
As we are using Google maps for the actual mapping element, a little research suggested KML files.
This was great news, as I've worked with KML files in the past, for other projects. (see here)

I discovered a website where you could upload the ArcGIS files, and it would hand you back either a KML file, which is a single file containing your polygon data, with no other data; or a KMZ file - which is a zip file containing the kml file, plus supporting information, such as markers etc.
I didnt require all of this information, as we already had that.. so, KML file it was.

KML - The good and the bad

Adding in a new KML layer to an existing map is really easy:

  var ctaLayer = new google.maps.KmlLayer({
    url: 'http://googlemaps.github.io/js-v2-samples/ggeoxml/cta.kml',
    map: map
  });

and thats it. Refresh your page, and the kml layer appears.
There is one gotcha though: the KML files have to be on an internet-facing location, where Google can see it to load the data.
Quickly upload the files to a temporary location, and off we go!

Next, was to research how to interact with this new layer to see if each point was in a layer.
This proved a little tricky, until I came across an article on StackOverflow, that mentioned that in order to interact with this new data, I had to actually plot the points myself, rather than just use the (much easier to use) kml layer.

One step forward, two steps back

Because I can't interact with a kml layer, the next task to was do it manually. KML (or Keyhole Markup Language) files are based on XML files, so dealing with these should be fairly straigh-forward. Opening the KML file, I saw that it contains one or more

<Folder>

elements. within this, are a few more elements detailing the style of the polygon, plus a name etc.
The one I needed is

<polygon>

. This contains a child-element of

<coordinates>

This contained one big list of co-ordinates that detail the polygon.
First task here was to get that data into a format I can use. Split that string up first by spaces, so I end up with a collection of strings like so:

-1.8117973000000003,52.63122890000001

Then, split each string into its constituent parts of Longitute and Latitude.
A quick edit of the web service later, and I have a function that will load my KML file, read out the co-ordinates, and return me a collection of GeoCoordinates, which I can use

A quick amend of the javascript later, and I have the polylines drawn:

No visible difference, but crucially, I can now interact with the zones (in purple).

The Interaction


Once I have my zones plotted on the map, its time to check where the markers sit, in relation to the zone.
I have a collection of route points (my map markers), and a collection of polygons (my Zone data).

Iterating through each polygon, I then check each map marker in turn to see if the latitude & longitude of that point is inside the polygon:

 function DoPointsIntersectPolygon() {
                
                _.each(self.generatedPolygons, function (poly, polyIndex) {
                    _.each(self.markers, function (marker, markerIndex) {
                        var latlng = new google.maps.LatLng(marker.position.lat(), marker.position.lng());
                        if (google.maps.geometry.poly.containsLocation(latlng, poly) === true) {

                            console.log(marker.title, " is in ", self.zonepolylines[polyIndex].Name, " zone");
                        }
                    });
                });
            } 

If it matches, then I render out to the browsers console (Firebug for the win!), detailing which map point is in which zone.

For now, this proof of concept is complete, and successfully proves what I set out to do.
There will be lots more refinement, and refactoring of code later on, but for now, job done!