Question

I have a Google Map that displays service stations across mainland Europe and can calculate routes between two locations. However, because there are a lot of stations, the map can look quite busy. I therefore want to only show markers that follow the route my google directions have given.

I thought about tracing the directions with a polyline and perhaps using an intercept, but I can't think of how to talk to the database. My current example shows the directions with an red polyline but with all the markers showing.

The code for the javascript is:

//<![CDATA[

var customIcons = {
  as24: {
    icon: 'images/as24.png'
  },
  pearson: {
    icon: 'images/p.png'
  }
};

var rendererOptions = {
draggable: true
};
var directionsDisplay = new google.maps.DirectionsRenderer(rendererOptions);
var directionsService = new google.maps.DirectionsService();
var map, trafficLayer;
var europe = new google.maps.LatLng(-25.274398, 133.775136);

function initialize() {

var mapOptions = {
zoom: 6,
center: europe
};

map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

directionsDisplay.setMap(map);
directionsDisplay.setPanel(document.getElementById('directionsPanel'));

google.maps.event.addListener(directionsDisplay, 'directions_changed', function() {
computeTotalDistance(directionsDisplay.getDirections());
});

trafficLayer = new google.maps.TrafficLayer();
    trafficLayer.setMap(map);

    var control = document.getElementById('traffic-wpr');
    map.controls[google.maps.ControlPosition.TOP_RIGHT].push(control);

    google.maps.event.addDomListener(control, 'click', function() {
      trafficLayer.setMap(trafficLayer.getMap() ? null : map);
    });

 calcRoute();
 }



function calcRoute() {
var start = document.getElementById('start').value;
var end = document.getElementById('end').value;
var request = {
  origin:start,
  destination:end,
  //waypoints:[{location: 'London, England'}, {location: 'Paris, France'}],
  travelMode: google.maps.TravelMode.DRIVING
 };
 directionsService.route(request, function(response, status) {
 if (status == google.maps.DirectionsStatus.OK) {
  directionsDisplay.setDirections(response);
 }
var polyline = new google.maps.Polyline({
 path: [],
 strokeColor: "#FF0000",
        strokeOpacity: 0.2,
        strokeWeight: 30,
        fillColor: "#FF0000",
        fillOpacity: 0.35
});
var bounds = new google.maps.LatLngBounds();


var legs = response.routes[0].legs;
for (i=0;i<legs.length;i++) {
var steps = legs[i].steps;
for (j=0;j<steps.length;j++) {
var nextSegment = steps[j].path;
for (k=0;k<nextSegment.length;k++) {
  polyline.getPath().push(nextSegment[k]);
  bounds.extend(nextSegment[k]);


 }
 }
}



polyline.setMap(map);
map.fitBounds(bounds);

 });
}



function computeTotalDistance(result) {
var total = 0;
var myroute = result.routes[0];
for (var i = 0; i < myroute.legs.length; i++) {
total += myroute.legs[i].distance.value;
}
total = total / 1000.0;
document.getElementById('total').innerHTML = total + ' km';
}
google.maps.event.addDomListener(window, 'load', initialize);


function load() {

  var infoWindow = new google.maps.InfoWindow;

  // Change this depending on the name of your PHP file
  downloadUrl("as24_genxml.php", function(data) {
    var xml = data.responseXML;
    var markers = xml.documentElement.getElementsByTagName("marker");
    for (var i = 0; i < markers.length; i++) {
      var name = markers[i].getAttribute("name");
      var address = markers[i].getAttribute("address");
      var price = markers[i].getAttribute("price");
      var type = markers[i].getAttribute("type");
      var point = new google.maps.LatLng(
          parseFloat(markers[i].getAttribute("lat")),
          parseFloat(markers[i].getAttribute("lng")));
      var html = "<b>" + name + " " + price + "</b> <br/>" + address;
      var icon = customIcons[type] || {}; 
      var marker = new google.maps.Marker({
        map: map,
        position: point,
        icon: icon.icon
      });
      map.getBounds().contains(marker.getPosition())
      bindInfoWindow(marker, map, infoWindow, html);
    }
  });
}

function bindInfoWindow(marker, map, infoWindow, html) {
  google.maps.event.addListener(marker, 'click', function() {
    infoWindow.setContent(html);
    infoWindow.open(map, marker);
  });
}

function downloadUrl(url, callback) {
  var request = window.ActiveXObject ?
      new ActiveXObject('Microsoft.XMLHTTP') :
      new XMLHttpRequest;

  request.onreadystatechange = function() {
    if (request.readyState == 4) {
      request.onreadystatechange = doNothing;
      callback(request, request.status);
    }
  };

  request.open('GET', url, true);
  request.send(null);
}




function doNothing() {}

//]]>

The code for the markers (as24_genxml.php) is:

<?php include ('php/config.php');

function parseToXML($htmlStr) 
{ 
$xmlStr=str_replace('<','&lt;',$htmlStr); 
$xmlStr=str_replace('>','&gt;',$xmlStr); 
$xmlStr=str_replace('"','&quot;',$xmlStr); 
$xmlStr=str_replace("'",'&#39;',$xmlStr); 
$xmlStr=str_replace("&",'&amp;',$xmlStr); 
return $xmlStr; 
} 

// Opens a connection to a MySQL server
$connection=mysql_connect (localhost, $mysql_user, $mysql_pass);
if (!$connection) {
die('Not connected : ' . mysql_error());
}

// Set the active MySQL database
$db_selected = mysql_select_db($mysql_db, $connection);
if (!$db_selected) {
  die ('Can\'t use db : ' . mysql_error());
}

// Select all the rows in the markers table
$query = "SELECT * FROM as24 WHERE 1";
$result = mysql_query($query);
if (!$result) {
  die('Invalid query: ' . mysql_error());
}

header("Content-type: text/xml");

// Start XML file, echo parent node
echo '<markers>';

// Iterate through the rows, printing XML nodes for each
while ($row = @mysql_fetch_assoc($result)){
  // ADD TO XML DOCUMENT NODE
  echo '<marker ';
  echo 'name="' . parseToXML($row['name']) . '" ';
  echo 'address="' . parseToXML($row['address']) . '" ';
  echo 'price="' . parseToXML($row['price']) . '" ';
  echo 'lat="' . $row['lat'] . '" ';
  echo 'lng="' . $row['lng'] . '" ';
  echo 'type="' . $row['type'] . '" ';
  echo '/>';
}

// End XML file
echo '</markers>';

?>

I can't seem to find anyone else that has a similar problem. I may be overcomplicating things by using the polyline?

Was it helpful?

Solution

Ok, I'm not sure if I'm over-complicating this to be honest but if you merely want the map to look less cluttered then you don't need to change anything in the back-end (presuming you're having no performance issues, I'm unsure how many points we're talking about here. All you need to do is check the distance between each coordinate on the polyline and each 'service station' marker.

An example of how to achieve this is available in the first part of the answer here. You can even hide the polyline to further reduce clutter, or remove it and use the coordinates within each path segment to achieve the same effect.

This could however be an issue if you have a lot of points to check and long routes. The only way to know for sure will be to try it, but the asymptotic complexity is not great.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top