我从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
在这一点上,我试着看看一个点是否在我存储的这些多边形中的一个:为此,我使用了我在这里找到的算法
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