将lat / long转换为JTS?

时间:2011-12-06 17:25:29

标签: java hibernate jpa geolocation geospatial

我正在尝试将hibernate空间与JPA集成以进行地理搜索。我一直在官方网站上引用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;
    }
}

4 个答案:

答案 0 :(得分:25)

JTS并不关心你的点的单位或坐标系是什么。

但是,it does assume that the coordinates are on a Cartesian plane,因此一些几何操作(如距离计算)可能在长距离上不准确。 (他们还不支持大地测量计算。)

对于简单的存储用途应该没问题。

然而,需要注意的一点是,经度是X值,纬度是Y值。所以我们说“lat / long”,但是JTS会按照“long / lat”的顺序来预期它。所以你应该使用geometryFactory.createPoint(new Coordinate(longitude, latitude))

答案 1 :(得分:2)

总结其他人所说的,转换为坐标时,有三件事需要处理:

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

所以,不,那不对。你直接陷入了第三个问题。 JTS是第一个。

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

答案 2 :(得分:1)

以下是如何在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 :(得分:0)

我在这里遇到了同样的问题,我将来自Lat / Long的坐标转换为UTM(参见http://en.wikipedia.org/wiki/Universal_Transverse_Mercator_coordinate_system)。

基本上你从Lat / Long转换为(X,Y)对,但有趣的是,那些X和Y是真实的米,因此你可以进行精确的计算,这取决于距离。 (实际上,你必须考虑一个小的失真,但在谈论米级精度时可以忽略不计)。

我对现有Java框架提供的LatLong2UTM功能并不满意,所以我推出了自己的功能。我从一些在线javascript转换器移植了一个没有太多麻烦。