OpenLayers routing map

Important

The content of this page is outdated and is for archiving purposes only.

  • Open text editor (i.e. Gedit, Mousepad)
  • Google key: you don’t need a valid key if you’re working on localhost
  • Note: these examples are not compatible with the latest stable version of OpenLayers (version 2.5). If you want to update the code, please look at: http://trac.openlayers.org/wiki/SphericalMercator

Starting page (00.index.html)

  • Create a basic html:
  • include OpenLayers and Google maps API javascript files
  • create an empty div to receive the OpenLayers map
  • create an empty init function. The function will be called on page load (see onload in the body tag)
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">
            function init() { }
        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>
  </body>
</html>

Design basic map layers (01.index.html)

  • Create an OpenLayers map object
  • Create and Controls to the maps (layer switcher and mouse position)
  • Create a Google Satellite layer and add it to the map
  • Recenter the map to a specified extent
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">
            // global variables
            var map;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});

                map.addLayers([satellite]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));
            }
        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>
  </body>
</html>

Create a Vector layer and draw a polygon on it (02.index.html)

  • Create a custom style for the vector layer
  • Create a Vector layer and add it to the map
  • Create a WKT parser and read a polygon, this create an OpenLayers.Geometry.Polygon object
  • Create a OpenLayers.Feature.Vector with the polygon and add it to the vector layer
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">
             var result_style = OpenLayers.Util.applyDefaults({
                 strokeWidth: 3,
                 strokeColor: "#ff0000",
                 fillOpacity: 0
             }, OpenLayers.Feature.Vector.style['default']);

            // global variables
            var map, parser, result, downtown;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});
                downtown = new OpenLayers.Layer.Vector("Downtown data area",
                                                     {style: result_style});
                result = new OpenLayers.Layer.Vector("Routing results",
                                                     {style: result_style});

                map.addLayers([satellite, downtown, result]);

                // create a feature from a wkt string and add it to the map
                parser = new OpenLayers.Format.WKT();
                var wkt = "POLYGON((-13737893 6151394, -13737893 6141906, -13728396 6141906, -13728396 6151394, -13737893 6151394))";
                var geometry = parser.read(wkt);
                var feature = new OpenLayers.Feature.Vector(geometry);
                downtown.addFeatures([feature]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));
            }
        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>
  </body>
</html>

“set start/end point” tool (03.index.html)

  • Create two more vector layers with custom style
  • Create the two drawing tools (OpenLayers.Control.!DrawFeature), those tools can only draw point (OpenLayers.Handler.Point)
  • The toggleControl function set the active tool
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">

            var start_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "start.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

            var stop_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "stop.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

             var result_style = OpenLayers.Util.applyDefaults({
                 strokeWidth: 3,
                 strokeColor: "#ff0000",
                 fillOpacity: 0
             }, OpenLayers.Feature.Vector.style['default']);

            // global variables
            var map, parser, start, stop, downtown, result, controls;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});
                start = new OpenLayers.Layer.Vector("Start point", {style: start_style});
                stop = new OpenLayers.Layer.Vector("End point", {style: stop_style});
                downtown = new OpenLayers.Layer.Vector("Downtown data area",
                                                     {style: result_style});
                result = new OpenLayers.Layer.Vector("Routing results",
                                                     {style: result_style});

                map.addLayers([satellite, start, stop, downtown,result]);

                // create a feature from a wkt string and add it to the map
                parser = new OpenLayers.Format.WKT();
                var wkt = "POLYGON((-13737893 6151394, -13737893 6141906, -13728396 6141906, -13728396 6151394, -13737893 6151394))";
                var geometry = parser.read(wkt);
                var feature = new OpenLayers.Feature.Vector(geometry);
                downtown.addFeatures([feature]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));

                // controls
                controls = {
                  start: new OpenLayers.Control.DrawFeature(start, OpenLayers.Handler.Point),
                  stop: new OpenLayers.Control.DrawFeature(stop, OpenLayers.Handler.Point)
                }
                for (var key in controls) {
                    map.addControl(controls[key]);
                }
            }

            function toggleControl(element) {
                for (key in controls) {
                    if (element.value == key && element.checked) {
                        controls[key].activate();
                    } else {
                        controls[key].deactivate();
                    }
                }
            }
        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>

        <ul>
          <li>
            <input type="radio" name="control" id="noneToggle"
                   onclick="toggleControl(this);" checked="checked" />
            <label for="noneToggle">navigate</label>
          </li>
          <li>
            <input type="radio" name="control" value="start" id="startToggle"
                   onclick="toggleControl(this);" />
            <label for="startToggle">set start point</label>
          </li>
          <li>
            <input type="radio" name="control" value="stop" id="stopToggle"
                   onclick="toggleControl(this);" />
            <label for="stopToggle">set stop point</label>
          </li>
        </ul>

  </body>
</html>

Customize the tools (04.index.html)

  • Create a custom OpenLayers.Handler.Point handle: !SinglePoint. This handler only draw one point on the layer
  • Add a method selector
  • Create the “compute” button with the callback function (empty for now)
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">

            var SinglePoint = OpenLayers.Class.create();
            SinglePoint.prototype = OpenLayers.Class.inherit(OpenLayers.Handler.Point, {
                createFeature: function(evt) {
                    this.control.layer.removeFeatures(this.control.layer.features);
                    OpenLayers.Handler.Point.prototype.createFeature.apply(this, arguments);
                }
            });

            var start_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "start.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

            var stop_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "stop.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

             var result_style = OpenLayers.Util.applyDefaults({
                 strokeWidth: 3,
                 strokeColor: "#ff0000",
                 fillOpacity: 0
             }, OpenLayers.Feature.Vector.style['default']);

            // global variables
            var map, parser, start, stop, downtown, result, controls;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});
                start = new OpenLayers.Layer.Vector("Start point", {style: start_style});
                stop = new OpenLayers.Layer.Vector("End point", {style: stop_style});
                downtown = new OpenLayers.Layer.Vector("Downtown data area",
                                                     {style: result_style});
                result = new OpenLayers.Layer.Vector("Routing results",
                                                     {style: result_style});

                map.addLayers([satellite, start, stop, downtown,result]);

                // create a feature from a wkt string and add it to the map
                parser = new OpenLayers.Format.WKT();
                var wkt = "POLYGON((-13737893 6151394, -13737893 6141906, -13728396 6141906, -13728396 6151394, -13737893 6151394))";
                var geometry = parser.read(wkt);
                var feature = new OpenLayers.Feature.Vector(geometry);
                downtown.addFeatures([feature]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));

                // controls
                controls = {
                  start: new OpenLayers.Control.DrawFeature(start, SinglePoint),
                  stop: new OpenLayers.Control.DrawFeature(stop, SinglePoint)
                }
                for (var key in controls) {
                    map.addControl(controls[key]);
                }
            }

            function toggleControl(element) {
                for (key in controls) {
                    if (element.value == key && element.checked) {
                        controls[key].activate();
                    } else {
                        controls[key].deactivate();
                    }
                }
            }

            function compute() { }

        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>

        <ul>
          <li>
            <input type="radio" name="control" id="noneToggle"
                   onclick="toggleControl(this);" checked="checked" />
            <label for="noneToggle">navigate</label>
          </li>
          <li>
            <input type="radio" name="control" value="start" id="startToggle"
                   onclick="toggleControl(this);" />
            <label for="startToggle">set start point</label>
          </li>
          <li>
            <input type="radio" name="control" value="stop" id="stopToggle"
                   onclick="toggleControl(this);" />
            <label for="stopToggle">set stop point</label>
          </li>
        </ul>

        <select id="method">
          <option value="SPD">Shortest Path Dijkstra - undirected (BBox)</option>
          <option value="SPA">Shortest Path A Star - undirected</option>
          <option value="SPS">Shortest Path Shooting Star</option>
        </select>
        <button onclick="compute()">Calculate Route</button>

  </body>
</html>

Ask for a route (05.index.html)

  • Code the compute function:
    • Create a request object (result)
    • Use the OpenLayers !LoadUrl function to call the php script via AJAX
    • The displayRoute function will be called with the output of the php script
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">

            var SinglePoint = OpenLayers.Class.create();
            SinglePoint.prototype = OpenLayers.Class.inherit(OpenLayers.Handler.Point, {
                createFeature: function(evt) {
                    this.control.layer.removeFeatures(this.control.layer.features);
                    OpenLayers.Handler.Point.prototype.createFeature.apply(this, arguments);
                }
            });

            var start_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "start.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

            var stop_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "stop.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

             var result_style = OpenLayers.Util.applyDefaults({
                 strokeWidth: 3,
                 strokeColor: "#ff0000",
                 fillOpacity: 0
             }, OpenLayers.Feature.Vector.style['default']);

            // global variables
            var map, parser, start, stop, downtown, result, controls;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});
                start = new OpenLayers.Layer.Vector("Start point", {style: start_style});
                stop = new OpenLayers.Layer.Vector("End point", {style: stop_style});
                downtown = new OpenLayers.Layer.Vector("Downtown data area",
                                                     {style: result_style});
                result = new OpenLayers.Layer.Vector("Routing results",
                                                     {style: result_style});

                map.addLayers([satellite, start, stop, downtown,result]);

                // create a feature from a wkt string and add it to the map
                parser = new OpenLayers.Format.WKT();
                var wkt = "POLYGON((-13737893 6151394, -13737893 6141906, -13728396 6141906, -13728396 6151394, -13737893 6151394))";
                var geometry = parser.read(wkt);
                var feature = new OpenLayers.Feature.Vector(geometry);
                downtown.addFeatures([feature]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));

                // controls
                controls = {
                  start: new OpenLayers.Control.DrawFeature(start, SinglePoint),
                  stop: new OpenLayers.Control.DrawFeature(stop, SinglePoint)
                }
                for (var key in controls) {
                    map.addControl(controls[key]);
                }
            }

            function toggleControl(element) {
                for (key in controls) {
                    if (element.value == key && element.checked) {
                        controls[key].activate();
                    } else {
                        controls[key].deactivate();
                    }
                }
            }

            function compute() {
                var startPoint = start.features[0];
                var stopPoint = stop.features[0];

                if (startPoint && stopPoint) {
                    var result = {
                        startpoint: startPoint.geometry.x + ' ' + startPoint.geometry.y,
                        finalpoint: stopPoint.geometry.x + ' ' + stopPoint.geometry.y,
                        method: OpenLayers.Util.getElement('method').value,
                        region: "victoria",
                        srid: "54004"
                    };
                    OpenLayers.loadURL("./ax_routing.php",
                                       OpenLayers.Util.getParameterString(result),
                                       null,
                                       displayRoute);
                }
            }

            function displayRoute(response) {
                if (response && response.responseXML) {
                    alert(response.responseXML);
                }
            }

        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>

        <ul>
          <li>
            <input type="radio" name="control" id="noneToggle"
                   onclick="toggleControl(this);" checked="checked" />
            <label for="noneToggle">navigate</label>
          </li>
          <li>
            <input type="radio" name="control" value="start" id="startToggle"
                   onclick="toggleControl(this);" />
            <label for="startToggle">set start point</label>
          </li>
          <li>
            <input type="radio" name="control" value="stop" id="stopToggle"
                   onclick="toggleControl(this);" />
            <label for="stopToggle">set stop point</label>
          </li>
        </ul>

        <select id="method">
          <option value="SPD">Shortest Path Dijkstra - undirected (BBox)</option>
          <option value="SPA">Shortest Path A Star - undirected</option>
          <option value="SPS">Shortest Path Shooting Star</option>
        </select>
        <button onclick="compute()">Calculate Route</button>

  </body>
</html>

Show the routing result on the map (06.index.html)

  • code the displayRoute function:
    • Erase the previous result
    • Get all the <edge> tag in the XML document
    • Parse the <wkt> content of each edge and add them to the result layer
<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
        <style type="text/css">
            #map {
                width: 800px;
                height: 512px;
                border: 1px solid black;
            }
        </style>
        <script src="./OpenLayers-google/lib/OpenLayers.js"></script>
        <script src="http://maps.google.com/maps?file=api&v=2&key=foobar"></script>

        <script type="text/javascript">

            var SinglePoint = OpenLayers.Class.create();
            SinglePoint.prototype = OpenLayers.Class.inherit(OpenLayers.Handler.Point, {
                createFeature: function(evt) {
                    this.control.layer.removeFeatures(this.control.layer.features);
                    OpenLayers.Handler.Point.prototype.createFeature.apply(this, arguments);
                }
            });

            var start_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "start.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

            var stop_style = OpenLayers.Util.applyDefaults({
                externalGraphic: "stop.png",
                graphicWidth: 18,
                graphicHeight: 26,
                graphicYOffset: -26,
                graphicOpacity: 1
            }, OpenLayers.Feature.Vector.style['default']);

             var result_style = OpenLayers.Util.applyDefaults({
                 strokeWidth: 3,
                 strokeColor: "#ff0000",
                 fillOpacity: 0
             }, OpenLayers.Feature.Vector.style['default']);

            // global variables
            var map, parser, start, stop, downtown, result, controls;

            function init() {
                map = new OpenLayers.Map('map', {projection: "EPSG: 54004",
                                                 units: "m",
                                                 maxResolution: 156543.0339,
                                                 maxExtent: new OpenLayers.Bounds(-20037508,
                                                                                  -136554022,
                                                                                  20037508,
                                                                                  136554022)
                                                });
                map.addControl(new OpenLayers.Control.LayerSwitcher());
                map.addControl(new OpenLayers.Control.MousePosition());

                // create and add layers to the map
                var satellite = new OpenLayers.Layer.GoogleMercator("Google Satellite",
                                                                    {type: G_NORMAL_MAP});
                start = new OpenLayers.Layer.Vector("Start point", {style: start_style});
                stop = new OpenLayers.Layer.Vector("End point", {style: stop_style});
                downtown = new OpenLayers.Layer.Vector("Downtown data area",
                                                     {style: result_style});
                result = new OpenLayers.Layer.Vector("Routing results",
                                                     {style: result_style});

                map.addLayers([satellite, start, stop, downtown,result]);

                // create a feature from a wkt string and add it to the map
                parser = new OpenLayers.Format.WKT();
                var wkt = "POLYGON((-13737893 6151394, -13737893 6141906, -13728396 6141906, -13728396 6151394, -13737893 6151394))";
                var geometry = parser.read(wkt);
                var feature = new OpenLayers.Feature.Vector(geometry);
                downtown.addFeatures([feature]);

                // set default position
                map.zoomToExtent(new OpenLayers.Bounds(-13737893,
                                                       6141906,
                                                       -13728396,
                                                       6151394));

                // controls
                controls = {
                  start: new OpenLayers.Control.DrawFeature(start, SinglePoint),
                  stop: new OpenLayers.Control.DrawFeature(stop, SinglePoint)
                }
                for (var key in controls) {
                    map.addControl(controls[key]);
                }
            }

            function toggleControl(element) {
                for (key in controls) {
                    if (element.value == key && element.checked) {
                        controls[key].activate();
                    } else {
                        controls[key].deactivate();
                    }
                }
            }

            function compute() {
                var startPoint = start.features[0];
                var stopPoint = stop.features[0];

                if (startPoint && stopPoint) {
                    var result = {
                        startpoint: startPoint.geometry.x + ' ' + startPoint.geometry.y,
                        finalpoint: stopPoint.geometry.x + ' ' + stopPoint.geometry.y,
                        method: OpenLayers.Util.getElement('method').value,
                        region: "victoria",
                        srid: "54004"
                    };
                    OpenLayers.loadURL("./ax_routing.php",
                                       OpenLayers.Util.getParameterString(result),
                                       null,
                                       displayRoute);
                }
            }

            function displayRoute(response) {
                if (response && response.responseXML) {
                    // erase the previous results
                    result.removeFeatures(result.features);

                    // parse the features
                    var edges = response.responseXML.getElementsByTagName('edge');
                    var features = [];
                    for (var i = 0; i < edges.length; i++) {
                        var g = parser.read(edges[i].getElementsByTagName('wkt')[0].textContent);
                        features.push(g);
                    }
                    result.addFeatures(features);
                }
            }

        </script>
  </head>
  <body onload="init()">
        <div id="map"></div>

        <ul>
          <li>
            <input type="radio" name="control" id="noneToggle"
                   onclick="toggleControl(this);" checked="checked" />
            <label for="noneToggle">navigate</label>
          </li>
          <li>
            <input type="radio" name="control" value="start" id="startToggle"
                   onclick="toggleControl(this);" />
            <label for="startToggle">set start point</label>
          </li>
          <li>
            <input type="radio" name="control" value="stop" id="stopToggle"
                   onclick="toggleControl(this);" />
            <label for="stopToggle">set stop point</label>
          </li>
        </ul>

        <select id="method">
          <option value="SPD">Shortest Path Dijkstra - undirected (BBox)</option>
          <option value="SPA">Shortest Path A Star - undirected</option>
          <option value="SPS">Shortest Path Shooting Star</option>
        </select>
        <button onclick="compute()">Calculate Route</button>

  </body>
</html>