You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.NET Core构建Polygon报错:points must form a closed linestring的解决方法

问题描述

从Overpass Turbo获取几何数据后,在.NET Core中将经纬度转为Coordinate并构建Polygon时,抛出如下异常:

Unhandled exception. System.ArgumentException: points must form a closed linestring

at NetTopologySuite.Geometries.LinearRing.ValidateConstruction()
at NetTopologySuite.Geometries.LinearRing..ctor(CoordinateSequence points, GeometryFactory factory)
at NetTopologySuite.Geometries.GeometryFactory.CreateLinearRing(CoordinateSequence coordinates)
at NetTopologySuite.Geometries.GeometryFactory.CreateLinearRing(Coordinate[] coordinates)
at NetTopologySuite.Geometries.GeometryFactory.CreatePolygon(Coordinate[] coordinates)

原实现代码:

var coordinates = new List<Coordinate>();

foreach (var geoElement in elements)
{
    if (geoElement.type == "way")
    {
        foreach (var g in geoElement.geometry)
        {
            Coordinate coordinate = new Coordinate(g.lon, g.lat);
            coordinates.Add(coordinate);
        }
    }
    else
    {
        foreach (var m in geoElement.members)
        {
            if (m.type == "way")
            {
                foreach (var g in m.geometry)
                {
                    Coordinate coordinate = new Coordinate(g.lon, g.lat);
                    coordinates.Add(coordinate);
                }
            }
        }
    }
}

var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
var polygon = geometryFactory.CreatePolygon(coordinates.ToArray());

return polygon;
解决方案

NetTopologySuite要求Polygon的坐标序列必须是闭合线性环——即首尾坐标完全相同,同时坐标数量需满足构建多边形的最低要求(至少3个不重复点,闭合后为4个点)。以下是具体修复步骤:

1. 强制闭合坐标序列

在创建Polygon前,检查坐标列表首尾是否一致,若不一致则手动添加首坐标到列表末尾:

// 检查并闭合坐标序列,同时确保点数足够构建多边形
if (coordinates.Count >= 3)
{
    if (!coordinates.First().Equals(coordinates.Last()))
    {
        coordinates.Add(coordinates.First());
    }
}

2. 优化Overpass数据处理逻辑

Overpass返回的relation需是多边形类型(如multipolygon或boundary),否则拼接的way可能无法形成闭合环。同时需避免混入开放道路类的非闭合way:

var coordinates = new List<Coordinate>();

foreach (var geoElement in elements)
{
    if (geoElement.type == "way")
    {
        foreach (var g in geoElement.geometry)
        {
            coordinates.Add(new Coordinate(g.lon, g.lat));
        }
    }
    // 明确处理多边形类型的relation
    else if (geoElement.type == "relation" && 
             (geoElement.tags?["type"] == "multipolygon" || geoElement.tags?["type"] == "boundary"))
    {
        foreach (var m in geoElement.members)
        {
            if (m.type == "way")
            {
                foreach (var g in m.geometry)
                {
                    coordinates.Add(new Coordinate(g.lon, g.lat));
                }
            }
        }
    }
}

完整修复后的代码

var coordinates = new List<Coordinate>();

foreach (var geoElement in elements)
{
    if (geoElement.type == "way")
    {
        foreach (var g in geoElement.geometry)
        {
            coordinates.Add(new Coordinate(g.lon, g.lat));
        }
    }
    else if (geoElement.type == "relation" && 
             (geoElement.tags?["type"] == "multipolygon" || geoElement.tags?["type"] == "boundary"))
    {
        foreach (var m in geoElement.members)
        {
            if (m.type == "way")
            {
                foreach (var g in m.geometry)
                {
                    coordinates.Add(new Coordinate(g.lon, g.lat));
                }
            }
        }
    }
}

// 关键:闭合坐标序列并校验点数
if (coordinates.Count >= 3)
{
    if (!coordinates.First().Equals(coordinates.Last()))
    {
        coordinates.Add(coordinates.First());
    }
}

var geometryFactory = new GeometryFactory(new PrecisionModel(), 4326);
var polygon = geometryFactory.CreatePolygon(coordinates.ToArray());

return polygon;

额外注意事项

  • 若处理带内环(洞)的复杂多边形,不能直接合并所有坐标,需使用CreatePolygon(LinearRing shell, LinearRing[] holes)方法分别构建外环和内环。
  • 若仍报错,需检查原始Overpass数据是否包含开放的way,这类数据无法直接转为Polygon,需过滤或补充数据。

内容的提问来源于stack exchange,提问作者Cyrus the Great

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 22:12:28