分享

网优之经纬度的那些事(1)

 vbavsto 2018-10-10

1 背景

这段时间被督导搞毛了,天天找我要一个两个站的TAC,我说你能不能把本期要建设的都给我一起来规划,他说不能。。。我也不想总被这么吵啊,毕竟我很忙的,那就写个工具吧,so easy!

2 成品

导入polygon文件,输入经纬度,执行获取点所在的polygon。

3 实现过程

3.1 获取polygon

最原始的方法,自己动手挨个画,当然我肯定不会去做这么low的事,我肯定先百度,果不其然

https://wenku.baidu.com/view/7721aca00066f5335b81218d.html

很简单的方法,但这样出来的边界区并不精确,正常的TAC区应该依街区、河流、山体等自然因素而定,没关系,我们在这个基础上再修改就是了。

随后点表-导出-mif,一份完整的polygon文件就出炉了,mif文件记录位置信息,mid文件记录字段信息,结构如下:

 3.2 算法原理

1、理论支持:如果从需要判断的点出发的一条射线与该多边形的焦点个数为奇数,则该点在此多边形内,否则该点在此多边形外。
2、编程思路:
该程序的思路是从A点出发向左做一条水平射线(平行于x轴,向X轴的反方向),判断与各边是否有焦点。
dLon1, dLon2, dLat1, dLat2分别表示边的起点和终点的经度和纬度(x轴和y轴)。
先判断A点是否在边的两端点d1和d2的水平平行线之间,不在则不可能有交点,继续判断下一条边。
在之间则说明可能与A点向左的射线有交点,接下来利用几何方法得到A点的水平直线与该边交点的x坐标。
然后判断交点的x坐标在A点的左侧还是右侧,左侧则总交点数加一,右侧则不在A点左射线上,继续判断下一条边。

继续搬运工

https://blog.csdn.net/bluehawksky/article/details/51669994

大神是用Python写的,对我们网优er来说,vba显然使用更便捷,改改就好了,编程语言无所谓,反正我全靠CTRL+CV。

4 我的代码

  1. Sub mif()
  2. With Application.FileDialog(msoFileDialogFilePicker)
  3. .AllowMultiSelect = False
  4. .Filters.Clear
  5. .InitialFileName = ThisWorkbook.Path
  6. .Filters.Add "Mif Files", "*.mif"
  7. .Filters.Add "All Files", "*.*"
  8. If .Show = -1 Then
  9. Path = .SelectedItems(1)
  10. Sheets("Polygon").Range("F1") = Path
  11. Else
  12. Exit Sub
  13. End If
  14. End With
  15. End Sub
  16. Function chkRow(s) As Boolean
  17. Dim c As Range, reg
  18. Set reg = CreateObject("vbscript.regexp")
  19. reg.Pattern = "^(\d+(\.\d+)?)[ ](\d+(\.\d+)?)"
  20. chkRow = reg.Test(s)
  21. End Function
  22. Sub main()
  23. With Sheets("Polygon")
  24. If .Range("F1") = "" Then Exit Sub
  25. Path = .Range("F1")
  26. m = 0
  27. n = 0
  28. i = -1
  29. Dim midArr() As String
  30. Dim textArr() As String
  31. Dim lonArr() As String
  32. Dim latArr() As String
  33. Open Replace(Path, ".MIF", ".MID") For Input As #1
  34. Do Until EOF(1)
  35. Line Input #1, textLine
  36. ReDim Preserve midArr(m + 1)
  37. midArr(m) = Replace(Split(textLine, ",")(0), """", "")
  38. m = m + 1
  39. Loop
  40. Close #1
  41. Open Path For Input As #1
  42. Do Until EOF(1)
  43. Line Input #1, textLine
  44. If textLine = "Region 1" Then
  45. i = i + 1
  46. End If
  47. If chkRow(textLine) = True Then
  48. ReDim Preserve textArr(n + 1)
  49. ReDim Preserve lonArr(n + 1)
  50. ReDim Preserve latArr(n + 1)
  51. textArr(n) = midArr(i)
  52. lonArr(n) = Split(textLine, " ")(0)
  53. latArr(n) = Split(textLine, " ")(1)
  54. n = n + 1
  55. End If
  56. Loop
  57. Close #1
  58. For j = 3 To .Range("B1000000").End(xlUp).Row '遍历点
  59. aLon = .Cells(j, 2) * 1
  60. aLat = .Cells(j, 3) * 1
  61. iSum = 0
  62. For k = 0 To n - 1 '遍历polygon顶点
  63. If textArr(k) = textArr(k + 1) Then
  64. pLon1 = Val(lonArr(k))
  65. pLat1 = Val(latArr(k))
  66. pLon2 = Val(lonArr(k + 1))
  67. pLat2 = Val(latArr(k + 1))
  68. If ((aLat >= pLat1) And (aLat < pLat2)) Or ((aLat >= pLat2) And (aLat < pLat1)) Then
  69. If (Abs(pLat1 - pLat2) > 0) Then
  70. pLon = pLon1 - ((pLon1 - pLon2) * (pLat1 - aLat)) / (pLat1 - pLat2)
  71. If (pLon < aLon) Then
  72. iSum = iSum + 1
  73. End If
  74. End If
  75. End If
  76. ElseIf textArr(k) <> textArr(k + 1) Or k - n = 2 Then
  77. If iSum Mod 2 <> 0 Then
  78. .Cells(j, 4) = textArr(k)
  79. Exit For
  80. Else
  81. .Cells(j, 4) = "N/A"
  82. End If
  83. End If
  84. Next
  85. Next
  86. End With
  87. MsgBox "完成!"
  88. End Sub

5 小结

作为网优,几乎每天都在和经纬度打交道,mapinfo、arcgis、googleearth、高德、百度等等等等,提高生产效率,从熟练工具开始,我将分N篇文章,将我的经验,我遇到的坑,一一记录下来。

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多