Retrieving Travel Times from a Multiple Travel Times Distance Matrix
A multiple travel times distance matrix is an extended version of the distance matrix where a travel time profile A profile is a collection of parameters used to configure the request. Full profiles consist of a number of specialized sub-profiles like the VehicleProfile which describes the properties of a vehicle. is stored between two locations.
Benefits
- The travel times can be requested for a specific point in time in the horizon.
- The travel time profiles can also be retrieved efficiently with one call to the service.
Prerequisites
Please ensure following prerequisites are fulfilled before you start with the use case:
- Installed and licensed PTV xDima service
Concepts
Programming Guide
The creation of a multiple travel times distance matrix is performed using the matrix call createDistanceMatrix by passing the origin and destination coordinates and the multiple travel times consideration scenario with a horizon.
var request = {
"distanceMatrixOptions": {
"timeConsideration": {
"$type": "MultipleTravelTimesConsideration",
"horizon": {
"$type": "StartEndInterval",
"start": "2023-03-09T00:00:00+01:00",
"end": "2023-03-10T00:00:00+01:00"
}
}
},
"startLocations": [
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.13565, "y": 49.4806576}
},
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.06479, "y": 49.62127}
}
],
"destinationLocations": [
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.125657, "y": 49.4816576}
},
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.16678, "y": 49.455127}
}
]
};
xdima.createDistanceMatrix(request, responseCallback);
Once the distance matrix is created it is possible to request the travel times at a specific point in time included in the horizon used for the calculation.
var request = {
"$type": "GetDistanceMatrixByRelationsRequest",
"id": response.summary.id,
"resultFields": {
"distanceMatrixContentsResultFields": {
"travelTimes": true
}
},
"relations": [{
"startLocation":
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.13565, "y": 49.4806576}
},
"destinationLocation":
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.125657, "y": 49.4816576}
}
}],
"contentsOptions": {
"startTime": "2023-03-09T12:00:00+01:00"
}
};
xdima.getDistanceMatrix(request, responseCallback);
or even requesting the complete travel time profile through the encoded arrays content options (please note that the travelTimes result field should be disabled explicitly as it is not compatible).
var request = {
"$type": "GetDistanceMatrixByRelationsRequest",
"id": response.summary.id,
"resultFields": {
"distanceMatrixContentsResultFields": {
"travelTimes": false,
"travelTimeProfiles":true
}
},
"relations": [{
"startLocation":
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.13565, "y": 49.4806576}
},
"destinationLocation":
{
"$type": "OffRoadRouteLocation",
"offRoadCoordinate": {"x": 6.125657, "y": 49.4816576}
}
}],
"contentsOptions": {
"returnEncodedArrays": true
}
};
xdima.getDistanceMatrix(request, responseCallback);
The following example shows to create and calculate a multiple travel times distance matrix, retrieve the travel time for a specific start time and delete the dima afterwards:
const startLocations = [{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.1037323682103315, "y": 49.60588624310334 } }]; const destinationLocations = [{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.172880691010506, "y": 49.60588624310334 } },{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.1529654781157905, "y": 49.61112799252659 } }]; const startTime = "2023-03-09T08:00:00+01:00"; const horizon = { start: "2023-03-09T00:00:00+01:00", end: "2023-03-10T00:00:00+01:00", }; const createRequest = { "$type": "CreateDistanceMatrixRequest", "storedProfile": "van", "requestProfile": { "featureLayerProfile": { "themes": [{ "id": "PTV_SpeedPatterns", "enabled": true }] } }, "startLocations": startLocations, "destinationLocations": destinationLocations, "distanceMatrixOptions": { "routingType": "CONVENTIONAL", "timeConsideration": { "$type": "MultipleTravelTimesConsideration", "horizon": { "$type": "StartEndInterval", "start": horizon.start, "end": horizon.end } } } }; xdima.createDistanceMatrix(createRequest, createDimaCallback); function createDimaCallback(response, exception) { var request = { "$type": "GetDistanceMatrixByRelationsRequest", "id": response.summary.id, "resultFields": { "distanceMatrixContentsResultFields": { "travelTimes": true } }, "relations": [{ "startLocation": startLocations[0], "destinationLocation": destinationLocations[0] }], "contentsOptions": { "startTime": startTime } }; xdima.getDistanceMatrix(request, function(result, exception) { getDistanceMatrixCallback(result, response.summary.id, exception); }); } function getDistanceMatrixCallback(response, id, exception) { print("The travel time from " + JSON.stringify(startLocations[0].offRoadCoordinate) + " to " + JSON.stringify(destinationLocations[0].offRoadCoordinate) + " at " + startTime.substring(11, startTime.length) + " is " + response.contents.travelTimes[0]); var deleteRequest = { "id": id }; xdima.deleteDistanceMatrix(deleteRequest); }The following example shows to create and calculate a multiple travel times distance matrix, retrieve the travel time profiles with encoded binary arrays and delete the dima afterwards:
const startLocations = [{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.1037323682103315, "y": 49.60588624310334 } }]; const destinationLocations = [{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.172880691010506, "y": 49.60588624310334 } },{ "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 6.1529654781157905, "y": 49.61112799252659 } }]; const createRequest = { "$type": "CreateDistanceMatrixRequest", "storedProfile": "van", "requestProfile": { "featureLayerProfile": { "themes": [{ "id": "PTV_SpeedPatterns", "enabled": true }] } }, "startLocations": startLocations, "destinationLocations": destinationLocations, "distanceMatrixOptions": { "routingType": "CONVENTIONAL", "timeConsideration": { "$type": "MultipleTravelTimesConsideration", "horizon": { "$type": "StartEndInterval", "start": "2023-03-09T00:00:00+01:00", "end": "2023-03-10T00:00:00+01:00" } } } }; xdima.createDistanceMatrix(createRequest, createDimaCallback); function createDimaCallback(response, exception) { const request = { "$type": "GetDistanceMatrixByLocationsRequest", "id" : response.summary.id, "startLocations": startLocations, "destinationLocations": destinationLocations, "resultFields": { "travelTimes": false, "travelTimeProfiles": true }, "resultFields": { "summary": true, "distanceMatrixContentsResultFields": { "travelTimes": false, "travelTimeProfiles": true } }, "contentsOptions": { "returnEncodedArrays": true } }; xdima.getDistanceMatrix(request, getDistanceMatrixCallback); } function convertBase64ToByteArray(base64Content) { const stringContent = atob(base64Content); const length = stringContent.length; let byteArray = new Uint8Array(length); for (let i = 0; i < length; ++i) { byteArray[i] = stringContent.charCodeAt(i); } return byteArray; }; function decodeTravelTimeProfiles(byteArray, numberOfProfiles) { const view = new DataView(byteArray.buffer); let profiles = []; let offset = 0; while (numberOfProfiles != 0) { const minimumTravelTime = view.getUint32(offset, true) / 1000.0; offset += 4; const n = view.getUint8(offset); offset += 1; let profile = []; for (let i = 0; i < n; ++i) { const x = view.getUint16(offset, true); offset += 2; const y = view.getUint16(offset, true); offset += 2; profile.push([x, minimumTravelTime + y]); } profiles.push(profile); --numberOfProfiles; } return profiles; } function getDistanceMatrixCallback(response, exception) { const byteArray = convertBase64ToByteArray(response.contents.travelTimeProfiles); const profiles = decodeTravelTimeProfiles(byteArray, startLocations.length * destinationLocations.length); const profile = profiles[0]; let description = profiles.length + " travel time profiles decoded, overview of the first one: "; if (profile.length == 0) { description += "no travel time profile (was estimated by airline distance)"; } else if (profile.length == 1) { description += JSON.stringify(profile[0]); } else { const excerpt = JSON.stringify(profile.slice(0, Math.min(5, profile.length - 1))); description += excerpt.substring(1, excerpt.length - 1) + "..." + JSON.stringify(profile[profile.length - 1]); } print(description); const deleteRequest = { "id": response.summary.id }; xdima.deleteDistanceMatrix(deleteRequest); };Related Topics
The following topics might be relevant for this use case.