VB.NET - 来自 KML 文件的多边形中的点

VB.NET - Point in Polygon From KML file

我从 KML 文件中提取了大量 Polygons。多边形代表地球表面上的“块”。 我可以读取多边形的坐标并存储它们的值,以及关于多边形的其他一些信息。

我的问题是,我现在有一组点(带有它们的坐标,我们再次谈论地球表面上的点),我需要检查它们属于哪个多边形。

我知道PiP不是一个小问题也不是新问题,所以我不想重新发明轮子! 有什么 VB.NET 库可以帮助我快速解决这个问题吗? 谢谢

编辑

我的多边形是 n 元组的形状,例如 5 元组(其中一些有更多,所有多边形的第一个点和最后一个点都相等):

[( -59.00002600000005,-52.00002600000001,0 ),
 ( -59.00002600000005,-51.50002600000001,0 ), 
 ( -59.50002600000005,-51.50002600000001,0 ),
 ( -59.50002600000005,-52.00002600000001,0 ),
 ( -59.00002600000005,-52.00002600000001,0 ) ]

目前我正在以这种方式阅读 KML 文件:

'foreach KML Placemark
For Each p As System.XML.Linq.XElement In xdata.Descendants(ns +"Placemark")
    ID =  p.Element(ns+"name").Value        
    'coordinates, every substring has triple x,y,z but i only care about x,y
    temp = p.Descendants(ns+"coordinates").Value
    str = temp.split(" ")
    
    'number of polygon vertexes
    lunghezza(ID) = str.length()-1
    'polygon vertexes
    Dim polygonPoints(str.length()-1) As System.Drawing.PointF
    'first substring is empty
    for s = 1 to str.length()-1
        'i get x,y
        x = String2Array(str(s),",",false)(1)
        y = String2Array(str(s),",",false)(2)
        'cast to double
        flt_x = double.Parse(x)
        flt_y = double.Parse(y)
        'point is made
        polygonPoints(s-1) = new System.Drawing.PointF(flt_x, flt_y)
    next
    'points are associated to the polygon ID
    punti(ID) = polygonPoints
Next

此时我尝试查看一个点是否在我存储的这些多边形之一内: 为此,我使用了我发现的算法 here

dim ok as boolean = false
dim xinters as double
' flt_y  and flt_x contain my test latitude and longitude
'foreach polygon stored
for each id in IDS
    if not empty(id)
        'get number of points defining the polygon
        Dim polygonPoints2(lunghezza(id)) As System.Drawing.PointF
        'i get the polygon vertexes
        polygonPoints2 = punti(id)
        dim p1, p2 as System.Drawing.PointF
        'first point
        p1 = polygonPoints2(0)
        'counter
        dim c as integer = 0
    
        for i as integer = 1 to lunghezza(id)
            p2 = polygonPoints2(i Mod lunghezza(id))
            if ( flt_x > Math.min(p1.x, p2.x) and flt_x <= Math.max(p1.x, p2.x) and flt_y <= Math.max(p1.y, p2.y) and p1.x <> p2.x) then
                xinters = (flt_x - p1.x) * (p2.y - p1.y) / (p2.x - p1.x) + p1.y
                if (p1.y = p2.y or flt_y <= xinters) 
                    c = c + 1
                end if
            end if
            p1 = p2
        next 
        
        if (c mod 2) <> 0
            'found one!
            ok = true
            exit for
        end if
    end if
next

但我一直找不到我的点属于哪个多边形! 我做错了什么?

测试我使用的坐标:x: 44,3034627 y: 7,800283

我确定这些适合这个多边形:

 <Polygon>
    <extrude>0</extrude>
    <altitudeMode>clampToGround</altitudeMode>
    <outerBoundaryIs>
    <LinearRing>
    <coordinates> 
        10.99997399999995,45.999974,0
         10.99997399999995,46.499974,0
         10.49997399999995,46.499974,0
         9.999973999999952,46.499974,0
         9.499973999999952,46.499974,0
         8.999973999999952,46.499974,0
         8.499973999999952,46.499974,0
         7.999973999999952,46.499974,0
         7.999973999999952,45.999974,0
         7.499973999999952,45.999974,0
         6.999973999999952,45.999974,0
         6.999973999999952,45.499974,0
         6.999973999999952,44.999974,0
         6.999973999999952,44.499974,0 
         6.999973999999952,43.999974,0
         7.499973999999952,43.999974,0 
         7.999973999999952,43.999974,0 
         7.999973999999952,44.499974,0 
         8.499973999999952,44.499974,0
         8.999973999999952,44.499974,0
         9.499973999999952,44.499974,0
         9.999973999999952,44.499974,0
         10.49997399999995,44.499974,0
         10.49997399999995,43.999974,0
         10.99997399999995,43.999974,0
         11.49997399999995,43.999974,0
         11.99997399999995,43.999974,0 
         11.99997399999995,44.499974,0
         12.49997399999995,44.499974,0 
         12.49997399999995,44.999974,0 
         11.99997399999995,44.999974,0 
         11.49997399999995,44.999974,0
         11.49997399999995,45.499974,0 
         10.99997399999995,45.499974,0 
         10.99997399999995,45.999974,0
     </coordinates>
     </LinearRing>
     </outerBoundaryIs>
 </Polygon>

我开始怀疑问题出在 PiP 算法中,更具体地说是关于 Doubles 之间的 <>= 比较,因此重新标记

最后,我的所有工作都是正确的,我只是以错误的顺序读取坐标,没有正确处理输入字符串。以下是读取 KML 的更正代码:

'foreach KML Placemark
For Each p As System.XML.Linq.XElement In xdata.Descendants(ns +"Placemark")
    ID =  p.Element(ns+"name").Value        
    'coordinates, every substring has triple x,y,z but i only care about x,y
    temp = p.Descendants(ns+"coordinates").Value
    str = temp.split(" ")
    
    'number of polygon vertexes
    lunghezza(ID) = str.length()-1
    'polygon vertexes
    Dim polygonPoints(str.length()-1) As System.Drawing.PointF
    'first substring is empty
    for s = 1 to str.length()-1
        'i get x,y
        y = String2Array(str(s),",",false)(1)
        x = String2Array(str(s),",",false)(2)
        'cast to double
        flt_x = double.Parse(x.replace(".", ","))
        flt_y = double.Parse(y.replace(".", ","))
        'point is made
        polygonPoints(s-1) = new System.Drawing.PointF(flt_x, flt_y)
    next
    'points are associated to the polygon ID
    punti(ID) = polygonPoints
Next