📄 shortpath.bas
字号:
Attribute VB_Name = "Module5"
Option Explicit
'绘最短路径图
Public Sub ShortPathPlot(TheOutPath As String, TableNameT As String, nNode As Integer, LonNode() As Double, LatNode() As Double, NoNode() As Integer, nNodeShortPath As Integer, NodeShortPath() As Integer)
Dim Columns() As String, ColumnsType() As String, ColumnsN As Integer
Dim I As Integer, J As Integer
Dim LineTemp As String
Dim Lon1 As Double, Lon2 As Double, Lat1 As Double, Lat2 As Double
Dim Node1 As Integer, Node2 As Integer
Dim V(1 To 2) As String
Screen.MousePointer = 11
ColumnsN = 2
ReDim Columns(1 To ColumnsN), ColumnsType(1 To ColumnsN)
Columns(1) = "节点1编码"
ColumnsType(1) = "SmallInt"
Columns(2) = "节点2编码"
ColumnsType(2) = "SmallInt"
TableName = TableNameT
Call MIFMID_Open(TheOutPath + TableName, Columns, ColumnsType, ColumnsN)
Call MIFMID_MakePen(2, 2, QBColors(12))
Node1 = NodeShortPath(1)
Lon1 = LonNode(Node1)
Lat1 = LatNode(Node1)
For I = 2 To nNodeShortPath
Node2 = NodeShortPath(I)
Lon2 = LonNode(Node2)
Lat2 = LatNode(Node2)
V(1) = NoNode(Node1)
V(2) = NoNode(Node2)
Call MIFMID_CreateLine(Lon1, Lat1, Lon2, Lat2)
Call OutMID(V)
Lon1 = Lon2
Lat1 = Lat2
Next I
'新表存盘
Call MIFMID_Close
TheInFile = TheOutPath + TableName + ".MIF"
TheOutFile = TheOutPath + TableName + ".TAB"
MapInfo.Do "Import """ & TheInFile & """ Type ""MIF"" Into """ & TheOutFile & """ Overwrite"
TheInFile = TheOutPath + TableName + ".MIF"
Kill TheInFile
TheInFile = TheOutPath + TableName + ".MID"
Kill TheInFile
mapWinID = CLng(MapInfo.Eval("FrontWindow()"))
If (mapWinID > 0) Then
MapInfo.Do "Add Map Layer " & TableName
End If
Screen.MousePointer = 0
End Sub
'读节点数据
Public Sub ShortPathData(TheInFileNode As String, TheInFileLine As String, LonNode() As Double, LatNode() As Double, NoNode() As Integer, nNode As Integer, LineNode() As Integer, LineDis() As Double, nLineNode As Integer, LinkN() As Integer, LinkNi() As Integer, LinkDis() As Double, LinkNo() As Integer)
Dim I As Integer, J As Integer, N As Integer, NN As Integer
Dim LineTemp As String
Dim Lon1 As Double, Lon2 As Double, Lat1 As Double, Lat2 As Double
Dim Node1 As Integer, Node2 As Integer
Dim NodeNo1 As Integer, NodeNo2 As Integer
Dim LineNodeNo1() As Integer, LineNodeNo2() As Integer
'Begin读节点数据
nNode = 0
Open TheInFileNode For Input As #1
Do While Not EOF(1)
Line Input #1, LineTemp
nNode = nNode + 1
Loop
Close (1)
ReDim LonNode(1 To nNode), LatNode(1 To nNode), NoNode(1 To nNode)
Open TheInFileNode For Input As #1
For I = 1 To nNode
Input #1, LatNode(I), LonNode(I), LineTemp
NoNode(I) = Val(LineTemp)
Next I
Close (1)
'End读节点数据
'Begin读Line数据
nLineNode = 0
Open TheInFileLine For Input As #1
Do While Not EOF(1)
Line Input #1, LineTemp
nLineNode = nLineNode + 1
Loop
Close (1)
ReDim LineNode(1 To 2, 1 To nLineNode), LineDis(1 To nLineNode)
ReDim LineNodeNo(1 To 2, 1 To nLineNode)
Open TheInFileLine For Input As #1
For I = 1 To nLineNode
Input #1, LineNode(1, I), LineNode(2, I), LineDis(I)
Next I
Close (1)
'End读Line数据
'Begin计算距离
For I = 1 To nLineNode
'Begin搜索Line对应节点
Node1 = LineNode(1, I)
Node2 = LineNode(2, I)
NodeNo1 = 0
NodeNo2 = 0
For J = 1 To nNode
If (NoNode(J) = Node1) Then
NodeNo1 = J
End If
If (NoNode(J) = Node2) Then
NodeNo2 = J
End If
If (NodeNo1 > 0 And NodeNo2 > 0) Then Exit For
Next J
'End搜索Line对应节点
If (NodeNo1 = 0 Or NodeNo2 = 0) Then
MsgBox "节点" + Format(NodeNo1, "####0 ") + Format(NodeNo2, "####0") + "不存在", vbOKOnly, "关于节点"
End If
LineNodeNo(1, I) = NodeNo1
LineNodeNo(2, I) = NodeNo2
'Begin开始计算距离
Lon1 = LonNode(NodeNo1)
Lat1 = LatNode(NodeNo1)
Lon2 = LonNode(NodeNo2)
Lat2 = LatNode(NodeNo2)
If (LineDis(I) <= 0) Then
LineDis(I) = 111.199 * Sqr((Lat1 - Lat2) ^ 2 + ((Lon1 - Lon2) * Cos((Lat1 + Lat2) * 0.00872665)) ^ 2)
End If
'End开始计算距离
Next I
'End计算距离
ReDim LinkN(1 To nNode), LinkNi(1 To nNode + 1), LinkDis(1 To nLineNode * 3), LinkNo(1 To nLineNode * 3)
'Begin开始搜索与节点相连的Line
LinkNi(1) = 1
NN = 0
For I = 1 To nNode
N = 0
For J = 1 To nLineNode
If (LineNode(1, J) = NoNode(I)) Then
N = N + 1
NN = NN + 1
LinkDis(NN) = LineDis(J)
LinkNo(NN) = LineNodeNo(2, J)
ElseIf (LineNode(2, J) = NoNode(I)) Then
N = N + 1
NN = NN + 1
LinkDis(NN) = LineDis(J)
LinkNo(NN) = LineNodeNo(1, J)
End If
Next J
LinkN(I) = N
LinkNi(I + 1) = LinkNi(I) + N
If (N = 0) Then
MsgBox "节点" + Format(NoNode(I), "###0") + "无线路!", vbOKOnly, "关于搜索与节点相连的线路"
End If
Next I
'End开始搜索与节点相连的Line
End Sub
'NoNode1 起始点编码
'NoNode2 结束点编码
'nNode 为网中最大的节点数
'NoNode(i) 节点编码
'LinkN(i) 与i点相连Line个数
'LinkNi(i) 与i点相连Line端点存放序号
'iLL=LinkNi(LL) - i + 1
'LinkNo(iLL) 与i点相连Line端点顺序编号
'LinkList(iLL) 与i点相连Line端点距离
'nNodeShortPath 最短路径节点数
'NodeShortPath 最短路径节点序号
Public Sub ShortPathSearch(NoNode1 As Integer, NoNode2 As Integer, nNode As Integer, NoNode() As Integer, LinkN() As Integer, LinkNi() As Integer, LinkNo() As Integer, LinkDis() As Double, nNodeShortPath As Integer, NodeShortPath() As Integer, ShortPath As Double)
Dim II As Integer, I As Integer, J As Integer, LL As Integer, iLL As Integer
Dim iNode As Integer
Dim S As Single, MinS As Single, MinPoint As Integer
Dim NodeCheck() As Boolean '标记已经查过的点
Dim NodeUse() As Boolean '标记已经作为结果点使用过的点
Dim RS() As Single '假设从起点到任一点的距离都为无穷大
Dim result() As Single '存放结果长度
Dim ResultNo() As Integer '存放结果节点编号
Dim iResult As Integer
Dim No() As Integer
Dim StartNo As Integer, EndNo As Integer
'Begin根据编码,搜索序号
StartNo = 0
EndNo = 0
For I = 1 To nNode
If (NoNode(I) = NoNode1) Then
StartNo = I
End If
If (NoNode(I) = NoNode2) Then
EndNo = I
End If
If (StartNo > 0 And EndNo > 0) Then Exit For
Next I
'End根据编码,搜索序号
ReDim NodeCheck(1 To nNode), NodeUse(1 To nNode)
ReDim RS(1 To nNode), result(1 To nNode), ResultNo(1 To nNode)
For I = 1 To nNode
NodeCheck(I) = False '标记未经查过的点。
NodeUse(I) = False '标记未作为结果点使用过的点
RS(I) = 1E+38 '假设从起点到任一点的距离都为无穷大
Next I
LL = StartNo '设置开始点。
NodeUse(LL) = True '标记开始点为真。即已经作为结果点使用过。
J = 0
For iNode = 1 To nNode
'先从与开始点相连的起点寻找
For I = 1 To LinkN(LL) '以与LL点相连的起点的个数循环
iLL = LinkNi(LL) + I - 1
iResult = LinkNo(iLL) '找出与LL点相连的起点的点号
If NodeCheck(iResult) = False Then '如果没查过,则进行
S = LinkDis(iLL) + result(LL) '找出长度并求和
If NodeUse(iResult) = True Then '如果已经作为结果点,判断哪一个长
If S <= RS(iResult) Then '如果这一点到起点的长度比现在的路线长,替代
RS(iResult) = S
result(iResult) = S '设置到这点的最短路径长度
ResultNo(iResult) = LL
End If
Else '如果上面的条件都不符合,则进行下面的语句
NodeCheck(iResult) = True
RS(iResult) = S
result(iResult) = S
ResultNo(iResult) = LL
J = J + 1 '每找到一个点加一,为了下面的判断
ReDim Preserve No(1 To J) '重新定义数组并使其值为当前的点号
No(J) = iResult
End If
End If
Next I
'设置最小为无穷大,最短路径点为空
MinS = 1E+38
MinPoint = 0
'找出已经查过点中长度最短的点
For I = iNode To J
If RS(No(I)) < MinS Then
II = I
MinS = RS(No(I))
MinPoint = No(I)
End If
Next I
'如果没有结果,即起点与终点没有通路,则退出程序
If MinS = 1E+38 Then
MsgBox "即起点与终点没有通路!", vbOKOnly, "关于搜索最短路径"
Exit Sub
End If
'将两点互换,减少循环。
No(II) = No(iNode)
No(iNode) = MinPoint
'标记已经作为结果点判断过
NodeUse(MinPoint) = True
LL = MinPoint
'判断结果点是否等于终点,如果等于则已经找到最短路径
If MinPoint = EndNo Then Exit For
Next iNode
'Begin检索最短路径节点
ReDim NodeShortPath(1 To nNode)
nNodeShortPath = 1
LL = MinPoint
NodeShortPath(nNodeShortPath) = LL
Do
LL = ResultNo(LL)
nNodeShortPath = nNodeShortPath + 1
NodeShortPath(nNodeShortPath) = LL
If (LL = StartNo) Then Exit Do
Loop
'End检索最短路径节点
ShortPath = result(EndNo)
End Sub
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -