基于PostGIS的高级应用(5)-- Polygon Spliting

一 案例背景

  PostGIS提供了丰富的function用于GIS数据的存储,元数据描述,空间分析,测量,空间图形处理等等,这些函数基本上都很简单,遇到合适的场景时,很容易能知道应该选用哪种function去解决。但有时候的图形处理问题并不是很简单就能实现的,PostGIS核心成员就遇到了社区提出的一个问题:

PostGIS是否有方法能将一个Polygon面切割成若干份小的Polygon面,且每一份的面积差不多大?

输入图形--切割前

输出图形--切割后

其第一反应是:

不可以吧,如此复杂的问题不是sql能解决的。

打脸的是,PostGIS开发者Darafei Praliaskouski解决了这个问题,并分享了解决步骤。本文作者,也就是我,仅仅负责稍微整理下,搬运了下大神们的解决方案,非个人原创。要看原文的朋友,可访问原文:《PostGIS Polygon Splitting》

二 切割步骤

Darafei Praliaskouski提供的切割步骤如下:

  • 使用ST_GeneratePoints方法将一个polygon转换成与面积成比例的一系列的点 (点越多,效果越好,大约1000个点为宜)。


    ST_GeneratePoints
  • 假设计划将Polygon切成k等份,则使用ST_ClusterKMeans方法将这些转换后的点聚合成k簇。


    ST_ClusterKMeans
  • 使用ST_Centroid方法求出每一簇的的均值中心。


    ST_Centroid
  • 将求出的均值中心作为ST_VoronoiPolygons方法的输入参数,可以计算出每个点映射出的Polygon面。


    ST_VoronoiPolygons
  • 使用ST_Intersection将这些映射的面和初始化的Polygon做切割处理,得到结果。


    ST_Intersection

    灵活使用PostGIS的方法,将如此复杂的问题,简单的解决了,堪称完美。

四 实践总结

  百闻不如一见,百看不如一试试,本文作者就是我,看完觉得很赞,于是决定抄抄看看,如何将南京切割成大小相等的十个面,感兴趣的朋友可以按照我的步骤也可以测试测试。
准备测试数据:


测试数据

测试数据
  • 将测试数据写入临时表:
 create table nanjing as select name,geom from city where name='南京市';
  • 面转换为点:
CREATE TABLE nanjing_points AS SELECT (ST_Dump(ST_GeneratePoints(geom, 2000))).geom 
AS geom FROM nanjing;
面转点
  • 点聚合成簇(看原文方法的朋友请注意他的ST_ClusterKMeans写错了)
CREATE TABLE nanjing_pts_clustered AS 
SELECT geom, ST_ClusterKMeans(geom, 10) over () AS cluster FROM nanjing_points;
ST_ClusterKMeans
  • 获取每一簇的均值中心
CREATE TABLE nanjing_centers AS SELECT cluster, ST_Centroid(ST_collect(geom)) AS geom
  FROM nanjing_pts_clustered GROUP BY cluster;
均值中心
  • 使用voronoi算法生成面
  CREATE TABLE nanjing_voronoi AS
  SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(geom)))).geom AS geom
  FROM nanjing_centers;
voronoi
  • 使用ST_Intersection方法切割
CREATE TABLE nanjing_divided AS
  SELECT ST_Intersection(a.geom, b.geom) AS geom
  FROM nanjing a
  CROSS JOIN nanjing_voronoi b;
切割完成

一个个写sql生成的临时表写逻辑方便,但是使用起来比较费劲,我们可以写个function去处理,我使用了临时表,怕事务并发冲突,加了uuid后缀。其实这个逻辑不是很复杂的话,多套用几个with中间表也可以,但是写多了不是很清晰,我就暂时套用上面表的逻辑改成临时表做了个事务,测试通过了:

create extension "uuid-ossp";--创建下uuid的扩展

create or replace function freegis_polygon_split(
    in split_geom geometry(Polygon),--输入的面
    in split_num int,--分割的数量
    out geom geometry(Polygon)--输出切割的面
) returns setof geometry as $$ 
declare  
    rec record; 
begin
    --使用原来的面,切割voronoi算法生成的面
    for rec in SELECT ST_Intersection(split_geom, t.geom) AS geom FROM (
        --voronoi算法生成面
        SELECT (ST_Dump(ST_VoronoiPolygons(ST_collect(voronoi.geom)))).geom AS geom FROM (
            --簇的均值中心
            SELECT clusters.cluster, ST_Centroid(ST_collect(clusters.geom)) AS geom FROM (
                --点ST_ClusterKMeans聚合成簇
                SELECT points.geom, ST_ClusterKMeans(points.geom, split_num) over () AS cluster from (
                    --面内生成点
                    SELECT row_number() over() as gid,(ST_Dump(ST_GeneratePoints(split_geom, 2000))).geom
                ) points
            ) clusters GROUP BY clusters.cluster
        ) voronoi
    ) t loop
        geom:=rec.geom;
        return next;
    end loop;
    return;
end;  
$$ language plpgsql strict; 

测试下通过了:


命令执行

可视化效果

结语:PostGIS还是很强大的!!!另外一定要自己练习。。。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,723评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,080评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,604评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,440评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,431评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,499评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,893评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,541评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,751评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,547评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,619评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,320评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,890评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,896评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,137评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,796评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,335评论 2 342

推荐阅读更多精彩内容