【问题标题】:Reading points from a Geography Polygon in a PostGIS database从 PostGIS 数据库中的地理多边形读取点
【发布时间】:2011-10-01 16:08:18
【问题描述】:

我的目标:从存储在我的 PostGIS 数据库中的地理多边形中读取点。

PostGIS 手册中有 a great example 说明如何从数据库中提取多边形。

PGgeometry geom = (PGgeometry)r.getObject(1); 
if (geom.getType() == Geometry.POLYGON ) { 
  Polygon pl = (Polygon)geom.getGeometry(); 

  for (int r = 0; r < pl.numRings(); r++) { 
    LinearRing rng = pl.getRing(r); 
    System.out.println("Ring: " + r); 

    for (int p = 0; p < rng.numPoints(); p++ ) { 
      Point pt = rng.getPoint(p); 
      System.out.println("Point: " + p);
      System.out.println(pt.toString()); 
    } 
  } 
}

我处理的是地理,但不是几何,所以这段代码不太适合我。如果我尝试从表中提取多边形,我会得到以下ClassCastException

org.postgresql.util.PGobject cannot be cast to org.postgis.PGgeometry

我已将前两行修改为如下所示,这样可以:

PGobject area = (PGobject)rs.getObject("area");
if (area.getType().compareTo("geography") == 0) {
    ...
}

我现在的问题是我不知道如何修改代码示例的第三行以适用于 Geography。我可能不应该将它转换为Polygon 类型,因为那是用于几何的,但是地理是否有等价物?我知道很多东西只部分支持 Geography,所以我不确定我能在这里做什么或不能做什么。

【问题讨论】:

  • 你试过st_geometrynst_pointn吗?伪代码:while (st_geometryn(i)) { while (st_pointn(k)) { process_pt(); k++ } i++ }?
  • 您需要以某种方式从服务器将多边形投射到GEOMETRY
  • @bvmou:ST_GeometryN 和 ST_PointN 仅适用于 Geometry,而我正在使用 Geography。不过,我没有考虑尝试在数据库端检索点,而不是在 Java 端。我想我可以做一个ST_AsText(polygon) 并解析那里的点,如果我想不出更好的东西的话。不过,似乎必须有更好的方法通过 JDBC 来做到这一点,我只是不知道。
  • @Mike Toews:我真的必须投吗?如果可以的话,我想避免这种情况,因为在跨越日期变更线、极点以及覆盖多个 UTM 区域的大型几何图形或几何图形对时,数据可能无法按预期运行。
  • 当您尝试使用面积和长度函数时,GEOMETRY 可能会出现异常(围绕日期线、极点等)。我相信这两种类型之间的数据结构是相同的(即 1:1),因此您始终可以将 GEOMETRY 转换回 GEOGRAPHY 以进行存储或面积/距离计算。但是,我不是 JDBC 接口的专家,所以您可能想与 postgis-users 邮件列表上的人核实一下。

标签: java postgresql jdbc postgis


【解决方案1】:

我最终决定使用 ST_AsText() 方法从 Postgres 获取坐标,而不是从 Java 中的某种 Geography 对象中提取它们。然后我只是用Java解析了多边形字符串。

我执行的 PostgreSQL 语句如下所示:

SELECT id, name, ST_AsText(area) FROM area_table;

在 Java 中,我在执行 JDBC 查询后从 ResultSet 中提取字符串:

String area = rs.getString("ST_AsText");

我得到的东西看起来像这样:

"POLYGON((-49 52,123 52,123 -4,-49 -4,-49 52))"

然后我只是从中解析出要点。

double[] bounds = new double[8];
int k = 0;
for (int i = 0; i < points.length; i++) {
    String[] lonLat = points[i].split(" ");
    for (int j = 0; j < lonLat.length; j++) {
        bounds[k++] = Double.parseDouble(lonLat[j]);
    }
}

我不知道这是否是最好的方法,但这是我自己能想到的最好方法。

【讨论】:

  • 我个人会使用正则表达式来获得积分。
  • 也在 SQL 中做子字符串以避免为每一行发送单词 "POLYGON(" substring(ST_AsText(ST_Transform(l.way,4326)),'((.+))') 作为方式
【解决方案2】:

如果你知道对象是一个多边形,那就很简单了。

PGpolygon polygon = (PGpolygon)rs.getObject("area");

for (int i = 0; i < polygon.points.length; i++)
    {
    System.out.println(String.format("(%d,%d)" polygon.points[i].x, polygon.points[i].y));
    }

【讨论】:

    【解决方案3】:
    PGgeometry geo = (PGgeometry)rs.getObject("coords");
    Geometry poly = foo.getGeometry();
    for (int i = 0; i < poly.numPoints(); i++)
    {
        System.out.println("-->"+poly.getPoint(i).y+", "+ poly.getPoint(i).x);
    }
    

    【讨论】:

      【解决方案4】:

      使用 ST_AsGeoJSON,然后只解析 json:

      SELECT id, name, ST_AsGeoJSON(area) FROM area_table;
      

      然后你可以像这样获取区域为json:

      String area = rs.getString("area");
      

      现在您已将它作为 geoJSON,您可以解析 JSON 并用它做任何您想做的事情。

      【讨论】:

        猜你喜欢
        • 2018-11-12
        • 2019-10-31
        • 1970-01-01
        • 2014-05-03
        • 2018-06-27
        • 1970-01-01
        • 1970-01-01
        • 2011-03-21
        • 2020-07-18
        相关资源
        最近更新 更多