Рассчитайте большое расстояние между двумя точками, используя GeoTools - PullRequest
0 голосов
/ 20 февраля 2020

Впервые в GeoTools и ГИС, и я пытаюсь вычислить расстояние между Мумбаи и Дурбаном, используя библиотеку GeoTools. Я нахожусь близко к точным результатам для небольших расстояний, но когда я go для больших, вычисление слишком далеко на 2000 км, я не совсем понимаю систему CRS. Ниже приведен мой Код для расчета расстояния между Мумбаи и Дурбаном

    Coordinate source = new Coordinate(19.0760, 72.8777);   ///Mumbai Lat Long
    Coordinate destination1 = new Coordinate(-29.883333, 31.049999); //Durban Lat Long

    GeometryFactory geometryFactory = new GeometryFactory();
    Geometry point1 = geometryFactory.createPoint(source);
    Geometry point2 = geometryFactory.createPoint(destination1);

    CoordinateReferenceSystem auto = auto = CRS.decode("AUTO:42001,13.45,52.3");
    MathTransform transform = CRS.findMathTransform(DefaultGeographicCRS.WGS84, auto);

    Geometry g3 = JTS.transform(point1, transform);
    Geometry g4 = JTS.transform(point2, transform);

    double distance = g3.distance(g4);

1 Ответ

2 голосов
/ 20 февраля 2020

Вот что происходит, когда вы слепо копируете код из stackexchange Вопросы , не читая Вопрос , на основе которого он объясняет, почему.

Все время я Если вы ответили на этот вопрос (и отправил код, подобный этому ), спрашивающий пытается использовать координаты широты / долготы в градусах для измерения короткого расстояния в метрах. Уловка, показанная в вашем вопросе, создает автоматическую проекцию c UTM с центром в положении, указанном после бита «AUTO: 42001» (в вашем случае 52N 13E) - это должен быть центр интересующей вас области, так что в вашем случае эти значения, вероятно, в любом случае неверны.

Но вас не интересует маленький регион, от Мумбаи до Дурбана, это значительный путь вокруг Земли, поэтому вам нужно учесть кривизна земной поверхности. Также вы не пытаетесь сделать что-то сложное, для которого JTS является единственным источником процесса (например, буферизация). В этом случае вы должны использовать GeodeticCalculator, который учитывает форму Земли, используя библиотеку C. Ф. Ф. Карней, Алгоритмы для геодезических, J. Geodesy 87, 43–55 (2013).

В любом случае достаточно объяснений, которые никто не прочтет в будущем, вот код:

  public static void main(String[] args) {
    DefaultGeographicCRS crs = DefaultGeographicCRS.WGS84;
    if (args.length != 4) {
      System.err.println("Need 4 numbers lat_1 lon_1 lat_2 lon_2");
      return;
    }
    GeometryFactory geomFactory = new GeometryFactory();
    Point[] points = new Point[2];
    for (int i = 0, k = 0; i < 2; i++, k += 2) {
      double x = Double.valueOf(args[k]);
      double y = Double.valueOf(args[k + 1]);
      if (CRS.getAxisOrder(crs).equals(AxisOrder.NORTH_EAST)) {
        System.out.println("working with a lat/lon crs");
        points[i] = geomFactory.createPoint(new Coordinate(x, y));
      } else {
        System.out.println("working with a lon/lat crs");
        points[i] = geomFactory.createPoint(new Coordinate(y, x));
      }

    }

    double distance = 0.0;

    GeodeticCalculator calc = new GeodeticCalculator(crs);
    calc.setStartingGeographicPoint(points[0].getX(), points[0].getY());
    calc.setDestinationGeographicPoint(points[1].getX(), points[1].getY());

    distance = calc.getOrthodromicDistance();
    double bearing = calc.getAzimuth();

    Quantity<Length> dist = Quantities.getQuantity(distance, SI.METRE);
    System.out.println(dist.to(MetricPrefix.KILO(SI.METRE)).getValue() + " Km");
    System.out.println(dist.to(USCustomary.MILE).getValue() + " miles");
    System.out.println("Bearing " + bearing + " degrees");
  }

Даёшь:

working with a lon/lat crs
POINT (72.8777 19.076)
POINT (31.049999 -29.883333)
7032.866960793305 Km
4370.020928274692 miles
Bearing -139.53428618565218 degrees
...