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
我从 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