ST_Union()vs ST_Node(ST_Collect())在很多相交的ST_ExteriorRing(圆圈)上

时间:2014-08-24 13:12:21

标签: sql postgresql postgis computational-geometry

我有近10,000个相同大小的圆圈,我用它来根据重叠圆圈的数量创建热图。

enter image description here

我有两个版本的第2步正在运行。一个比另一个更有效吗?我应该尝试不同的方法吗?

以下是我试图完成此任务的方法:

  1. 获取圈子的轮廓(跑得很快)

    create table circle_outlines as 
        SELECT distinct ST_ExteriorRing(the_circle) AS the_geom FROM circle_list;
        create index idx_geom_circle_outlines  on circle_outlines  using gist (the_geom);
        select distinct geometrytype(the_geom) from circle_outlines ; -- LINESTRING
    
         

    QGIS中此表的输出:   比例为1:38,167,029 - [oi60.tinypic.com/23uwytv.jpg] [2]   以1:234,378的比例进入东北密集区 - [oi59.tinypic.com/96i4xt.jpg][2]

  2. 将这些行组合在一起(请参阅帖子的结尾,了解正在考虑的两种方法

  3. 一个。检查创建的geom类型,如果感兴趣(应该是GEOMETRYCOLLECTION)

    湾合并边框的多边形化(ST_Dump((ST_Polygonize(the_geom)))

  4. 使用ST_PointOnSurface(polygonized_geoms)在内部添加点

  5. 计算num_overlaps

  6. 我正在尝试的两个步骤

    create table noded_circles as 
    SELECT ST_Node(ST_Collect(the_geom)) AS the_geom FROM circle_outlines;
    -- been running 7 hours - 100% cpu - 2199 MB (24%) memory
    

    create table noded_circles as 
    SELECT ST_Union(the_geom) AS the_geom FROM circle_outlines;
    -- been running 43 hours - 100% cpu - 4086 MB (48%) memory
    

    因此,为了“展平”相同大小的交叉圆的线串,st_union()和st_node(st_collect())之间的性能是否存在差异?还有更好的方法吗?

    - 更新:由于内存不足,两个查询都被终止了。

2 个答案:

答案 0 :(得分:0)

我使用以下内容在10,000乘10,000网格上创建一个10,000点的随机集合,点半径为500.

drop table circles; 
create table circles as select g as id, 
    st_buffer(st_makepoint(random()*10000, random()*10000), 500) as geom 
from generate_series(1, 10000) g; 
create index ix_spatial_circles on circles using gist(geom);

使用它,我想出了以下查询,该查询生成原始多边形ID列表,与此相交的其他多边形的数量,交叉点和区域。对于10,000个网格上10,000个半径为500的圆形网格,此查询在我们的一个服务器上运行大约20分钟。我不确定是否值得进入硬件细节,因为我怀疑计算的复杂性非常依赖于网格的密度,圆的半径等,因此设置与您的环境完全相同的环境是有问题的。

select id, max(total_intersected) as "total intersected", st_area(st_union(geom)) as area   
from 
  (select a.id as id, array_agg(b.id) as b_int, 
          sum(case when st_intersects(a.geom, b.geom)='t' then 1 else 0 end) as total_intersected, 
          array_agg(b.geom) as geom 
  from 
    circles a, circles b 
  where  st_intersects(a.geom, b.geom)  group by a.id) agg 
where id=any(b_int) group by id, geom order by max(total_intersected) desc;

子查询中的主要思想是找到与所有其他多边形相交的所有多边形(通过ID)(使用空间自连接)并构建这些ID的数组(array_agg(b.id),作为查找两个多边形是否相交,比找到它们的实际交点更快;然后,在外部查询中,找到实际的交点,但只考虑那些已知为每个输入多边形相交的多边形,即where id=any(b_int)部分我怀疑这可能比尝试使用ST_Collect或ST_Union一次性结合所有圆(多边形)更快,因为您在已知交叉的多边形上操作,而不是在一个巨大交叉点中的所有多边形。

对于它的价值,我对比较ST_Union(geom)和ST_Node(ST_Collect(geom))的随机点集进行了一些测试,整体上ST_Union的速度略快,但我认为有太多的自由变量这是一个非常科学的发现。

答案 1 :(得分:0)

我最终采用的方法是QGIS中的HeatMap插件。 http://www.qgistutorials.com/en/docs/creating_heatmaps.html 我使用Uniform内核来允许我按栅格的值对重叠的数量进行分类。