Преобразование lat/long в JTS?

Я пытаюсь интегрировать спящий пространственный объект с JPA для поиска в Geo. Я ссылаюсь на tutorial на официальном сайте (я не связан с hibernatespatial).

В учебнике, к сожалению, не рассматривается, как создать экземпляр Point из пары широты/долготы. Я пытаюсь сделать это здесь, но я все еще не уверен, что это правильный способ преобразования пары широты/долготы в экземпляр JTS Point:

import com.vividsolutions.jts.geom.Coordinate;
import com.vividsolutions.jts.geom.GeometryFactory;
import com.vividsolutions.jts.geom.Point;
import org.geotools.geometry.jts.JTSFactoryFinder;
import org.hibernate.annotations.Type;
import javax.persistence.*;

@Entity
public class Location {

    private Double latitude;

    private Double longitude;

    @Type(type = "org.hibernatespatial.GeometryUserType")
    private Point coordinates;

    private final GeometryFactory geometryFactory = JTSFactoryFinder.getGeometryFactory(null);

    @PrePersist
    @PreUpdate
    public void updateCoordinate() {
        if (this.latitude == null || this.longitude == null) {
            this.coordinates = null;
        } else {
            this.coordinates = geometryFactory.createPoint(new Coordinate(latitude, longitude));
        }
    }

    public Double getLatitude() {
        return latitude;
    }

    public void setLatitude(Double latitude) {
        this.latitude = latitude;
    }

    public Double getLongitude() {
        return longitude;
    }

    public void setLongitude(Double longitude) {
        this.longitude = longitude;
    }
}

Ответы

Ответ 1

JTS не волнует, что ваши точечные единицы или система координат.

Однако он предполагает, что координаты находятся на картезианской плоскости, поэтому некоторые операции с геометрией, такие как вычисления расстояния, могут быть неточными на больших расстояниях. (Они пока не поддерживают геодезические расчеты.)

Это должно быть хорошо для использования в простом хранилище.

Однако важно отметить, что долгота - это значение X и широта значения Y. Поэтому мы говорим "lat/long", но JTS ожидает его в порядке "long/lat". Поэтому вы должны использовать geometryFactory.createPoint(new Coordinate(longitude, latitude))

Ответ 2

Вот как создать координату в WGS-84:

    double EARTH_RADIUS = 6378137.0;
    double x = longitude * EARTH_RADIUS * Math.PI / 180.;
    double y = EARTH_RADIUS * Math.sin(Math.toRadians(latitude));
    return new Coordinate(x,y,0.);

Приветствия

Ответ 3

Подводя итог тому, что говорили другие, при преобразовании в Координат есть 3 основных момента, чтобы позаботиться о:

  • Проекция. JTS работает в картезианской плоскости, поэтому все искажения, например. Меркатор распространяется на ваш расчет. Таким образом, вы должны использовать его только на довольно короткой дистанции. Я не уверен в точной величине, но я думаю, что все, что ниже уровня расширения, должно быть прекрасным. Оставайтесь ниже 0,1 градуса, и вы определенно находитесь в безопасности.
  • Единицы. Вы можете помещать абсолютно любой блок в JTS. Проблема в том, что вы не можете сказать JTS, используете ли вы счетчики или градусы или что-то еще. Поэтому вы должны позаботиться о том, чтобы вы либо придерживались одной единицы, либо конвертировали там, где это необходимо.
  • Стандарт. В стандарте ISO указано, что геопространственные координаты предоставляются лат первым. Тем не менее, он конкурирует с стандартами GeoJSON/WKT, которые в первую очередь задерживаются, поэтому обратные. Обе стандартные группы имеют приложения, прилипающие к ним (например, Apache Lucene переключает стандарты между выпусками без изменения сигнатуры метода, тем самым вызывая головные боли сотен пользователей, которые задаются вопросом, почему их карты внезапно перевернулись), и JTS держится на GeoJSON/WKT. Обратите внимание на то, где бы вы не передавали данные из другой библиотеки - она ​​может следовать за GeoJSON и WKT или ISO, вы должны заранее сообщить об этом. (Поверь мне, у меня уже были проблемы с этим, и это может быть очень неприятно, проходя весь код и переворачивая заказ.)

Итак, нет, это не так. Вы прямо входите в третью проблему. JTS является первым.

Кроме того, вы можете использовать Neo4j Spatial вместо спящего режима. Он использует скорость запросов к графику Neo4j и имеет встроенную поддержку JTS. Он также имеет один из самых удобных Java-API вокруг IMHO.

Ответ 4

У меня была такая же проблема, и я перевел коорды с Lat/Long на UTM (см. http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system).

В основном вы конвертируете из Lat/Long в пару (X, Y), но интересным фактом является то, что эти X и Y являются реальными метрами, поэтому вы можете делать точные вычисления, которые зависят от расстояния. (На самом деле, вы должны учитывать небольшое искажение, но незначительно, если говорить о точности шкалы шкалы).

Я не был доволен функциями LatLong2UTM, которые предоставляли существующие Java-фреймворки, поэтому я развернул свои собственные. Я переносил один из некоторых онлайн-конвертеров без особых проблем.