VB.NET KML提取多边形PiP(点在多边形内)匹配异常问题求助
问题原因与修复方案
现有代码的核心错误
- KML坐标读取逻辑完全错误
KML的coordinates节点内每个坐标三元组格式为经度,纬度,海拔,按逗号分割后索引0对应经度、1对应纬度,你现有代码取索引1、2作为x/y,既搞反了经纬度的存储对应关系,还误读了不需要的海拔字段,坐标存储完全错误自然无法匹配到正确的多边形。 - 精度损失严重
你用System.Drawing.PointF存储坐标,其X/Y属性为单精度浮点数,将解析得到的双精度经纬度转成单精度会产生最大几十米的误差,完全不符合GIS计算的精度要求。 - 浮点数比较逻辑错误
直接用=、<>判断浮点数相等,受精度误差影响几乎不可能得到正确结果,需要加入合理容差(如1e-8度,对应分米级误差)。 - 射线法逻辑瑕疵
你的多边形本身已经是首尾闭合的,不需要额外用i Mod lunghezza(id)处理索引,边界判断逻辑也没有覆盖点刚好落在多边形边上的场景。
修复建议
如果要继续使用手写算法,首先修正坐标读取逻辑:
' 正确读取KML坐标,0为经度,1为纬度 x = Double.Parse(String2Array(str(s),",",False)(0)) ' 经度 y = Double.Parse(String2Array(str(s),",",False)(1)) ' 纬度 ' 不要用PointF,用自定义结构体存储Double类型的经纬度
其次将所有浮点数比较改为带容差的判断,例如:
' 替换p1.x <> p2.x If Math.Abs(p1.x - p2.x) > 1e-8 Then ' 替换p1.y = p2.y If Math.Abs(p1.y - p2.y) < 1e-8 Then
推荐现成库方案
不需要自己手写PiP算法,直接用.NET生态最成熟的GIS计算库NetTopologySuite(NTS),原生支持VB.NET,直接通过Nuget安装NetTopologySuite包即可,内置点在多边形判断、空间索引等成熟功能,性能远高于手写实现,还自动处理球面坐标的边界问题。
使用示例:
' 安装Nuget包后导入命名空间 Imports NetTopologySuite.Geometries Imports NetTopologySuite.Index.Strtree ' 存储多边形时构建Geometry对象 Dim factory As New GeometryFactory() Dim coordinates As New List(Of Coordinate)() ' 读取KML坐标存入coordinates列表 Dim polygon As Polygon = factory.CreatePolygon(coordinates.ToArray()) ' 点在多边形判断 Dim testPoint As Point = factory.CreatePoint(New Coordinate(经度, 纬度)) Dim isInside As Boolean = polygon.Contains(testPoint)
如果需要批量判断大量点归属,还可以用NTS的STRtree空间索引加速查询,不需要遍历所有多边形。
内容的提问来源于stack exchange,提问作者Carlo Prato
相关产品推荐
相关产品推荐

