使用NetTopologySuite偏移C#多边形出现多余线条问题求助
多边形偏移(Buffer)结果异常排查与修复
我正在开发一个基于C#的几何项目,使用NetTopologySuite库。自定义了Z_Point类(构造函数接收X、Y、Z三个double参数)与Z_Polygon类(构造函数接收点列表)。为实现多边形偏移,Z_Polygon的Offset方法实现如下:
public List<Z_Polygon> Offset(double distance) { Coordinate[] coords = new Coordinate[Vertices.Count]; for (int i = 0; i < this.Vertices.Count; i++) { coords[i] = new Coordinate(this.Vertices[i].X, this.Vertices[i].Y); } LinearRing rng1 = new LinearRing(coords); Polygon pol1 = new Polygon(rng1); var bufParams = new BufferParameters(); bufParams.MitreLimit = 5; bufParams.JoinStyle = JoinStyle.Mitre; Geometry b = BufferOp.Buffer(pol1, distance, bufParams); List<Z_Polygon> result = new List<Z_Polygon>(); List<Z_Point> newVertices = new List<Z_Point>(); if (b is MultiPolygon) { b = (MultiPolygon)b; for (int i = 0; i < b.NumGeometries; i++) { Polygon pol = (Polygon)b.GetGeometryN(i); Geometry g = (Geometry)pol; foreach (var item in pol.Coordinates) { newVertices.Add( new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); } } else { Polygon pol = (Polygon)b; foreach (var item in pol.Coordinates) { newVertices.Add(new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); } return result; }
但该方法未返回正确结果,出现了不必要的多余线条。测试用多边形代码如下:
Z_Point p1 = new Z_Point(1300.0, 1200.0); Z_Point p2 = new Z_Point(1300.0, 9800.0); Z_Point p3 = new Z_Point(6200.0, 9800.0); Z_Point p4 = new Z_Point(6200.0, 6500.0); Z_Point p5 = new Z_Point(2600.0, 6500.0); Z_Point p6 = new Z_Point(2600.0, 5300.0); Z_Point p7 = new Z_Point(10700.0, 5300.0); Z_Point p8 = new Z_Point(10700.0, -2900.0); Z_Point p9 = new Z_Point(3200.0, -2900.0); Z_Point p10 = new Z_Point(3200.0, -800.0); Z_Point p11 = new Z_Point(9700.0, -800.0); Z_Point p12 = new Z_Point(9700.0, 1200.0); Z_Polygon polygon1 = new Z_Polygon(new List<Z_Point>() { p1, p2, p3, p4, p5, p6, p7, p8, p9, p10, p11, p12, p1 }); List<Z_Polygon> new_polygon = polygon1.Offset(-800);
问题原因分析
- 顶点列表未重置:处理
MultiPolygon时,newVertices列表未在每个子多边形处理前清空,导致后续子多边形顶点追加到前一个列表中,生成错误多边形。 - 多边形拓扑方向错误:原始多边形顶点顺序可能不符合NetTopologySuite的标准规则(外环逆时针、内环顺时针),负距离偏移时容易出现拓扑异常。
- Mitre连接风格适配问题:Mitre连接在小角度下会产生过长尖刺,复杂多边形内角处偏移时易引发拓扑错误。
修复方案
1. 重置子多边形顶点列表
每个子多边形单独创建顶点列表,避免顶点累积:
if (b is MultiPolygon multiPolygon) { for (int i = 0; i < multiPolygon.NumGeometries; i++) { List<Z_Point> newVertices = new List<Z_Point>(); Polygon pol = (Polygon)multiPolygon.GetGeometryN(i); foreach (var item in pol.Coordinates) { newVertices.Add(new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); } } else if (b is Polygon pol) { List<Z_Point> newVertices = new List<Z_Point>(); foreach (var item in pol.Coordinates) { newVertices.Add(new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); }
2. 修正多边形拓扑方向
使用NetTopologySuite内置方法将多边形调整为标准拓扑结构:
Polygon pol1 = new Polygon(rng1); pol1 = (Polygon)pol1.Orient(); // 自动修正外环逆时针、内环顺时针
3. 调整Buffer连接风格
改用更稳定的Round连接风格,避免尖刺问题:
var bufParams = new BufferParameters(); bufParams.JoinStyle = JoinStyle.Round;
完整修复后的Offset方法
public List<Z_Polygon> Offset(double distance) { Coordinate[] coords = new Coordinate[Vertices.Count]; for (int i = 0; i < this.Vertices.Count; i++) { coords[i] = new Coordinate(this.Vertices[i].X, this.Vertices[i].Y); } LinearRing rng1 = new LinearRing(coords); Polygon pol1 = new Polygon(rng1); // 修正多边形拓扑方向 pol1 = (Polygon)pol1.Orient(); var bufParams = new BufferParameters(); bufParams.JoinStyle = JoinStyle.Round; Geometry b = BufferOp.Buffer(pol1, distance, bufParams); List<Z_Polygon> result = new List<Z_Polygon>(); if (b is MultiPolygon multiPolygon) { for (int i = 0; i < multiPolygon.NumGeometries; i++) { List<Z_Point> newVertices = new List<Z_Point>(); Polygon pol = (Polygon)multiPolygon.GetGeometryN(i); foreach (var item in pol.Coordinates) { newVertices.Add(new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); } } else if (b is Polygon pol) { List<Z_Point> newVertices = new List<Z_Point>(); foreach (var item in pol.Coordinates) { newVertices.Add(new Z_Point(item.X, item.Y)); } result.Add(new Z_Polygon(newVertices)); } return result; }
额外验证建议
- 用
pol1.IsValid检查原始多边形是否自相交,自相交多边形会导致Buffer结果异常。 - 负距离偏移前,可通过
BufferOp.IsValidDistance判断偏移距离是否会导致多边形收缩至消失或自相交。
内容的提问来源于stack exchange,提问作者dotnetexplorer
相关产品推荐
相关产品推荐

