前言
如果我们遇到路径问题,可以使用点点连线,给定一个点,可以到达另外几个点,寻找最优解
例:如下图所示,如果要从A1-C1,可以有三条路
1.A1-B1-C1
2.A1-B2-C1
3.A1-B3-C1
最优解肯定是A1-B1-C1,因为两点之间直线最短,但当业务复杂时,我们就要通过轮询来查出最优路径
数据库设计
首先是数据库的设计:创建表:sys_pilot
CREATE TABLE sys_pilot (
pilotid numeric(1000) NOT NULL, -- 内场点位Id
ptname varchar(50) NOT NULL, -- 点位名称
xaxis int4 NOT NULL, -- X轴
yaxis int4 NULL, -- Y轴
transfer varchar(500) NULL, -- 经过点
CONSTRAINT sys_pilot_pk PRIMARY KEY (pilotid)
);
COMMENT ON TABLE public.sys_pilot IS '点位图表';
后端代码
根据传入的两点名称,例:A1,C1
最优解:A1-B1-C1就会被依次返回
private static Dictionary<string, Sys_Pilot> _points;
/// <summary>
/// 查找图形点位
/// </summary>
/// <param name="json"></param>
/// <returns></returns>
/// <exception cref="InterfaceException"></exception>
public List<Sys_Pilot> VerifyPilot(string json)
{
Sys_Pilot pilot = JsonHelper.Instance.Deserialize<Sys_Pilot>(json);
if (pilot == null)
{
throw new InterfaceException("请求参数错误");
}
string[] values = pilot.PtName.Split(',');
if (values.Length != 2)
{
throw new InterfaceException("请传入两个点");
}
string inPoint = values[0];
string terminus = values[1];
Sys_PilotDtl pilotDtl = _paramsDal.FirstOrDefault(new Sys_PilotDtl { BeginName = inPoint, EndName = terminus });
if (!pilotDtl.IsEmpty())
{
List<Sys_Pilot> pilots1 = new List<Sys_Pilot>();
string[] Val = pilotDtl.Transfer.Split(',');
for (int i = 0; i < Val.Length; i++)
{
Sys_Pilot pilot2 = _paramsDal.FirstOrDefault(new Sys_Pilot { PtName = Val[i] });
pilots1.Add(pilot2);
}
return pilots1;
}
List<Sys_Pilot> pilots = _paramsDal.FindData(new Sys_Pilot());
List<Sys_Pilot> shortestPath = ShortestPath(pilots, inPoint, terminus);
return shortestPath;
}
/// <summary>
/// 轮询查出中间点
/// </summary>
/// <param name="pilots"></param>
/// <param name="start"></param>
/// <param name="end"></param>
/// <returns></returns>
public List<Sys_Pilot> ShortestPath(List<Sys_Pilot> pilots, string start, string end)
{
Dictionary<string, Sys_Pilot> _points = pilots.ToDictionary(p => p.PtName);
if (!_points.ContainsKey(start))
throw new InterfaceException("起点不存在!");
if (!_points.ContainsKey(end))
throw new InterfaceException("终点不存在!");
ShortestPath sp = new ShortestPath();
foreach (Sys_Pilot item in pilots)
{
if (item.Transfer.IsEmpty())
{
continue;
}
foreach (string str in item.Transfer.Split(','))
{
sp.AddEdge(item.PtName, str);
}
}
List<string> shortestPath = sp.FindShortestPath(start, end);
List<Sys_Pilot> pilotsList = new List<Sys_Pilot>();
foreach (string str in shortestPath)
{
pilotsList.Add(pilots.Find(p => p.PtName == str));
}
// 保存查出的最短路径
string transfer = string.Join(",", pilotsList.Select(p => p.PtName));
Sys_PilotDtl pilotDtl = new Sys_PilotDtl
{
PilotDtlId = YitIdHelper.NextId(),
BeginName = start,
EndName = end,
Transfer = transfer,
Creator = _tokenBLL.GetUserName(),
CreateTime = _paramsDal.GetDBDateTime(),
Modifier = _tokenBLL.GetUserName(),
ModifierTime = _paramsDal.GetDBDateTime()
};
_paramsDal.InsertData(pilotDtl);
return pilotsList;
}
ShortestPath类
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GUIDE.IOMS.PlatForm.Common.Utilities
{
public class ShortestPath
{
private Dictionary<string, List<string>> graph;
public ShortestPath()
{
graph = new Dictionary<string, List<string>>();
}
public void AddEdge(string source, string destination)
{
if (!graph.ContainsKey(source))
{
graph[source] = new List<string>();
}
graph[source].Add(destination);
}
public List<string> FindShortestPath(string start, string end)
{
Queue<string> queue = new Queue<string>();
Dictionary<string, int> distance = new Dictionary<string, int>();
Dictionary<string, string> predecessor = new Dictionary<string, string>();
List<string> shortestPath = new List<string>();
distance[start] = 0;
predecessor[start] = " ";
queue.Enqueue(start);
while (queue.Count > 0)
{
string current = queue.Dequeue();
if (current == end)
{
string temp = end;
while (temp != " ")
{
shortestPath.Insert(0, temp);
temp = predecessor[temp];
}
break;
}
if (graph.ContainsKey(current))
{
foreach (string neighbor in graph[current])
{
if (!distance.ContainsKey(neighbor))
{
distance[neighbor] = distance[current] + 1;
predecessor[neighbor] = current;
queue.Enqueue(neighbor);
}
}
}
}
return shortestPath;
}
}
}
后记
前端代码是通过Uni-app实现的,有兴趣可以看下Uni-app开发Canvas当子组件示例,点点绘制图形