使用 Java 查找最近的坐标并打印参考

Find nearest coordinate and print reference using Java

我想使用 java 读取一组纬度和经度值,从 table 预定义值中识别最近的坐标并报告参考名称。

例如输入坐标lat=37.423423和long=-122.083953,我想从下面的输入table中找到最近的点,并报告相关的网格参考。

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。

如有任何建议,我们将不胜感激

祝福 奥利

可以使用Haversine formula计算距离。 Java 中的实施示例可在此处找到:

https://gist.github.com/vananth22/888ed9a22105670e7a4092bdcf0d72e4

编辑:您的距离计算在 sphere/curved 表面上不会特别准确。如果准确性是一项要求,我会建议实施上面写的 Haversine 公式。

但是,您的问题似乎与将区域名称映射到一组坐标有关?如果是这种情况,有几种不同的解决方案(下面列出了一些):

  1. 您可以创建一个结构 (class) 来保存区域标签(名称)、纬度和经度坐标,并为列表中的每个坐标对存储一个实例。

  2. 您可以像现在一样将坐标对存储在一个列表中,并将标签(名称)存储在与坐标列表中的索引匹配的单独字符串列表中。

  3. 您可以将每个坐标对存储在哈希图中,标签名称作为键。

此外,我建议根据与固定点的距离等对坐标列表进行排序。这样,可以通过简单的二进制搜索找到最接近给定坐标的点,而不必遍历列表中的每个坐标(最坏情况下为 O(N))。

编辑 2:

这是我修改你的原始代码的例子。这不是最佳解决方案,我建议遵循我上面给出的一些建议。

修改后的代码 return 是最近点的索引,而不是坐标对本身。然后它使用该索引在另一个字符串数组中查找区域。注意:没有错误检查 return 索引是否有效。

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;
    }
}