用Java从Google DistanceMatrix响应计算2d距离矩阵
我试图用谷歌或工具库解决旅行推销员问题和车辆路径问题,在教程中发现,他们使用了一个距离矩阵用Java从Google DistanceMatrix响应计算2d距离矩阵,java,google-distancematrix-api,distance-matrix,Java,Google Distancematrix Api,Distance Matrix,我试图用谷歌或工具库解决旅行推销员问题和车辆路径问题,在教程中发现,他们使用了一个距离矩阵,其I,j条目是从位置I到位置j的距离(以英里为单位),位置顺序如下: 纽约1。洛杉矶2。芝加哥3。明尼阿波利斯4号。丹佛5号。达拉斯6号。西雅图7。波士顿8。旧金山9。圣路易斯10号。休斯顿11。凤凰12号。盐湖城 它们的矩阵距离如下所示: public final long[][] distanceMatrix = { {0, 2451, 713, 1018, 1631, 1374, 2
,其I,j
条目是从位置I到位置j的距离(以英里为单位),位置顺序如下:
public final long[][] distanceMatrix = {
{0, 2451, 713, 1018, 1631, 1374, 2408, 213, 2571, 875, 1420, 2145, 1972},
{2451, 0, 1745, 1524, 831, 1240, 959, 2596, 403, 1589, 1374, 357, 579},
{713, 1745, 0, 355, 920, 803, 1737, 851, 1858, 262, 940, 1453, 1260},
{1018, 1524, 355, 0, 700, 862, 1395, 1123, 1584, 466, 1056, 1280, 987},
{1631, 831, 920, 700, 0, 663, 1021, 1769, 949, 796, 879, 586, 371},
{1374, 1240, 803, 862, 663, 0, 1681, 1551, 1765, 547, 225, 887, 999},
{2408, 959, 1737, 1395, 1021, 1681, 0, 2493, 678, 1724, 1891, 1114, 701},
{213, 2596, 851, 1123, 1769, 1551, 2493, 0, 2699, 1038, 1605, 2300, 2099},
{2571, 403, 1858, 1584, 949, 1765, 678, 2699, 0, 1744, 1645, 653, 600},
{875, 1589, 262, 466, 796, 547, 1724, 1038, 1744, 0, 679, 1272, 1162},
{1420, 1374, 940, 1056, 879, 225, 1891, 1605, 1645, 679, 0, 1017, 1200},
{2145, 357, 1453, 1280, 586, 887, 1114, 2300, 653, 1272, 1017, 0, 504},
{1972, 579, 1260, 987, 371, 999, 701, 2099, 600, 1162, 1200, 504, 0},
};
它们进一步提供了一个关于如何动态创建距离矩阵的方法,除了在Python
中,我在这方面不是很好,我正在使用Java
在我的Java实现中
我使用的是Java客户机
,我的代码如下
private static long[][] buildDistanceMatrix(int matrixSize, DistanceMatrix distanceMatrix) {
long[][] matrix = new long[matrixSize][matrixSize];
for (int i = 0; i < distanceMatrix.rows.length; i++) {
DistanceMatrixElement[] elements = distanceMatrix.rows[i].elements;
for (int j = 0; j < elements.length; j++) {
matrix[i][j] = elements[j].distance.inMeters;
}
}
return matrix;
}
public static void getDistanceMatrix(List<LatLng> origins, List<LatLng> destinations){
GeoApiContext context = new GeoApiContext.Builder()
.apiKey(GOOGLE_MAPS_API_KEY)
.build();
DistanceMatrixApiRequest distanceMatrixApiRequest = DistanceMatrixApi.newRequest(context)
.mode(TravelMode.DRIVING)
.trafficModel(TrafficModel.BEST_GUESS)
.departureTime(Instant.now().atZone(ZoneOffset.UTC).toInstant())
.destinations(destinations.toArray(new LatLng[destinations.size()]))
.origins(origins.toArray(new LatLng[origins.size()]));
distanceMatrixApiRequest.setCallback(new PendingResult.Callback<DistanceMatrix>() {
@Override
public void onResult(DistanceMatrix distanceMatrix) {
long[][] matrix = buildDistanceMatrix(destinations.size(), distanceMatrix);
System.out.println(Arrays.deepToString(matrix));
}
@Override
public void onFailure(Throwable throwable) {
throwable.printStackTrace();
}
});
}
"destinationAddresses": [
"Central St, Lusaka, Zambia",
"Unnamed Road, Lusaka, Zambia",
"Jacaranda Rd, Lusaka, Zambia"
],
"originAddresses": [
"1940 - 3 Munthaka Cl, Lusaka, Zambia"
],
"rows": [
{
"elements": [
{
"distance": {
"humanReadable": "10.2 km",
"inMeters": 10193
},
"duration": {
"humanReadable": "23 mins",
"inSeconds": 1352
},
"durationInTraffic": {
"humanReadable": "26 mins",
"inSeconds": 1549
},
"status": "OK"
},
{
"distance": {
"humanReadable": "6.6 km",
"inMeters": 6647
},
"duration": {
"humanReadable": "13 mins",
"inSeconds": 779
},
"durationInTraffic": {
"humanReadable": "14 mins",
"inSeconds": 839
},
"status": "OK"
},
{
"distance": {
"humanReadable": "4.9 km",
"inMeters": 4881
},
"duration": {
"humanReadable": "9 mins",
"inSeconds": 516
},
"durationInTraffic": {
"humanReadable": "9 mins",
"inSeconds": 538
},
"status": "OK"
}
]
}
]
}```
public static Assignment findWithVehicleRoutingProblem(List<LatLng> destinations, int numOfVehicles) {
long[][] distanceMatrix = RoutUtils.computeEuclideanDistanceMatrix(RoutUtils.scaleCoordinatesForEuclidean(destinations));
RoutingIndexManager manager = new RoutingIndexManager(distanceMatrix.length, numOfVehicles, 0);
RoutingModel routing = new RoutingModel(manager);
final int transitCallbackIndex = routing.registerTransitCallback((long fromIndex, long toIndex) -> {
int fromNode = manager.indexToNode(fromIndex);
int toNode = manager.indexToNode(toIndex);
return distanceMatrix[fromNode][toNode];
});
routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
routing.addDimension(transitCallbackIndex, 0, 3000,
true,
"Distance");
RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
distanceDimension.setGlobalSpanCostCoefficient(100);
RoutingSearchParameters searchParameters = main.defaultRoutingSearchParameters()
.toBuilder()
.setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
.build();
return routing.solveWithParameters(searchParameters);
}
我确实解决了这个问题。我用
欧几里德距离公式
得到了一个距离矩阵
/// @brief Compute Euclidean distance matrix from locations array.
/// @details It uses an array of locations and computes
/// the Euclidean distance between any two locations.
private static long[][] computeEuclideanDistanceMatrix(long[][] locations) {
// Calculate distance matrix using Euclidean distance.
long[][] distanceMatrix = new long[locations.length][locations.length];
for (int fromNode = 0; fromNode < locations.length; ++fromNode) {
for (int toNode = 0; toNode < locations.length; ++toNode) {
if (fromNode == toNode) {
distanceMatrix[fromNode][toNode] = 0;
} else {
distanceMatrix[fromNode][toNode] =
(long) Math.hypot(locations[toNode][0] - locations[fromNode][0],
locations[toNode][1] - locations[fromNode][1]);
}
}
}
return distanceMatrix;
}
以及scalecoordinationsforeuclidean
方法
private static final long DISTANCE_MATRIX_SCALE_FACTOR = 100000000000L;
private static long[][] scaleCoordinatesForEuclidean(List<LatLng> destinations) {
long[][] locations = new long[destinations.size()][destinations.size()];
for (int i = 0; i < destinations.size(); i++) {
long[] coordinate = {(long) (destinations.get(i).lat * DISTANCE_MATRIX_SCALE_FACTOR), (long) (destinations.get(i).lng * DISTANCE_MATRIX_SCALE_FACTOR)};
locations[i] = coordinate;
}
return locations;
}
专用静态最终长距离矩阵比例系数=1000000000L;
专用静态长[][]ScaleCoordinationsForeClidean(列出目的地){
long[][]位置=新的long[destinations.size()][destinations.size()];
对于(int i=0;i
@Anbry Lungu找到了任何解决方案,请告诉我。@RajKumar是的,我找到了。检查我的答案,如果你需要进一步的帮助,请不要犹豫。你能帮我找出这个方法需要的参数吗?计算uclideandstancematrix(..)@astonio这些参数非常简单,因此在地图上给定两个位置,每个位置都由其坐标标识,坐标包括纬度和经度。所以位置数组只是一个多维的位置数组,在我最初的问题中,这就是纽约1号的坐标。洛杉矶2。芝加哥3。明尼阿波利斯4号。丹佛5号。达拉斯6号。西雅图7。波士顿8。旧金山9。圣路易斯10号。休斯顿11。凤凰12号。盐湖城你的意思是我们需要准备一个带有经纬度的数组?这里经纬度是双精度的,但我们需要将变量作为长数组传递,如果我们将双精度转换为长数组,那么结果将是2位数字,比如22.272504,96.607590到22,96,可以吗?
private static final long DISTANCE_MATRIX_SCALE_FACTOR = 100000000000L;
private static long[][] scaleCoordinatesForEuclidean(List<LatLng> destinations) {
long[][] locations = new long[destinations.size()][destinations.size()];
for (int i = 0; i < destinations.size(); i++) {
long[] coordinate = {(long) (destinations.get(i).lat * DISTANCE_MATRIX_SCALE_FACTOR), (long) (destinations.get(i).lng * DISTANCE_MATRIX_SCALE_FACTOR)};
locations[i] = coordinate;
}
return locations;
}