Рассчитать большое расстояние между двумя точками с помощью GeoTools

Новичок в GeoTools и ГИС, и я пытаюсь рассчитать расстояние между Мумбаи и Дурбаном, используя библиотеку GeoTools. Я приближаюсь к точным результатам для небольших расстояний, но когда я иду на большие расстояния, расчет слишком отклоняется от курса на 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);

person Nikhil Karanjkar    schedule 20.02.2020    source источник


Ответы (1)


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

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

Но вас не интересует небольшой регион от Мумбаи до Дурбана, это значительный путь вокруг Земли, поэтому вам нужно учитывать кривизну земной поверхности. Также вы не пытаетесь сделать что-то сложное, для которого JTS является единственным источником процесса (например, буферизация). В этом случае вы должны использовать GeodeticCalculator, который учитывает форму Земли, используя библиотеку CFF Karney, Algorithms for geodesics, 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
person Ian Turton    schedule 20.02.2020
comment
Это именно то, что я хотел !!!. Спасибо, Ян. ценится - person Nikhil Karanjkar; 22.02.2020
comment
Я также хотел узнать расстояние пересечения между линией и многоугольником. Я пытаюсь сделать это путем проецирования геометрии на автоматические проекции из wGs84 с использованием центроида многоугольника (но я думаю, что я должен взять центроид обеих геометрий, и я в настоящее время не уверен, как это сделать), и затем получить расстояние пересекающейся геометрии. Но я обнаружил, что это не так. Можете ли вы посоветовать мне, как мне подойти к этому? - person Nikhil Karanjkar; 22.02.2020
comment
@Ian, какие библиотеки ты используешь для кода? Количество‹Длина› dist = Quantities.getQuantity(расстояние, SI.METRE); - person Jeryl Cook; 27.07.2021