介绍
NetTopologySuite 2.x
提供了GeometryFixer类,该类能够将几何体修复为有效几何体,同时尽可能保留输入的形状和位置。几何的IsValid
属性,反映了几何是否是有效的。
输入的几何图形始终会被处理,因此即使是有效的输入也可能会有一些微小的更改。输出始终是一个新的几何体对象。
自动修复规则
- 删除具有X、Y坐标无限大(或无限小)的顶点(根据IsValid属性)
- 重复的点减少到一个点
- 空几何的结构是有效的,不作修复
- 从集合中删除空元素
Point
:保持有效坐标,或为空LineString
:修复坐标LinearRing
:修复坐标,保持环的有效性或将其转为LineStringPolygon
:转换为有效的多边形,尽可能多地保留范围和顶点
- 环被修复,以保证环是有效的
- 从外轮廓中减掉孔洞
- 外轮廓线外部的孔洞会被转为
Polygon
MultiPolygon
:每个多边形都被修复,并且它们之间不会重叠,否则会被合并成一个多边形GeometryCollection
:每个元素都被修复- 通过为
GeometryFixer
设置参数keepCollapse
,折叠线和多边形的处理方式如下:
keepCollapse=false
,这是默认值,“形状萎缩退化”的几何会变成空几何图形(如果它们是集合的元素,则会被删除)keepCollapse=true
,“形状萎缩退化”的几何会被转化为较低维度的有效几何图形
注意:NetTopologySuite 1.x
版本没有提供GeometryFixer
这个类,需要使用2.x
的版本。
对多边形的修复测试
测试1、单个自相交多边形被修复为多个有效的多边形
使用该博客中提到的两个自相交多边形进行测试:
public void TestMethod1()
{
var r = new WKTReader();
var wkts = new string[]
{
"POLYGON((0 2, 2 2, 0 0, 2 0, 0 2))",
"POLYGON((0 0, 1 1, 2 0, 3 0, 4 1,5 0,0 0))"
};
var geos = wkts.Select(x=>r.Read(x)).ToList();
var fixedGeos = geos.Select(x => GeometryFixer.Fix(x)).ToList();
foreach (var item in fixedGeos)
{
Trace.WriteLine(item.AsText());
}
}
输出的结果:
MULTIPOLYGON (((0 2, 2 2, 1 1, 0 2)), ((1 1, 2 0, 0 0, 1 1)))
MULTIPOLYGON (((0 0, 1 1, 2 0, 0 0)), ((3 0, 4 1, 5 0, 3 0)))
可以发现修复结果是正确的:
- 第一个漏斗形状的多边形,被修复为三角形形状的两个多边形
- 第二个多边形,被修复为三角形形状的两个多边形
测试2、自相交形成“内部洞”,但修复后无洞
多边形ABCDEFGH,是自相交的,并且在内部自相交出一个“洞”。
由于多边形本身不带洞,所以修复后,也不带洞。
修复前的WKT:Polygon((0 0,0 3,2 3,2 1,1 1,1 2,3 2,3 0,0 0))
,
修复后的WKT:POLYGON ((0 0, 0 3, 2 3, 2 2, 3 2, 3 0, 0 0))
测试3、自相交形成“内部洞”,且修复后有洞
与上面相似但不同的是,多边形ABCDEFGHIFEA被修复后得到一个有洞的多边形,即多边形JKLM带有洞NQPO。
修复前的WKT:Polygon((0 0,0 3,3 3,3 0,1 0,1 1,2 1,2 2,1 2,1 1,1 0,0 0))
,
修复后的WKT:POLYGON ((0 0, 0 3, 3 3, 3 0, 1 0, 0 0), (1 1, 2 1, 2 2, 1 2, 1 1))
测试4、对测试2的调整,使其修复后有洞
修复后是否有洞,与折线的交叉方向、形式有关。
对测试2中的输入几何做略微调整,便可以得到有洞的多边形:
修复前的WKT:Polygon((0 0,0 3,2 3,2 2,1 2,1 1,2 1,2 2,3 2,3 0,0 0))
,
修复后的WKT:POLYGON ((0 0, 0 3, 2 3, 2 2, 3 2, 3 0, 0 0), (2 2, 1 2, 1 1, 2 1, 2 2))