Calculating a route with rectangular geographic restrictions
This use-case describes how to calculate a route A route corresponds to a path of a vehicle through the underlying transport network. The main attributes of a route are the distance and the time that the vehicle travels along the path. with rectangular geographic restrictions.
Benefits
- Using the xRoute API makes it easy to obtain routes based on rectangular geographic restrictions.
- Using the xData API makes it easy to create new high-performance routing networks using search space bounds.
- Using the rectangular geographic restrictions could enhance the performance especially for the creation of high-performance routing networks and distance matrices.
Prerequisites
Please ensure following prerequisites are fulfilled before you start with the use case:
- Installed and licensed PTV xData service
- Installed and licensed PTV xRoute service
Programming Guide
In this example we provide our waypoints A waypoint is a geographic location used to specify start, destination and possible stopovers for a route. A, B and C as x, y coordinates in the default EPSG:4326 format (see RequestBase.coordinateFormat
).
At the very beginning a high-performance routing network with rectangular geographic restrictions is calculated.
A calculateRoute
is then done with routing type HIGH_PERFORMANCE_ROUTING to use the high-performance routing network previously calculated.
Once xRoute has processed the request, the callback routingCompleted
is invoked which gives us access to the result of the calculation in the form of a RouteResponse
object which contains the response routing type.
After the route is calculated successfully, the high-performance routing network is deleted.
One of the downsides when using rectangular geographic restrictions is that we can get a wrong (or bad) route because of the limitation of search bounds. This problem is illustrated with the next two samples.
This first example below shows how to request a calculateRoute when the search space bounds have no effect on the route. The rectangle is big enough to contain the optimal route.
var options = { "geographicRestrictions": { "allowedCountries": [ "LU" ], "searchSpaceBounds": { "restrictionMode": "CUSTOM", "customBounds": { "minX": "6.10", "maxX": "6.35", "minY": "49.47", "maxY": "49.63" } } }, }; job = xdata.startCreateHighPerformanceRoutingNetwork({ "label": "Luxembourg with a high-performance routing network calculated with rectangular geographic restrictions.", "highPerformanceRoutingNetworkOptions": options }); var id = waitForJobToFinish(job); function waitForJobToFinish(job, exception) { while (job.status == "RUNNING" || job.status == "QUEUING") { job = xdata.watchJob({ "id": job.id }); } if (job.status == "SUCCEEDED") { return xdata.fetchHighPerformanceRoutingNetworkResponse(job.id).id; } else { return null; } }; var A = { "$type": "OffRoadWaypoint", "location": { "offRoadCoordinate": {"x": 6.1256572, "y": 49.5983745 } } }; var B = { "$type": "OnRoadWaypoint", "location": { "coordinate": {"x": 6.1256572, "y": 49.4816576 } } }; var C = { "$type": "OffRoadWaypoint", "location": { "offRoadCoordinate": {"x": 6.3256572, "y": 49.5516576 } } }; var map = new L.Map('map', { center: [49.61, 6.125], zoom: 13 }); // Add tile layer to map var tileUrl = xServerUrl + '/services/rest/XMap/tile/{z}/{x}/{y}'; var tileLayer = new L.TileLayer(tileUrl, { minZoom: 3, maxZoom: 18, noWrap: true }).addTo(map); xroute.calculateRoute({ "waypoints" : [A, C, B], "resultFields" : { "report" : "true", "polyline" : true }, "routeOptions" : { "routingType": "HIGH_PERFORMANCE_ROUTING", "geographicRestrictions": options.geographicRestrictions, "polylineOptions" : { "elevations" : true } } }, routingFinished); function convert2LatLong(x, y) { var ll = proj4('EPSG:4326' ,'EPSG:4326', {x: x, y: y}); return L.latLng([ll.y, ll.x]); }; function displayPolyline(poly) { var polyline = []; for (var i = 0; i < poly.length;++i) { polyline.push(L.latLng(poly[i].y, poly[i].x)); } polylineLayer = L.polyline(polyline, { color: '#2882C8', weight: 8 }); polylineLayer.addTo(map); map.fitBounds(polylineLayer.getBounds()); }; function routingFinished(route, exception) { var polyline = route.polyline.plain.polyline; displayPolyline(polyline); var southWest = convert2LatLong(options.geographicRestrictions.searchSpaceBounds.customBounds.minX, options.geographicRestrictions.searchSpaceBounds.customBounds.maxY); var northEast = convert2LatLong(options.geographicRestrictions.searchSpaceBounds.customBounds.maxX, options.geographicRestrictions.searchSpaceBounds.customBounds.minY); rectangle = L.rectangle(L.latLngBounds(southWest, northEast), {}); rectangle.addTo(map); print(route.distance + 'm in ' + route.travelTime + 's starting at ' + polyline[0].z + 'm elevation' + ' routing type ' + route.report.routingType ); xdata.deleteHighPerformanceRoutingNetwork({ "id": id }); }This second example below shows how to request a calculateRoute when the search space bounds have an effect on the route. The route is modified so as it doesn't go beyond the rectangle. The results show that this is not the optimal route.
var options = { "geographicRestrictions": { "allowedCountries": [ "LU" ], "searchSpaceBounds": { "restrictionMode": "CUSTOM", "customBounds": { "minX": "6.10", "maxX": "6.35", "minY": "49.47", "maxY": "49.60" } } }, }; job = xdata.startCreateHighPerformanceRoutingNetwork({ "label": "Luxembourg with a high-performance routing network calculated with rectangular geographic restrictions.", "highPerformanceRoutingNetworkOptions": options }); var id = waitForJobToFinish(job); function waitForJobToFinish(job, exception) { while (job.status == "RUNNING" || job.status == "QUEUING") { job = xdata.watchJob({ "id": job.id }); } if (job.status == "SUCCEEDED") { return xdata.fetchHighPerformanceRoutingNetworkResponse(job.id).id; } else { return null; } }; var A = { "$type": "OffRoadWaypoint", "location": { "offRoadCoordinate": {"x": 6.1256572, "y": 49.5983745 } } }; var B = { "$type": "OnRoadWaypoint", "location": { "coordinate": {"x": 6.1256572, "y": 49.4816576 } } }; var C = { "$type": "OffRoadWaypoint", "location": { "offRoadCoordinate": {"x": 6.3256572, "y": 49.5516576 } } }; var map = new L.Map('map', { center: [49.61, 6.125], zoom: 13 }); // Add tile layer to map var tileUrl = xServerUrl + '/services/rest/XMap/tile/{z}/{x}/{y}'; var tileLayer = new L.TileLayer(tileUrl, { minZoom: 3, maxZoom: 18, noWrap: true }).addTo(map); xroute.calculateRoute({ "waypoints" : [A, C, B], "resultFields" : { "report" : "true", "polyline" : true }, "routeOptions" : { "routingType": "HIGH_PERFORMANCE_ROUTING", "geographicRestrictions": options.geographicRestrictions, "polylineOptions" : { "elevations" : true } } }, routingFinished); function convert2LatLong(x, y) { var ll = proj4('EPSG:4326' ,'EPSG:4326', {x: x, y: y}); return L.latLng([ll.y, ll.x]); }; function displayPolyline(poly) { var polyline = []; for (var i = 0; i < poly.length;++i) { polyline.push(L.latLng(poly[i].y, poly[i].x)); } polylineLayer = L.polyline(polyline, { color: '#2882C8', weight: 8 }); polylineLayer.addTo(map); map.fitBounds(polylineLayer.getBounds()); }; function routingFinished(route, exception) { var polyline = route.polyline.plain.polyline; displayPolyline(polyline); var southWest = convert2LatLong(options.geographicRestrictions.searchSpaceBounds.customBounds.minX, options.geographicRestrictions.searchSpaceBounds.customBounds.maxY); var northEast = convert2LatLong(options.geographicRestrictions.searchSpaceBounds.customBounds.maxX, options.geographicRestrictions.searchSpaceBounds.customBounds.minY); rectangle = L.rectangle(L.latLngBounds(southWest, northEast), {}); rectangle.addTo(map); print(route.distance + 'm in ' + route.travelTime + 's starting at ' + polyline[0].z + 'm elevation' + ' routing type ' + route.report.routingType ); xdata.deleteHighPerformanceRoutingNetwork({ "id": id }); }Please refer to the documentation of the RouteRequest
for more information on request parameterization.
The rectangular geographic restrictions with search space bounds can even be used in a calculateRoute request without high-performance routing networks.