我想使用 java 读取一组纬度和经度值,从预定义值表中识别最近的坐标并报告引用名称。
例如,对于 lat=37.423423 和 long=-122.083953 的输入坐标,我想从下面的输入表中找到最近的点并报告相关的网格参考。
lat long gridRef
37.00 -121.50 A1
37.00 -122.00 A2
37.00 -122.50 A3
37.50 -121.50 B1
37.50 -122.00 B2
37.50 -122.50 B3
38.00 -121.50 C1
38.00 -122.00 C2
38.00 -122.50 C3
在此示例中,输出应打印"B2">
我有一些代码可以报告最近点的坐标:
public class ClosestPoint {
public static void main(String[] args) {
final int X = 0;
final int Y = 1;
// input coordinates to search against
double[] coordinate = {37.423423, -122.083953};
// input points to search against
double[][] points = {{37.00, -121.50}, // 0 A1
{37.00, -122.00}, // 1 A2
{37.00, -122.50}, // 2 A3
{37.50, -121.50}, // 3 B1
{37.50, -122.00}, // 4 B2
{37.50, -122.50}, // 5 B3
{38.00, -121.50}, // 6 C1
{38.00, -122.00}, // 7 C2
{38.00, -122.50} // 8 C3
};
double[] closest = nearestPoint(coordinate, points);
System.out.println("("+closest[X]+", "+closest[Y]+")");
double d = distance(coordinate[X], coordinate[Y], closest[X], closest[Y]);
System.out.println("Distance: "+ d);
}
public static double distance(double x1, double y1, double x2, double y2) {
double x = Math.pow(x2 - x1, 2);
double y = Math.pow(y2 - y1, 2);
return Math.sqrt( x + y );
}
public static double[] nearestPoint(double[] coordinate, double[][] points) {
final int X = 0;
final int Y = 1;
double[] closestPoint = points[0];
double closestDist = distance(coordinate[X], coordinate[Y],
closestPoint[X], closestPoint[Y]);
// Traverse the array
for(int i = 0; i < points.length; i++) {
double dist = distance(coordinate[X], coordinate[Y],
points[i][X], points[i][Y]);
if (dist < closestDist && dist != 0.0) {
closestDist = dist;
closestPoint = points[i];
}
}
return closestPoint;
}
}
输出如下所示:
(37.5, -122.0)
Distance: 0.11363161152601435
我现在要做的是输出这个坐标的参考名称,在上面的示例中是 B2。
任何建议将不胜感激
愿你安好 奥利
可以使用哈弗斯公式计算距离。Java 中的实现示例可以在此处找到:
https://gist.github.com/vananth22/888ed9a22105670e7a4092bdcf0d72e4
编辑:您的距离计算在球体/曲面上不会特别准确。如果精度是一个要求,我建议实现上面写的Haversine公式。
但是,您的问题似乎与将区域名称映射到一组坐标更相关?如果是这种情况,有几种不同的解决方案(下面列出了一些(:
-
您可以创建一个结构(类(来保存区域标记(名称(、纬度和纬度坐标,并在列表中存储每个坐标对的实例。
-
您可以像现在一样将坐标对存储在一个列表中,并将标记(名称(存储在与坐标列表中的索引匹配的单独字符串列表中。
-
您可以将每个坐标对存储在哈希图中,并将标签名称作为键。
此外,我建议根据例如到固定点的距离对坐标列表进行排序。这样,可以通过简单的二叉搜索找到与给定坐标最近的点,而不必迭代列表中的每个坐标(在最坏的情况下为 O(N((。
编辑2:
下面是我修改原始代码的示例。这不是最佳解决方案,我建议遵循我上面给出的一些建议。
修改后的代码返回到最近点的索引,而不是坐标对本身。然后,它使用该索引在另一个字符串数组中查找区域。注意:没有错误检查返回索引是否有效。
public class ClosestPoint {
public static void main(String[] args) {
final int X = 0;
final int Y = 1;
// input coordinates to search against
double[] coordinate = {37.423423, -122.083953};
// input points to search against
double[][] points = {{37.00, -121.50}, // 0 A1
{37.00, -122.00}, // 1 A2
{37.00, -122.50}, // 2 A3
{37.50, -121.50}, // 3 B1
{37.50, -122.00}, // 4 B2
{37.50, -122.50}, // 5 B3
{38.00, -121.50}, // 6 C1
{38.00, -122.00}, // 7 C2
{38.00, -122.50} // 8 C3
};
String[] zonenames = {
"A1",
"A2",
"A3",
"B1",
"B2",
"B3",
"C1",
"C2",
"C3",
};
//double[] closest = nearestPoint(coordinate, points);
int index = nearestPoint(coordinate, points);
double[] closest = points[index];
String zone = zonenames[index];
System.out.println("("+closest[X]+", "+closest[Y]+")");
System.out.println("Zone: " + zone);
double d = distance(coordinate[X], coordinate[Y], closest[X], closest[Y]);
System.out.println("Distance: "+ d);
}
public static double distance(double x1, double y1, double x2, double y2) {
double x = Math.pow(x2 - x1, 2);
double y = Math.pow(y2 - y1, 2);
return Math.sqrt( x + y );
}
//public static double[] nearestPoint(double[] coordinate, double[][] points) {
public static int nearestPoint(double[] coordinate, double[][] points) {
final int X = 0;
final int Y = 1;
int indexFound = 0;
double[] closestPoint = points[0];
double closestDist = distance(coordinate[X], coordinate[Y],
closestPoint[X], closestPoint[Y]);
// Traverse the array
for(int i = 0; i < points.length; i++) {
double dist = distance(coordinate[X], coordinate[Y],
points[i][X], points[i][Y]);
if (dist < closestDist && dist != 0.0) {
closestDist = dist;
closestPoint = points[i];
indexFound = i;
}
}
//return closestPoint;
return indexFound;
}
}