Преобразование 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-фреймворки, поэтому я развернул свои собственные. Я переносил один из некоторых онлайн-конвертеров без особых проблем.