将纬度/经度转换为 JTS?

2022-09-01 23:03:34

我正在尝试将休眠空间与JPA集成以进行地理搜索。我一直在参考官方网站上的教程(我不与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

总结一下其他人所说的,当转换为坐标时,有3件主要的事情需要注意:

  • 投影。JTS在笛卡尔平面上工作,因此墨卡托等的所有失真都会传播到您的计算中。因此,您应该只在相当短距离的区域使用它。我不确定确切的幅度,但我认为低于一定程度的扩张应该没问题。保持在0.1度以下,你绝对在安全的一面。
  • 单位。你可以把任何单位完美地放入JTS中。麻烦的是,您无法判断JTS是否使用米,度数或其他任何东西。因此,您必须注意自己,要么坚持一个单位,要么在必要时进行转换。
  • 标准。ISO 标准规定,地理空间坐标首先提供纬度。但是,它与GeoJSON / WKT标准竞争,这两个标准都首先声明lon,所以相反。这两个标准组都有应用程序坚持使用它们(例如,Apache Lucene在不更改方法签名的情况下在版本之间切换标准,从而给数百名用户带来了麻烦,想知道为什么他们的地图突然被翻转),JTS坚持使用GeoJSON / WKT版本。请注意,无论您从另一个库传递数据 - 它可能遵循GeoJSON和WKT或ISO,您应该提前通知自己。(相信我。我已经遇到了麻烦,浏览整个代码并翻转顺序可能真的很烦人。

所以,不,这是不对的。你直接走进了第三个问题。JTS是lon first。

此外,您可以考虑使用Neo4j Spatial而不是休眠。它使用Neo4j的图形查询速度,并具有内置的JTS支持。它还有一个最舒适的Java API,恕我直言。


推荐