Parsing a KML file using Google Maps API v3 and geoXML3

Posted on December 9, 2014, 8:25 am by about-dev.com


As I told you in a previous article, I am using Google Maps API for a personal project.

In that article I wanted to find places close by a route. But the route was provided by google directions service.

This means that you have a starting point and a destination one, and google decides what is the route between that points.

But if we have a custom route, how can we get the places near this route?!

For example: we have a kml file containing our route.

We can easily load it in google maps using KmlLayer method.

But our main goal is to obtain the track data from the KML file because the path of the track can be passed to RouteBoxer to obtain the nearby places.

Apparently I have found a partial solution. Using geoxml3 we can parse the KML file and obtain a lot of data. But the track definition can be found in a tag named "gx:Track" and the geoxml3 doesn't parse this tag of the KML file. After searching and searching for a better solution, I have decided to make the modifications directly in the geoxml3 library (I know that a decent solution was at least to extend the library to add new functionalities and keep the source library intact, but...). Now, my geoxml3 library is providing me all the necessary data and RouteBoxer helps me obtain the surrounding areas and the job is done.

And now, the long story short:

- load the libraries google maps api, geoxml3 and routeboxer

- load the kml file

- parse the kml file using geoxml3

- pass the path of the track provided by geoxml3 to routeboxer

- obtain the places located inside the boxes

- display the path using a polyline and place the markers for the places found

//kml file source
var kmlTrack = "greece.kml";

//create the map
var map = new google.maps.Map(document.getElementById("google_map"), {
 center: new google.maps.LatLng(39.49,20.5),
 zoom: 10,
 mapTypeId: google.maps.MapTypeId.DRIVING
});

infowindow = new google.maps.InfoWindow({});

//instantiate the geoxml library
geoXml = new geoXML3.parser({
 map: map,
 infoWindow: infowindow,
 singleInfoWindow: true,
 zoom: true,
 markerOptions: {optimized: false},
 createMarker: function() {},
 //the function called after parsing the kml file
 afterParse: useTheData
});

geoXml.parse(kmlTrack);


//placing a marker on the map
function createMarker(map, coords, title) {
 var marker = new google.maps.Marker({
  position: coords,
  map: map,
  title: title,
  draggable: false
 });
 return marker;
}

//Search places having coordinates inside the boxes
function findPlaces(boxes) {
 var data = "";
 for (var i = 0; i < boxes.length; i++) {
  //form the query string that will be sent via ajax
  if (data != "") {
   data += "&";
  }
  data += "boxes[]=" + boxes[i].getNorthEast().lat() + ":" + boxes[i].getNorthEast().lng() + "-" + boxes[i].getSouthWest().lat() + ":" + boxes[i].getSouthWest().lng();
 }

 if (data != "") {
  //make an ajax request to query the database
  //the JSON response
  var response = '[{"title":"Dodona Site","latitude":"39.546135","longitude":"20.785105"},{"title":"Perama Cave","latitude":"39.695000","longitude":"20.846457"},{"title":"Trikorfo Castle","latitude":"39.298645","longitude":"20.367601"}]';
  var places= JSON.parse(response);
  for (i in places) {
   var coords = new google.maps.LatLng(places[i].latitude, places[i].longitude);
   createMarker(map, coords, places[i].title);
  }
 }
}

function useTheData(doc) {
 var boxes, placemark;
 var distance = 0.3; // km
 var geoXmlDoc = doc[0];
 //instantiate the RouteBoxer library
 var routeBoxer = new RouteBoxer();
 var currentBounds = map.getBounds();

 if (!currentBounds) {
  currentBounds = new google.maps.LatLngBounds();
 }

 for (var i = 0; i < geoXmlDoc.placemarks.length; i++) {
  placemark = geoXmlDoc.placemarks[i];
  if (placemark.track) {
   if (placemark.track.coordinates.length > 0) {
    var path = [];
    var maxPointsCount = 300;
    //if we have too many points on the track, we skip some
    if (placemark.track.coordinates.length > maxPointsCount) {
     var step = Math.ceil(placemark.track.coordinates.length / maxPointsCount);
     for (var i = 0; i < placemark.track.coordinates.length; i += step) {
      path.push(placemark.track.coordinates[i]);
     }
    } else {
     path = placemark.track.coordinates;
    }

    //Display the track using a polyline
    polyline = new google.maps.Polyline(pathOptions = {
     path: path,
     geodesic: true,
     strokeColor: '#FF0000',
     strokeWeight: 2,
     strokeOpacity: 1.0,
     opacity: 0.4,
     map: map
    });

    boxes = routeBoxer.box(path, distance);
    findPlaces(boxes, map);
   }
  }
 }
}

You can find attached a working example, but it should be placed on a server, as the geoxml3 makes an ajax request to get the kml file.

Download files:


Leave a Comment:

User
Email
Website

Blog Search

Popular Blog Categories

Newsletter

Want to be informed about latest posts? Subscribe to our newsletter