从不相交的多边形创建像Voronoi Diagram这样的镶嵌图


12

下图显示了该问题

在此处输入图片说明

(a)中所示,我有一组不相交的多边形,如 PostGIS中的几何。我需要像(b)这样的一组多边形的 “马赛克”,并根据“影响区域”标准进行构建...就像是Voronoi构造(由(c)所示):实际上,如果多边形是要点,影响区域是沃罗诺伊。

总结:我需要一种SQL算法(或一些特定于PostGIS的算法)来生成一组不相交的多边形的“马赛克”。 (也许是一个小的ST_Buffer和ST_Difference操作的循环)

PS:我需要像Voronoi一样,忽略空间定界((b)中的方形框)。


这个问题和其他有关线路的问题类似。

编辑(@FelixIP评论后)

我倾向于留在向量宇宙中,以免失去精度(例如,使用ST_DelaunayTriangles并通过原始多边形添加和减去内部,它们采用对偶图解决方案)...一些简单而自动的程序包,例如pprepair(如QGIS拓扑工具那样辅助使用)不是自动的)。但是栅格也许更简单,并且占用更少的CPU。

该“ GRID过程”图示也可以作为解决方案,前提是它可以允许相同的精度和“欧几里得影响区域增长”。

在此处输入图片说明

在ARCGIS中,存在着一种称为欧几里得分配的空间分析工具,因此,也许有一种PostGIS类似的解决方案,它从一组多边形开始(对多边形进行分类,栅格化和重新制作)。


感谢@Nir,对点混淆感到抱歉,我没有使用点,仅将多边形用作插图的(a)(b) ...您是否有解决方案的线索链接?
彼得·克劳斯

在Arcgis中,有一个称为欧几里得分配或接近度的栅格解决方案
FelixIP,2015年

感谢@FelixIP,我编辑了“很好的栅格解决方案” ;-)
Peter Krauss

如果您从多边形的range.aspolygon中删除多边形,则会留下多边形。我猜它的骨架是gis.stackexchange.com/questions/177/…。实施是一个大问题
FelixIP 2015年

1
@Cyril,我可以查看您的脚本...下周。发布一些似乎具有现代PostGIS功能解决方案的东西,将是一个不错的第一步。
彼得·克劳斯

Answers:


1

因此,如果我正确理解了这个问题,我将按照您的要求使用PostGis工具为您准备蛋糕-水果拼盘,并且正如我提到的,PostGIS烤箱的操作责任由她的创意团队承担。

我会要求任何人都不要以我的幽默风格来冒犯,并将其理解为一种游戏!

原始文件是切成薄片的水果和简单的形状(以下称为水果),请参见下面的图1。

在此处输入图片说明

这是我的秘诀,亲爱的程序员将为我提供帮助,稍后您将学习。让我们开始吧,为此,我们将创建一个面团,将其放入水果中,并为此运行脚本:

create table poly_extent as SELECT ST_SetSRID(ST_Buffer(ST_Envelope(ST_Extent(geom)),0.05),4326) as geom FROM poly;

参见下面图2的结果

在此处输入图片说明

现在,如果水果很少(如我的图片所示),则在水果上创建外部缓冲区的边界,或者如果水果很多,则创建负缓冲区的边界,并为此运行脚本:

create table poly_buff_dump as SELECT ((ST_Dump(ST_Boundary(ST_Union(ST_Buffer((geom),0.01, 'join=mitre mitre_limit=5.0'))))).geom) geom FROM poly;

并将每个水果的缓冲线切成薄片

UPDATE poly_buff_dump SET geom=ST_RemovePoint(geom, ST_NPoints(geom)-1) WHERE ST_IsClosed(geom)=true; 参见下面图3的结果

在此处输入图片说明

(实际上,我认为结果是会出现虚线(例如圆形),但是如果图形很困难,有时会出现断点,例如矩形的一侧掉落等不正确的断点等。 )

然后,您需要以方便的方式将获得的线划分为相等的线段并从中提取点

create table poly_buff_dump_pt as SELECT (ST_DumpPoints((geom))).geom geom FROM poly_buff_segm;

结果,请参见下面的图4

在此处输入图片说明

现在运行Voronoi工具,在这里我使用了链接MickyT建议的工具:https ://gis.stackexchange.com/a/172246/120129 ,因此,您将创建名称为“ voronoi”的表感谢“我的第一助手”与厨师分开,感谢厨师!:-)。

此步骤的第二种方法是运行ST_VoronoiPolygons函数。

结果,请参见下面的图5

在此处输入图片说明

现在,通过运行脚本切断多余的部分:

create table poly_voronoi_cut as SELECT ST_Intersection(a.geom, b.geom) geom FROM voronoi a INNER JOIN poly_extent b ON ST_Intersects(a.geom, b.geom); 结果,请参见下面的图6。

在此处输入图片说明

现在运行脚本以在LineString中对齐地理数据类型:

create table poly_voronoi_dump as SELECT (ST_Dump(geom)).geom as geom FROM poly_voronoi_cut; 现在我会问:“我的二副”拿起我的职责和混合蛋糕WEL(杰夫- /gis//a/785/120129),练级吧单层,并为,谢谢我!

CREATE TABLE poly_overlay_cut AS SELECT geom FROM ST_Dump(( SELECT ST_Polygonize(geom) AS geom FROM ( SELECT ST_Union(geom) AS geom FROM ( SELECT ST_ExteriorRing(geom) AS geom FROM poly_voronoi_dump) AS lines ) AS noded_lines ) ); 现在是我开始工作的时候了,为此我运行了脚本:

create table poly_voronoi_union as SELECT b.id, (ST_ConvexHull(ST_Union(a.geom, b.geom))) geom FROM poly_overlay_cut a INNER JOIN poly_buff_dump b ON ST_Intersects(a.geom, b.geom) GROUP BY b.id, a.geom, b.geom; 和另一个脚本:

create table poly_voronoi_union_area as SELECT ST_Union(ST_ConvexHull(ST_BuildArea(geom))) as geom FROM poly_voronoi_union GROUP BY id; 参见下面的图7

在此处输入图片说明

如您在图片中所看到的,我们的剪切具有较小的图层,可以使用ST_SnapToGrid(或以其他方式)将其删除,作为一个选项:

最后,我们将从馅饼中切出烤好的水果,我什至有点不耐烦地站在烤箱旁,:-)

create table polygon_voronoi_result as SELECT (ST_Dump(ST_Difference(a.geom, b.geom))).geom as geom FROM poly_voronoi_union_area_snap as a JOIN poly b ON ST_Intersects(a.geom, b.geom); 结果见图8 在此处输入图片说明

从这一天开始的一切,现在每个人都将学会烤美味的馅饼-水果拼盘。全力以赴,选择适合自己的零配件。

(可惜我真的不能养活所有人,不是用电子蛋糕,而是用真正的蛋糕,也许饥饿会在地球上终结...)

编辑:馅饼上的樱桃可能看起来像这样:-):

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM poly),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT ST_Intersection(a.geom, b.geom) geom FROM tblb a JOIN poly_extent b ON ST_Intersects(a.geom,b.geom)),
tbld AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM poly GROUP BY id, geom)
SELECT id, ST_Union(a.geom) as geom FROM tblc a JOIN tbld b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

要么

WITH
tbla AS (SELECT (ST_DumpPoints(geom)).geom geom FROM polygons),
tblb AS (SELECT ((ST_Dump(ST_VoronoiPolygons(ST_Collect(geom)))).geom) geom FROM tbla),
tblc AS (SELECT id, ((ST_Dump(geom)).geom) geom FROM polygons GROUP BY id, geom)
SELECT id, ST_Union(a.geom) geom FROM tblb a JOIN tblc b ON ST_Intersects(a.geom, b.geom) GROUP BY id;

贝克先生,您真是个好人,谢谢大家,祝您好运,:-)...

原始解决方案。

该脚本称为:ST_VoronoiDiagramsFromPolygons。


1
嗨,好的插图,而且效果不错(!)。建议以一个简短的讨论,请参见@geogeek的解决方案,在QGIS步骤似乎PostGIS的主要步骤在这里...为什么E需求 ST_BufferST_ConvexHull?有替代算法吗?
彼得·克劳斯

1)参见,创建ST_Buffer和on多边形是为了在应用Voronoi函数期间减少原始图形之间的分隔线,因此,可以指定的缓冲区大小越大,分隔线的构建就越平滑。一个Voronoi函数... 2)每个多边形上大量图形的ST_ConvexHull,我们需要的多边形... 3)今天,这是我解决您的问题的愿景,我不知道我们所有人都会发生什么和我们未来的决定...
西里尔·米哈尔琴科

缓冲线的另一个重要价值是,它们将帮助我们从Voronoi函数的结果中选择片段,以为每种形状创建组合的多边形……
Cyril Mikhalchenko,

顺便说一句,我欢迎代码和方法的改进,以使它们不会恶化结果……
西里尔·米哈尔琴科

1
嗨,西里尔(Cyril),我同意ST_Buffer是规范轮廓线的理想选择,完美(!)。About ST_ConvexHull只是一个好奇,在poly_voronoi_union没有ST_ConvexHull的情况下,我们可以在图6之后获得什么样的结果。
彼得·克劳斯

8

Postgis没有用于voronoi的专用功能,但是Qgis包含可以从点组成voronoi多边形的vornoi函数,因此使用qgis我遵循了以下步骤来获得这些结果:

-使用extract nodes函数从多边形制作点。

使用Qgis中的voroi函数制作vornoi多边形。

-在Qgis中进行空间连接。

-溶解结果。

在此处输入图片说明


1
不错的解决方案(!),并感谢插图。你能增强它吗?参见下面的左侧矩形,在Voronoi处为4点,矩形的中心没有表示,从而扭曲了其区域(向三角形丢失)...也许可以对每个多边形进行定期采样来增强效果...并且也许还有一些内在点。
彼得·克劳斯

我在ArcGIS中使用密集工具。这显着改善了邻近多边形。+1
FelixIP '16

3

好的-考虑了一下,发现它就像我最近一直在看的东西。

采取您的起始多边形:

在此处输入图片说明

生成一个带有数字(在我的情况下为100)的新属性,使用“矢量”->“研究”工具->“多边形内的随机点”工具,这将在每个多边形内生成(100)个点: 在此处输入图片说明

然后“矢量”->“几何工具”->“ Voronoi”基于该点图层生成多边形。

在此处输入图片说明

现在,您可以使用向量->空间查询工具:选择属于一个多边形(或其中一个多边形)的点。使用空间查询工具生成适用于该多边形的voronoi多边形的选择。将一个属性添加到与感兴趣的多边形相对应的voroni多边形。(我只用了1,2,3,4)

现在,您可以根据您的新属性,在“向量”->“地理处理工具”->“溶解”中进行选择。

在此处输入图片说明


感谢@AAmes(!),插图很好,该方法是一个很好的选择...但是问题是关于“ SQL算法(或某些特定于PostGIS的算法)”,现在是关于使用该函数的赏金ST_VoronoiPolygons(),也许一键即可解决所有问题;-)
Peter Krauss

@AAmes快速搜索显示该方法确实也可以在PostGIS中使用。在postgis中如何在多边形中创建随机点说明了从多边形创建点的方法,从那里开始应该很简单。
Phil G'1

我的赏识是对您的鼓励(欢迎在这里!),但是对于问题和赏金要求,此答案是不满意的。
彼得·克劳斯

谢谢彼得,我看了你的笔记,但不幸的是我没有机会再来解决它。我还没有PostGIS方面的经验,这将花费我很多时间来提供任何良好的响应。我希望我们对这个空间的探索对将来的人们有帮助,也许如果我很快就对PostGIS有所了解,我会回来并再次尝试它!
AA

2

随机点是从多边形生成voronoi多边形的一个好主意,它工作得很好,但是对于彼此靠近的多边形来说却很糟糕: 在此处输入图片说明 在此处输入图片说明

如果使用PostGIS,则ST_近似MedialAxis是另一个不错的选择: 计算多边形的Voronoi图

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.