稀释许多ST_Points

时间:2011-01-10 20:50:23

标签: sql geospatial postgis

我在Postgres-db中有很多(1.000.000)个ST_Points和postgis 延期。当我在地图上显示它们时,浏览器变得非常繁忙。 为此我想写一个sql语句,它将高密度过滤到只有一点 当用户缩小100个ST_Points时,postgres应该只返回一个。 但只有这些点紧密相连 我用这句话试了一下:

select a.id, count(*)
from points as a, points as b
where st_dwithin(a.location, b.location, 0.001)
and a.id != b.id
group by a.id

我会称之为稀薄,但没有找到任何东西 - 也许是因为我 不是母语为英语的人。 有人有什么建议吗?

4 个答案:

答案 0 :(得分:2)

我同意tcarobruce群集是你正在寻找的术语。但它可以在postgis中找到。

基本上可以通过减少X和Y中的小数位数并对它们进行分组来实现聚类;

select 
  count(*),
  round(cast (ST_X(geom) as numeric),3)
  round(cast (ST_Y(geom) as numeric),3)
from mytable 
group by 
round(cast (ST_X(geom) as numeric),3), 
round(cast (ST_Y(geom) as numeric),3)

这将产生一个表格,其中包含坐标和该坐标处的实际点数。在这个特定的示例中,它会在您的初始语句中留下3位小数的舍入值,0.001。

答案 1 :(得分:1)

您可以使用ST_ClusterDBSCAN

将附近的点聚在一起

然后保留所有单点,例如:

  1. 每个集群选择一个随机点

  1. 选择每个点簇的质心。

我使用eps 300将300米内的点聚在一起。

create table buildings_grouped as
SELECT geom, ST_ClusterDBSCAN(geom, eps := 300, minpoints := 2) over () AS cid
FROM buildings

enter image description here

1:

create table buildings_grouped_keep_random as
select geom, cid from buildings_grouped
where cid is null
union
select * from 
(SELECT DISTINCT ON (cid) *
FROM buildings_grouped
ORDER BY cid, random()) sub

enter image description here

2:

create table buildings_grouped_keep_centroid as
select geom, cid from buildings_grouped
where cid is null
union
select st_centroid(st_union(geom)) geom, cid
from buildings_grouped
where cid is not null
group by cid

enter image description here

答案 2 :(得分:0)

您正在寻找的术语是“群集”。

client-side个库可以执行此操作,还有commercial services可以执行此操作。

但这不是PostGIS原生的做法。 (它有一个ticket。)

您可能必须编写自己的解决方案,并提前预先计算群集。

答案 3 :(得分:0)

基于 ST_ClusterDBSCAN 和 KMeans 的聚类有效,但速度非常慢!对于大数据集。所以它实际上是无法使用的。像 ST_SnapToGrid 和 ST_RemoveRepeatedPoints 这样的 PostGIS 函数速度更快,在某些情况下可以提供帮助。但我认为最好的方法是使用像 sample filter 这样的 PDAL 细化过滤器。我建议将它与 PG Point Cloud 一起使用。

编辑: ST_SnapToGrid 非常快速且有用。以下是使用优化进行三角剖分的示例查询:

    WITH step1 AS 
    (
        SELECT geometry, ST_DIMENSION(geometry) AS dim FROM table
    )
    , step2 AS 
    (
        SELECT ST_SIMPLIFYVW(geometry, :tolerance) AS geometry FROM step1 WHERE dim > 0
        UNION ALL
        (WITH q1 AS
        (
            SELECT (ST_DUMP(geometry)).geom AS geometry FROM step1 WHERE dim = 0
        )
        SELECT ST_COLLECT(DISTINCT(ST_SNAPTOGRID(geometry, :tolerance))) FROM q1)
    )
    , step3 AS 
    (
        SELECT ST_COLLECT(geometry) AS geometry FROM step2
    )
    SELECT ST_DELAUNAYTRIANGLES(geometry, :tolerance, 0)::BYTEA AS geometry
    FROM step3 
    OFFSET :offset LIMIT :limit;