从PostGIS数据库中读取地理多边形的点

10

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

PostGIS手册提供了一个极好的示例,展示如何从数据库中提取多边形。

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) {
    ...
}

我现在的问题是,我不知道如何修改代码示例的第三行以使其适用于地理信息。我可能不应该将其转换为Polygon类型,因为那只适用于几何信息,但是是否有适用于地理信息的等效物呢?我知道地理信息只有部分功能得到了支持,所以我不确定我在这里可以做什么。


你尝试过使用 st_geometrynst_pointn 吗?伪代码:while (st_geometryn(i)) { while (st_pointn(k)) { process_pt(); k++ } i++ } - unmounted
你需要将多边形从服务器转换为 GEOMETRY - Mike T
@bvmou:ST_GeometryN和ST_PointN仅适用于Geometry,而我正在处理Geography。虽然我没有考虑过在Java端而不是数据库端检索点,但我可以尝试从数据库端获取点。如果我找不到更好的方法,我想我只需执行ST_AsText(polygon)并从中解析出点即可。尽管如此,通过JDBC完成这项任务似乎必须有更好的方法,只是我不知道而已。 - Steph
@Mike Toews:我真的需要强制转换吗?如果可能的话,我想避免这种情况,因为数据在越过日期线、极点以及对于覆盖多个UTM区域的大型几何体或几何体对时,可能不会按预期行事。 - Steph
当涉及到日期线、极点等问题时,GEOMETRY可能会出现异常(例如在计算面积和长度函数时)。我认为这两种类型的数据结构是相同的(即1:1),因此您可以始终将GEOMETRY转换回GEOGRAPHY进行存储或面积/距离计算。然而,我不是JDBC接口的专家,所以您可能需要与postgis-users邮件列表上的人员进行确认。 - Mike T
4个回答

5

我最终决定使用ST_AsText()方法从Postgres获取坐标,而不是从Java中的某种地理对象中提取它们。然后我只需在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]);
    }
}

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


我个人会使用正则表达式来获取点数。 - grasshopper
在SQL中进行子字符串操作,以避免在每一行中发送单词“POLYGON()”,子字符串(ST_AsText(ST_Transform(l.way,4326)),'((.+))')作为路径。 - Stan Sokolov

1
如果您知道该对象是多边形,那么它就非常简单。
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));
    }

0
使用ST_AsGeoJSON,然后解析json即可:
SELECT id, name, ST_AsGeoJSON(area) FROM area_table;

然后你可以像这样获取面积的JSON:

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

现在您已经将它作为geoJSON,您可以解析JSON并对其进行任何您希望的操作。


0
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);
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接