我在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
我会称之为稀薄,但没有找到任何东西 - 也许是因为我 不是母语为英语的人。 有人有什么建议吗?
答案 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
将附近的点聚在一起然后保留所有单点,例如:
或
我使用eps 300
将300米内的点聚在一起。
create table buildings_grouped as
SELECT geom, ST_ClusterDBSCAN(geom, eps := 300, minpoints := 2) over () AS cid
FROM buildings
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
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
答案 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;