【问题标题】:Postgis - ST_within didn't do what I want. How to find a point in a hollow area?Postgis - ST_within 没有做我想做的事。如何在空心区域找到一个点?
【发布时间】:2020-06-13 02:26:47
【问题描述】:

查看屏幕打印。

我在 Postgis 中运行了一个空间查询,以返回地图上某个点所在的选区(区域)。该查询使用ST_within 函数,其中该点位于多边形内。

正如您从打印中看到的那样,该点实际上并不在 York Outer 的多边形区域中,尽管从技术上讲,您可能会说它在它的“内部”,或者至少 Postgis 是这么认为的。重点实际上在于约克中心。

我确定 Postgis 实际上返回了两者,但由于我只从游标中获取第一条记录,这就是我所看到的。

一个点一次只能在一个选区中,这个查询返回了错误的,或者我问了错误的数据库问题。

我应该使用哪个函数来确保我始终返回正确的区域,因为该区域可能具有中空的内部或奇怪的形状?

谢谢

菲尔

【问题讨论】:

  • 谢谢 (@Jim Jones) 和 (@Michael Entin),我的第一个想法是 ST_within 没有像我想象的那样工作,但我会用实际的数据/查询更新我的问题和下周初提示。如果可以的话,我会很感激你们看看,菲尔

标签: postgresql leaflet geospatial postgis


【解决方案1】:

这应该像你描述的那样工作。也许数据有问题?你能提供一个带有多边形/点数据的小型复制品吗?

此外,此类问题的一个常见原因是无效的 GIS 数据。您可以使用 PostGIS 的 ST_IsValid 函数检查多边形形状。如果数据无效,不同的工具可能会以不同的方式对其进行解释,并且 GIS 数据的绘制方式可能与 PostGIS 认为该数据所代表的不匹配,从而导致更多的混乱。

这是一个简单的重现,显示它可以按预期工作,外部多边形孔内的点仅st_within 内部多边形,而不是外部多边形:

select st_astext(point), name 
from 
  (select 
       'outer' as name, 
       st_geomfromtext('polygon((0 0, 30 0, 30 30, 0 30, 0 0), (10 10, 20 10, 20 20, 10 20, 10 10))') g
  union all 
  select 
      'inner' as name, 
       st_geomfromtext('polygon((10 10, 20 10, 20 20, 10 20, 10 10))') g
  ) shapes
cross join
  (select st_geomfromtext('point(15 15)') point
   union all
   select st_geomfromtext('point(5 5)') point
  ) points
where st_within(point, g)

我的结果是

1   POINT(5 5)     outer
2   POINT(15 15)   inner

【讨论】:

  • 感谢 (@Michael Entin) 的回答帮助我解决了这个问题,并感谢 (@Jim Jones) 的帮助。
  • 使用 ST_isvalid,我能够确定我在 650 个数据集中有 3 个无效形状,所有形状都带有“嵌套壳”的 ST_isvalidreason()。这三个选区都被挖空了。数据最初来自 (ons-inspire.esriuk.com/arcgis/rest/services/…),尽管我可能在导入它的方式上犯了错误。我能够使用 ST_makevalid 解决问题。它现在按预期找到“York Central”。使用ST_isvalid()查看数据!
【解决方案2】:

考虑到您的多边形和查询是您描述的方式,它应该可以正常工作。考虑以下几何形状..

.. 您会看到该点仅位于内部多边形内。如果您使用ST_Within 执行查询并给出该点的坐标,您应该获得内部多边形:

WITH j (geom) AS (VALUES 
  ('POLYGON((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))'),
  ('POLYGON((26.88 31.08,30.57 31.08,30.57 28.49,26.88 28.49,26.88 31.08))'))
SELECT * FROM j
WHERE ST_Within('POINT(28.46 28.64)',j.geom)

但是,如果您的查询以某种方式使用多边形的 BBOX 而不是它们的面积,您确实也会得到外部多边形,例如:

WITH j (geom) AS (VALUES 
  ('POLYGON((35 10, 45 45, 15 40, 10 20, 35 10),(20 30, 35 35, 30 20, 20 30))'),
  ('POLYGON((26.88 31.08,30.57 31.08,30.57 28.49,26.88 28.49,26.88 31.08))'))
SELECT * FROM j
WHERE ST_Within('POINT(28.46 28.64)',j.geom::GEOMETRY::BOX2D)

考虑将数据样本和查询添加到您的问题中。希望它可以帮助您调试代码。

【讨论】:

    猜你喜欢
    • 2014-07-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-13
    • 1970-01-01
    • 2020-11-26
    • 2011-03-28
    相关资源
    最近更新 更多