This is not really an answer to the question, but it might help you.
I put the locations in sortable boxes (jQuery-UI).
So you can easily change the order (also the start and end) and check again.
Optimizing routing is not easy. I don't see any obvious solution.
You might have to use algorithms like Dijkstra.
If anyone has suggestion; they are welcome.
<!DOCTYPE html>
<html>
<head>
<title></title>
<meta name="viewport" content="initial-scale=1.0, user-scalable=no">
<meta charset="utf-8">
<link rel="stylesheet" href="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/themes/smoothness/jquery-ui.css" />
<style>
#map-canvas {
height: 500px;
width: 48%;
float: left;
margin: 0px;
padding: 0px
}
ul.sortable {
height: 500px;
width: 48%;
float: left;
overflow-y: auto;
}
ul.sortable li {
border: 1px solid #eee;
margin: 2px;
cursor: pointer;
}
</style>
<script src="https://maps.googleapis.com/maps/api/js?v=3.exp"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.11.2/jquery-ui.min.js"></script>
<script>
// list of some locations in Brussels
var locations = [
{lat: 50.8949444353626, lng: 4.34153383970260, title: 'Atomium'},
{lat: 50.8224796094648, lng: 4.39153021574020, title: 'VUB'},
{lat: 50.8348811096048, lng: 4.29784601926803, title: 'RSCA stadion'},
{lat: 50.8471595652635, lng: 4.34852904081344, title: 'AB'},
{lat: 50.8390463848631, lng: 4.37321072816848, title: 'European parliament'},
];
var locationsOrdered = [];
// generates the <li> items
function generateListItems(items) {
var content='';
for(var i=0; i<items.length; i++) {
content += '<li data-id="' + i + '">' + items[i].title + '</li>';
}
return content;
}
var map;
function initialize() {
directionsDisplay = new google.maps.DirectionsRenderer();
// generates the <li> items, add them to ul.sortable
var ul = generateListItems(locations);
$('ul.sortable').html(ul);
// make the <ul> sortable with jQuery-UI
locationsOrdered = locations;
$('ul.sortable').sortable({
stop: function(event, ui) {
// update the order of the items
locationsOrdered = [];
$('ul.sortable li').each(function( key, value ) {
var index = $(value).data('id'); // reads the data-id="X"; this value is the original order
locationsOrdered.push(locations[index]);
});
}
});
var my_position = new google.maps.LatLng(50.84715956, 4.3485290);
map = new google.maps.Map(document.getElementById('map-canvas'), {
center: my_position,
zoom: 12
});
directionsDisplay.setMap(map);
}
google.maps.event.addDomListener(window, 'load', initialize);
var directionsDisplay;
var directionsService = new google.maps.DirectionsService();
// based on https://developers.google.com/maps/documentation/javascript/examples/directions-waypoints
function calcRoute(locationsOrdered) {
// optimize? read the checkbox
var optimize = $('#optimize').prop('checked');
// clear all previous overlays, and distance display
directionsDisplay.setMap(null);
$('#log').empty();
//
var length = locationsOrdered.length;
var start = new google.maps.LatLng(locationsOrdered[0].lat, locationsOrdered[0].lng);
var end = new google.maps.LatLng(locationsOrdered[length - 1].lat, locationsOrdered[length - 1].lng);
var waypts = [];
var checkboxArray = document.getElementById('waypoints');
for (var i=1; i < locationsOrdered.length - 1; i++) {
waypts.push({
location: new google.maps.LatLng(locationsOrdered[i].lat, locationsOrdered[i].lng),
stopover: true
});
}
var request = {
origin: start,
destination: end,
waypoints: waypts,
optimizeWaypoints: optimize, // depends on the checkbox
travelMode: google.maps.TravelMode.DRIVING
};
directionsService.route(request, function(response, status) {
if (status == google.maps.DirectionsStatus.OK) {
// as Google changes the order of the waypoints, we will update the order of the <li> items
var waypoint_order = response.routes[0].waypoint_order;
for (var i=0; i<waypoint_order.length; i++) {
swapLiItem(i + 1, waypoint_order[i] + 1); // the + 1 is because the start point is not a waypoint, but it is an <li>
}
// route display
directionsDisplay.setDirections(response);
var route = response.routes[0];
// display the distances
var totalDistance = 0;
log('Waypoint distances: <br>');
for (var i = 0; i < route.legs.length; i++) {
totalDistance += route.legs[i].distance.value;
log(i +': ' + route.legs[i].distance.text + '<br>');
}
log('Total distance: ' + (totalDistance / 1000) + 'km');
directionsDisplay.setMap(map);
}
});
}
// How to set sortable items manually.
// @see http://stackoverflow.com/questions/9981563/jquery-ui-sortable-set-manually-a-position
function swapLiItem(from, to) {
$('ul.sortable li:eq(' + from + ')').insertAfter($('ul.sortable li:eq(' + to + ')'));
}
// writes a message in <div id=log"></div>
function log(message) {
$('#log').append(message);
}
</script>
</head>
<body>
<div id="map-canvas"></div>
<ul class="sortable"></ul>
<input type="button" id="go" value="Go" onclick="calcRoute(locationsOrdered)"><br>
<input type="checkbox" id="optimize" checked="checked"> auto optimize waypoints
<hr>
<div id="log"></div>
</body>
</html>