Accessing distance matrix contents with binary encoded arrays
This use-case describes how to create a distance matrix and get the content in encoded format. As the content is in the binary compact encoded arrays, here is shown how to get in uncoded format
Benefits
- Using the getDistanceMatrix with binary encoded arrays reduces the size of the data exchange especially for large contents.
Prerequisites
Please ensure following prerequisites are fulfilled before you start with the use case:
- Installed and licensed PTV xDima service
Programming Guide
Javascript
This below Javascript shows how to use in a simple way the uncoding process:
var locations = [ { "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 147.35255956649783, "y": -43.06534499935546 } }, { "$type": "OffRoadRouteLocation", "offRoadCoordinate": { "x": 147.37571239471438, "y": -43.100011493947584 } }, { "$type": "OnRoadRouteLocation", "coordinate": { "x": 147.31614589691165, "y": -43.003077911658735 } } ]; var contentsResultFields = { "distances" : true, "travelTimes" : true, "violated" : true, "estimatedByDirectDistance" : true, }; var resultFields = { "summary" : true, "distanceMatrixContentsResultFields" : contentsResultFields }; var distanceMatrixResponse; var uncodedResponse; var encodedResponse; xdima.createDistanceMatrix({ "startLocations": locations }, dimaReturn); // first request is not encoded var contentsOptions = { "returnEncodedArrays" : false }; function dimaReturn(distanceMatrixResp, exception) { distanceMatrixResponse = distanceMatrixResp; var byLocationsRequest = { "$type": "GetDistanceMatrixByLocationsRequest", "id" : distanceMatrixResponse.summary.id, "startLocations": locations, "destinationLocations": locations, "resultFields": resultFields, "contentsOptions" : contentsOptions }; xdima.getDistanceMatrix(byLocationsRequest, uncodedCallback); }; function uncodedCallback(resultUncoded, exception) { uncodedResponse = resultUncoded; encodedVersionCalling(); }; function encodedVersionCalling() { var byLocationsRequest = { "$type": "GetDistanceMatrixByLocationsRequest", "id" : distanceMatrixResponse.summary.id, "startLocations": locations, "destinationLocations": locations, "resultFields": resultFields, "contentsOptions" : {"returnEncodedArrays" : true} // second request in encoded }; xdima.getDistanceMatrix(byLocationsRequest, encodedCallback); }; function encodedCallback(resultEncoded, exception) { encodedResponse = resultEncoded; convertAndCheckResults(); }; // returns the value of the integer in the buffer function getUint32FromIndex( byteArray, index ){ // set the endianness in the second parameter, tha data is in little endian return byteArray.getUint32(index * 4, true); // the offset is 4, this can be calculated like byteArray.length / elementCount }; // the byteArray is encoded in base64 // getBytes makes conversion from base64 to Uint8Array function getBytes( byteArray ){ var decoded = atob(byteArray); var i, il = decoded.length; var array = new Uint8Array(il); for (i = 0; i< il; ++i) { array[i] = decoded.charCodeAt(i); } return array; }; function getBoolValueAt(byteArray, index) { var bitMask = 1 << (index % 8); var val = byteArray[Math.trunc(index / 8)] & bitMask; return val === bitMask; }; function convertAndCheckResults(){ var elementCount = encodedResponse.summary.numberOfStartLocations * encodedResponse.summary.numberOfDestinationLocations ; var distancesBytes = getBytes(encodedResponse.contents.distances); // uncoding the contents which is encoded in base64 var distances = new DataView(distancesBytes.buffer); var travelTimesBytes = getBytes(encodedResponse.contents.travelTimes ); var travelTimes = new DataView(travelTimesBytes.buffer); var violatedBytes = getBytes(encodedResponse.contents.violated); var estimatedByDirectDistanceBytes = getBytes(encodedResponse.contents.estimatedByDirectDistance); for (i = 0; i < elementCount; ++i) { var valuesAreSame = true; if (getUint32FromIndex(distances, i) != uncodedResponse.contents.distances[i]) { print('Distance is not same'); valuesAreSame = false; break; } if (getUint32FromIndex(travelTimes, i) / 1000 != uncodedResponse.contents.travelTimes[i]) { print('TravelTimes is not same'); valuesAreSame = false; break; } if (getBoolValueAt(violatedBytes, i) != uncodedResponse.contents.violated[i]) { print('Violated is not same'); valuesAreSame = false; break; } if (getBoolValueAt(estimatedByDirectDistanceBytes, i) != uncodedResponse.contents.estimatedByDirectDistance[i]) { print('estimatedByDirectDistance is not same'); valuesAreSame = false; break; } } if(valuesAreSame){ print('Uncoded and encoded versions are same '); } };Java
The following code shows an example in Java:
Show code...
import static org.hamcrest.MatcherAssert.assertThat;
import static org.junit.Assert.fail;
import java.net.URL;
import java.util.ArrayList;
import java.util.BitSet;
import java.util.List;
import com.ptvgroup.xserver.dima.DistanceMatrixProgress;
import com.ptvgroup.xserver.geometry.Coordinate;
import com.ptvgroup.xserver.xdima.CreateDistanceMatrixRequest;
import com.ptvgroup.xserver.xdima.DeleteDistanceMatrixRequest;
import com.ptvgroup.xserver.xdima.DistanceMatrixContentsArrays;
import com.ptvgroup.xserver.xdima.DistanceMatrixContentsEncodedArrays;
import com.ptvgroup.xserver.xdima.DistanceMatrixContentsOptions;
import com.ptvgroup.xserver.xdima.DistanceMatrixContentsResultFields;
import com.ptvgroup.xserver.xdima.DistanceMatrixDescription;
import com.ptvgroup.xserver.xdima.DistanceMatrixInformation;
import com.ptvgroup.xserver.xdima.DistanceMatrixListResponse;
import com.ptvgroup.xserver.xdima.DistanceMatrixResponse;
import com.ptvgroup.xserver.xdima.DistanceMatrixResultFields;
import com.ptvgroup.xserver.xdima.ExtendDistanceMatrixRequest;
import com.ptvgroup.xserver.xdima.GetDistanceMatrixByLocationsRequest;
import com.ptvgroup.xserver.xdima.GetDistanceMatrixByRelationsRequest;
import com.ptvgroup.xserver.xdima.ListDistanceMatricesRequest;
import com.ptvgroup.xserver.xdima.ListDistanceMatricesResponse;
import com.ptvgroup.xserver.xdima.Relation;
import com.ptvgroup.xserver.xdima.XDima;
import com.ptvgroup.xserver.xdima.XDima_Service;
import com.ptvgroup.xserver.xdima.XServerException;
import net.bytebuddy.matcher.StringMatcher;
public class TestClass {
private static XDima xdima;
public static Coordinate createCoordinate(double x, double y) {
Coordinate coordinate = new Coordinate();
coordinate.setX(x);
coordinate.setY(y);
return coordinate;
}
public static RouteLocation createOffRoadCoordinate(double x, double y) {
OffRoadRouteLocation offRoadRouteLocation = new OffRoadRouteLocation();
offRoadRouteLocation.setOffRoadCoordinate(createCoordinate(x, y));
return offRoadRouteLocation;
}
public static RouteLocation createOnRoadCoordinate(double x, double y) {
OnRoadRouteLocation onRoadRouteLocation = new OnRoadRouteLocation();
onRoadRouteLocation.setCoordinate(createCoordinate(x, y));
return onRoadRouteLocation;
}
private CreateDistanceMatrixRequest constructCreateDistanceMatrixRequest() {
CreateDistanceMatrixRequest createDistanceMatrixRequest = new CreateDistanceMatrixRequest();
List<RouteLocation> startLocations = createDistanceMatrixRequest.getStartLocations();
startLocations.add(createOffRoadCoordinate(147.35255956649783, -43.06534499935546));
startLocations.add(createOffRoadCoordinate(147.37571239471438, -43.100011493947584));
startLocations.add(createOnRoadCoordinate(147.31614589691165, -43.003077911658735));
return createDistanceMatrixRequest;
}
public static List<Long> asLongList(byte[] byteArray) {
final int bytesSize = Integer.SIZE / Byte.SIZE;
List<Long> result = new ArrayList<>();
for (int i = 0; i < byteArray.length; i += bytesSize) {
result.add(getUnsignedInt(byteArray, i, bytesSize));
}
return result;
}
public static long getUnsignedInt(byte[] data, int offset, int length) {
long result = 0;
for (int i = 0; i < length; i++) {
result += (data[i + offset] & 0xFF) << 8 * i;
}
return result;
}
public static List<Boolean> asBooleanList(byte[] byteArray, int nbits) {
BitSet bitSet = BitSet.valueOf(byteArray);
List<Boolean> result = new ArrayList<>();
for (int bitIndex = 0; bitIndex < nbits; ++bitIndex) {
result.add(bitSet.get(bitIndex));
}
return result;
}
public static void main(String[] args) {
try {
xdima = new XDima_Service(new URL("http://localhost:50000/services/ws/XDima/experimental")).getXdima();
CreateDistanceMatrixRequest createDistanceMatrixRequest = constructCreateDistanceMatrixRequest();
DistanceMatrixResponse distanceMatrixResponse = xdima.createDistanceMatrix(createDistanceMatrixRequest);
GetDistanceMatrixByLocationsRequest byLocationsRequest = new GetDistanceMatrixByLocationsRequest();
byLocationsRequest.setId(distanceMatrixResponse.getSummary().getId());
byLocationsRequest.getStartLocations().addAll(createDistanceMatrixRequest.getStartLocations());
byLocationsRequest.getDestinationLocations().addAll(createDistanceMatrixRequest.getDestinationLocations());
DistanceMatrixResultFields resultFields = new DistanceMatrixResultFields();
resultFields.setSummary(true);
DistanceMatrixContentsResultFields contentsResultFields = new DistanceMatrixContentsResultFields();
contentsResultFields.setDistances(true);
contentsResultFields.setTravelTimes(true);
contentsResultFields.setViolated(true);
contentsResultFields.setEstimatedByDirectDistance(true);
resultFields.setDistanceMatrixContentsResultFields(contentsResultFields);
byLocationsRequest.setResultFields(resultFields);
DistanceMatrixContentsOptions contentsOptions = new DistanceMatrixContentsOptions();
contentsOptions.setReturnEncodedArrays(false);
byLocationsRequest.setContentsOptions(contentsOptions);
DistanceMatrixResponse unencodedResponse = xdima.getDistanceMatrix(byLocationsRequest);
DistanceMatrixContentsArrays unencodedArrays = (DistanceMatrixContentsArrays) unencodedResponse
.getContents();
byLocationsRequest.getContentsOptions().setReturnEncodedArrays(true);
DistanceMatrixResponse encodedResponse = xdima.getDistanceMatrix(byLocationsRequest);
DistanceMatrixContentsEncodedArrays encodedArrays = (DistanceMatrixContentsEncodedArrays) encodedResponse
.getContents();
final List<Long> distances = asLongList(encodedArrays.getDistances());
final List<Long> travelTimes = asLongList(encodedArrays.getTravelTimes());
final int elementsCount = encodedResponse.getSummary().getNumberOfDestinationLocations()
* encodedResponse.getSummary().getNumberOfStartLocations();
final List<Boolean> violated = asBooleanList(encodedArrays.getViolated(), elementsCount);
final List<Boolean> estimatedByDirectDistance = asBooleanList(encodedArrays.getEstimatedByDirectDistance(),
elementsCount);
for (int idx = 0; idx < elementsCount; ++idx) {
assertThat((double) distances.get(idx), is(unencodedArrays.getDistances().get(idx)));
assertThat((double) travelTimes.get(idx) / 1000.0, is(unencodedArrays.getTravelTimes().get(idx)));
}
assertThat(violated, is(unencodedArrays.getViolated()));
assertThat(estimatedByDirectDistance, is(unencodedArrays.getEstimatedByDirectDistance()));
DeleteDistanceMatrixRequest deleteDistanceMatrixRequest = new DeleteDistanceMatrixRequest();
deleteDistanceMatrixRequest.setId(distanceMatrixResponse.getSummary().getId());
xdima.deleteDistanceMatrix(deleteDistanceMatrixRequest);
} catch (XServerException xserverException) {
fail("Did not expect an exception for this test. Got exception: " + xserverException);
}
}
}
C#
The following code shows an example in C#:
Show code...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using XDimaTestIT.xDimaService;
using System.Diagnostics;
using System.Collections;
using System.Security.Policy;
namespace XDimaTestIT
{
class Program
{
private static XDima xdima;
public static void setUpBeforeClass()
{
xdima = new XDimaClient();
}
public static Coordinate createCoordinate(double x, double y)
{
Coordinate coordinate = new Coordinate();
coordinate.x = x;
coordinate.y = y;
return coordinate;
}
public static RouteLocation createOffRoadCoordinate(double x, double y)
{
OffRoadRouteLocation offRoadRouteLocation = new OffRoadRouteLocation();
offRoadRouteLocation.offRoadCoordinate = createCoordinate(x, y);
return offRoadRouteLocation;
}
public static RouteLocation createOnRoadCoordinate(double x, double y)
{
OnRoadRouteLocation onRoadRouteLocation = new OnRoadRouteLocation();
onRoadRouteLocation.coordinate = createCoordinate(x, y);
return onRoadRouteLocation;
}
private static createDistanceMatrix constructCreateDistanceMatrixRequest()
{
createDistanceMatrix createDistanceMatrixRequest = new createDistanceMatrix();
List<RouteLocation> startLocations = new List<RouteLocation>();
startLocations.Add(createOffRoadCoordinate(147.35255956649783, -43.06534499935546));
startLocations.Add(createOffRoadCoordinate(147.37571239471438, -43.100011493947584));
startLocations.Add(createOnRoadCoordinate(147.31614589691165, -43.003077911658735));
createDistanceMatrixRequest.request = new CreateDistanceMatrixRequest();
createDistanceMatrixRequest.request.startLocations = startLocations.ToArray();
return createDistanceMatrixRequest;
}
public static List<long> asLongList(byte[] byteArray)
{
int bytesSize = sizeof(int) / sizeof(Byte);
List<long> result = new List<long>();
for (int i = 0; i < byteArray.Length; i += bytesSize)
{
result.Add(getUnsignedInt(byteArray, i, bytesSize));
}
return result;
}
public static long getUnsignedInt(byte[] data, int offset, int length)
{
long result = 0;
for (int i = 0; i < length; i++)
{
result += (data[i + offset] & 0xFF) << 8 * i;
}
return result;
}
public static List<Boolean> asBooleanList(byte[] byteArray, int nbits)
{
var test = BitConverter.IsLittleEndian;
BitArray bitSet = new BitArray(byteArray);
List<Boolean> result = new List<Boolean>();
for (int bitIndex = 0; bitIndex < nbits; ++bitIndex)
{
result.Add(bitSet.Get(bitIndex));
}
return result;
}
static void Main(string[] args)
{
try
{
setUpBeforeClass();
createDistanceMatrix createDistanceMatrixRequest = constructCreateDistanceMatrixRequest();
createDistanceMatrixResponse distanceMatrixResponse = xdima.createDistanceMatrix(createDistanceMatrixRequest);
getDistanceMatrix byLocationsRequest = new getDistanceMatrix();
byLocationsRequest.request = new GetDistanceMatrixByLocationsRequest();
byLocationsRequest.request.id = distanceMatrixResponse.@return.summary.id;
byLocationsRequest.request.startLocations = createDistanceMatrixRequest.request.startLocations;
byLocationsRequest.request.destinationLocations = createDistanceMatrixRequest.request.destinationLocations;
DistanceMatrixResultFields resultFields = new DistanceMatrixResultFields();
resultFields.summary = true;
resultFields.summarySpecified = true;
DistanceMatrixContentsResultFields contentsResultFields = new DistanceMatrixContentsResultFields();
contentsResultFields.distances = true;
contentsResultFields.distancesSpecified = true;
contentsResultFields.travelTimes = true;
contentsResultFields.travelTimesSpecified = true;
contentsResultFields.violated = true;
contentsResultFields.violatedSpecified = true;
contentsResultFields.estimatedByDirectDistance = true;
contentsResultFields.estimatedByDirectDistanceSpecified = true;
resultFields.distanceMatrixContentsResultFields = contentsResultFields;
byLocationsRequest.request.resultFields = resultFields;
DistanceMatrixContentsOptions contentsOptions = new DistanceMatrixContentsOptions();
contentsOptions.returnEncodedArrays = false;
byLocationsRequest.request.contentsOptions = contentsOptions;
getDistanceMatrixResponse unencodedResponse = xdima.getDistanceMatrix(byLocationsRequest);
DistanceMatrixContentsArrays unencodedArrays = (DistanceMatrixContentsArrays)unencodedResponse.@return.contents;
byLocationsRequest.request.contentsOptions.returnEncodedArrays = true;
byLocationsRequest.request.contentsOptions.returnEncodedArraysSpecified = true;
getDistanceMatrixResponse encodedResponse = xdima.getDistanceMatrix(byLocationsRequest);
DistanceMatrixContentsEncodedArrays encodedArrays = (DistanceMatrixContentsEncodedArrays)encodedResponse.@return.contents;
List< long > distances = asLongList(encodedArrays.distances);
List<long> travelTimes = asLongList(encodedArrays.travelTimes);
int elementsCount = encodedResponse.@return.summary.numberOfDestinationLocations
* encodedResponse.@return.summary.numberOfStartLocations;
List< Boolean > violated = asBooleanList(encodedArrays.violated, elementsCount);
List< Boolean > estimatedByDirectDistance = asBooleanList(encodedArrays.estimatedByDirectDistance,
elementsCount);
for (int idx = 0; idx < elementsCount; ++idx)
{
Debug.Assert((double)distances.ElementAt(idx) == unencodedArrays.distances.ElementAt(idx));
Debug.Assert((double)travelTimes.ElementAt(idx) / 1000.0 == unencodedArrays.travelTimes.ElementAt(idx));
Debug.Assert(violated.ElementAt(idx) == unencodedArrays.violated.ElementAt(idx));
Debug.Assert(estimatedByDirectDistance.ElementAt(idx) == unencodedArrays.estimatedByDirectDistance.ElementAt(idx));
}
deleteDistanceMatrix deleteDistanceMatrixRequest = new deleteDistanceMatrix();
deleteDistanceMatrixRequest.request = new DeleteDistanceMatrixRequest();
deleteDistanceMatrixRequest.request.id = distanceMatrixResponse.@return.summary.id;
xdima.deleteDistanceMatrix(deleteDistanceMatrixRequest);
System.Console.WriteLine("xDima finished: " );
}
catch (System.ServiceModel.FaultException<XServerFault> e)
{
System.Console.WriteLine("Got exception: " + e.Message);
System.Console.WriteLine("Hint: " + e.Detail.hint);
}
System.Console.ReadLine();
}
}
}