基於谷歌地圖的Dijkstra算法水路路徑規划


  最終效果圖如下:

還是圖、鄰接表,可以模擬出幾個對象=》節點、邊、路徑。三個類分別如下:

Node 節點:

using System;
using System.Collections.Generic;

namespace Road.Plan
{
    public class Node
    {
        private string id;
        private IList<Edge> edgeList;

        public double Lat
        {
            get;
            set;
        }

        public double Lng
        {
            get;
            set;
        }
        
        public Node(string nid)
        {
            id = nid;
            edgeList = new List<Edge>();
        }

        public string Id
        {
            get
            {
                return id;
            }
        }

        public IList<Edge> EdgeList
        {
            get
            {
                return edgeList;
            }
        }
    }
}

  Edge 邊:

using System;
using System.Web.Script.Serialization;

namespace Road.Plan
{
    public class Edge
    {
        [ScriptIgnore]
        public Node StartNode
        {
            get;
            set;
        }
        [ScriptIgnore]
        public Node EndNode
        {
            get;
            set;
        }
        public int Weight
        {
            get;
            set;
        }
    }
}

  Graph 圖:

using System;
using System.Collections.Generic;

namespace Road.Plan
{
    /// <summary>
    /// 由於邊存在節點里了,鄰接表的方式的圖就這么簡單
    /// </summary>
    public class Graph
    {
        public List<Node> NodeList = new List<Node>();
    }
}

  路徑Path:

using System;
using System.Collections.Generic;

namespace Road.Plan
{
    public class Path
    {
        //起始點 到 這個點
        public string CurrentNodeId;
        //該點是否已經計算
        public bool IsProcessed = false;
        //路徑 權重合計
        public int Weight = 99999999;
        //路徑表示
        public List<Node> PathNodeList = new List<Node>();
    }
}

  路徑規划輔助類:

using System;
using System.Collections.Generic;
using System.Linq;

namespace Road.Plan
{
    /// <summary>
    /// 計算最短路徑幫助類
    /// </summary>
    public class CaculateHelper
    {
        private Dictionary<string, Path>  dicPath = new Dictionary<string, Path>();
        public Dictionary<string, Path> DicPath
        {
            get
            {
                return dicPath;
            }
        }

        public void IniFirstNode(Graph graph, string StartNodeId)
        {
            Node OriginNode = null;
            foreach (Node node in graph.NodeList)
            {
                if (node.Id == StartNodeId)
                {
                    OriginNode = node;
                }
                else
                {
                    Path path = new Path();
                    path.CurrentNodeId = node.Id;
                    dicPath.Add(path.CurrentNodeId, path);  //初始化A->到所有邊都是默認的Path 99999999
                }
            }

            //如果有A直接進入的邊,則設置為相應權重值,和記錄下路徑
            foreach (Edge edge in OriginNode.EdgeList)
            {
                Path path = new Path();
                path.CurrentNodeId = edge.EndNode.Id;
                path.Weight = edge.Weight;
                path.PathNodeList.Add(edge.StartNode);
                dicPath[path.CurrentNodeId] = path;
            }
        }

        public Node GetFromNodeMinWeightNode(Graph graph)
        {
            Node CNode = null;
            KeyValuePair<string, Path> KVPPath = dicPath.Where(m => !m.Value.IsProcessed).OrderBy(m => m.Value.Weight).FirstOrDefault();
            if (KVPPath.Key != null)
            {
                CNode = graph.NodeList.FirstOrDefault(m => m.Id == KVPPath.Value.CurrentNodeId);
            }
            return CNode;
        }

        /// <summary>
        /// 計算最短權值路徑
        /// </summary>
        public void CatelateMinWeightRoad(Graph graph, string StartNodeId)
        {
            //取從第一個點出發,最小權值且未被訪問果的節點的點
            Node CNode = GetFromNodeMinWeightNode(graph);
            //這段代碼是核心 循環每個頂點,看看經過該頂點是否會讓權值變小,如果會則存起此路徑。直到再未訪問過的點
            while (CNode != null)
            {
                Path CurrentPath = dicPath[CNode.Id];
                foreach (Edge edge in CNode.EdgeList)
                {
                    if (edge.EndNode.Id == StartNodeId)
                    {
                        continue;
                    }
                    Path TargetPath = dicPath[edge.EndNode.Id];

                    int tempWeight = CurrentPath.Weight + edge.Weight;
                    if (tempWeight < TargetPath.Weight)
                    {
                        TargetPath.Weight = tempWeight;
                        TargetPath.PathNodeList.Clear();

                        for (int i = 0; i < CurrentPath.PathNodeList.Count; i++)
                        {
                            TargetPath.PathNodeList.Add(CurrentPath.PathNodeList[i]);
                        }

                        TargetPath.PathNodeList.Add(CNode);
                    }
                }

                //標志為已處理
                dicPath[CNode.Id].IsProcessed = true;
                //再次獲取權值最小的點
                CNode = GetFromNodeMinWeightNode(graph);
            }
        }
    }
}

  此處需要1個Controller、3個Action、1個頁面。

  第一步,打開地圖、並初始化好“運算-圖”。

  第二步,獲取所有節點,並將節點在地圖上顯示出來。

  第三步,獲取運算結果,並在地圖上根據計算結果將線划出來。

  Controller代碼如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Road.Plan;

namespace Road.Controllers
{
    public class HomeController : Controller
    {
        static Graph graph = new Graph();

        public ActionResult GetAllNodes()
        {
            return Json(graph.NodeList, JsonRequestBehavior.AllowGet);
        }

        public ActionResult Index()
        {
            graph.NodeList.Clear();

            #region 初始化航路-圖

            Node Node1 = new Node("1");
            Node1.Lat = 23.1589850342836;
            Node1.Lng = 112.7859878540039;
            graph.NodeList.Add(Node1);

            Node Node2 = new Node("2");
            Node2.Lat = 23.136255816129122;
            Node2.Lng = 112.79937744140625;
            graph.NodeList.Add(Node2);

            Node Node3 = new Node("3");
            Node3.Lat = 23.11447003284563;
            Node3.Lng = 112.79869079589844;
            graph.NodeList.Add(Node3);

            Node Node4 = new Node("4");
            Node4.Lat = 23.142885569598484;
            Node4.Lng = 112.80890464782715;
            graph.NodeList.Add(Node4);

            Node Node5 = new Node("5");
            Node5.Lat = 23.144621879424374;
            Node5.Lng = 112.81577110290527;
            graph.NodeList.Add(Node5);

            Node Node6 = new Node("6");
            Node6.Lat = 23.151566893799817;
            Node6.Lng = 112.82074928283691;
            graph.NodeList.Add(Node6);

            Node Node7 = new Node("7");
            Node7.Lat = 23.15551276434145;
            Node7.Lng = 112.82984733581543;
            graph.NodeList.Add(Node7);

            Node Node8 = new Node("8");
            Node8.Lat = 23.1545657660099;
            Node8.Lng = 112.84452438354492;
            graph.NodeList.Add(Node8);

            Node Node9 = new Node("9");
            Node9.Lat = 23.167507497056675;
            Node9.Lng = 112.81705856323242;
            graph.NodeList.Add(Node9);

            //***************** 1 Node *******************
            //1 -> 2
            Edge aEdge1 = new Edge();
            aEdge1.StartNode = Node1;
            aEdge1.EndNode = Node2;
            aEdge1.Weight = 1;
            Node1.EdgeList.Add(aEdge1);

            //***************** 2 Node *******************
            //2 -> 3
            Edge bEdge3 = new Edge();
            bEdge3.StartNode = Node2;
            bEdge3.EndNode = Node3;
            bEdge3.Weight = 1;
            Node2.EdgeList.Add(bEdge3);

            //2 -> 1
            Edge bEdge1 = new Edge();
            bEdge1.StartNode = Node2;
            bEdge1.EndNode = Node1;
            bEdge1.Weight = 1;
            Node2.EdgeList.Add(bEdge1);

            //2 -> 4
            Edge bEdge4 = new Edge();
            bEdge4.StartNode = Node2;
            bEdge4.EndNode = Node4;
            bEdge4.Weight = 1;
            Node2.EdgeList.Add(bEdge4);


            //***************** 3 Node *******************
            //3 -> 2
            Edge cEdge2 = new Edge();
            cEdge2.StartNode = Node3;
            cEdge2.EndNode = Node2;
            cEdge2.Weight = 1;
            Node3.EdgeList.Add(cEdge2);

            //***************** 4 Node *******************
            //4 -> 2
            Edge dEdge2 = new Edge();
            dEdge2.StartNode = Node4;
            dEdge2.EndNode = Node2;
            dEdge2.Weight = 1;
            Node4.EdgeList.Add(dEdge2);

            //4 -> 5
            Edge dEdge5 = new Edge();
            dEdge5.StartNode = Node4;
            dEdge5.EndNode = Node5;
            dEdge5.Weight = 1;
            Node4.EdgeList.Add(dEdge5);

            //***************** 5 Node *******************
            //5 -> 6
            Edge eEdge6 = new Edge();
            eEdge6.StartNode = Node5;
            eEdge6.EndNode = Node6;
            eEdge6.Weight = 1;
            Node5.EdgeList.Add(eEdge6);

            //5 -> 4
            Edge eEdge4 = new Edge();
            eEdge4.StartNode = Node5;
            eEdge4.EndNode = Node4;
            eEdge4.Weight = 1;
            Node5.EdgeList.Add(eEdge4);

            //***************** 6 Node *******************
            //6 -> 5
            Edge fEdge5 = new Edge();
            fEdge5.StartNode = Node6;
            fEdge5.EndNode = Node5;
            fEdge5.Weight = 1;
            Node6.EdgeList.Add(fEdge5);

            //6 -> 7
            Edge fEdge7 = new Edge();
            fEdge7.StartNode = Node6;
            fEdge7.EndNode = Node7;
            fEdge7.Weight = 1;
            Node6.EdgeList.Add(fEdge7);

            //***************** 7 Node *******************
            //7 -> 6
            Edge gEdge6 = new Edge();
            gEdge6.StartNode = Node7;
            gEdge6.EndNode = Node6;
            gEdge6.Weight = 1;
            Node7.EdgeList.Add(gEdge6);

            //7 -> 8
            Edge gEdge8 = new Edge();
            gEdge8.StartNode = Node7;
            gEdge8.EndNode = Node8;
            gEdge8.Weight = 1;
            Node7.EdgeList.Add(gEdge8);

            //7 -> 9
            Edge gEdge9 = new Edge();
            gEdge9.StartNode = Node7;
            gEdge9.EndNode = Node9;
            gEdge9.Weight = 1;
            Node7.EdgeList.Add(gEdge9);

            //***************** 8 Node *******************
            //8 -> 7
            Edge hEdge7 = new Edge();
            hEdge7.StartNode = Node8;
            hEdge7.EndNode = Node7;
            hEdge7.Weight = 1;
            Node8.EdgeList.Add(hEdge7);

            //***************** 9 Node *******************
            //9 -> 7
            Edge iEdge7 = new Edge();
            iEdge7.StartNode = Node9;
            iEdge7.EndNode = Node7;
            iEdge7.Weight = 1;
            Node9.EdgeList.Add(iEdge7);

            #endregion

            return View();
        }

        /// <summary>
        /// 計算起始點,結束點的最短路徑
        /// </summary>
        /// <param name="StartNodeId"></param>
        /// <param name="EndNodeId"></param>
        /// <returns></returns>
        public ActionResult GetWaterWay(string StartNodeId, string EndNodeId)
        {
            CaculateHelper CH = new CaculateHelper();
            //第一步,初始化初始化源點 A 到 其他各點的 權重以及 路徑(完成 A->B A->C A->E A->D 邊權重,與A無直接邊的則默認99999999)
            CH.IniFirstNode(graph, StartNodeId);
            //第二步,從權重最小的點開始,一直到權值最大的點
            CH.CatelateMinWeightRoad(graph, StartNodeId);
            
            //組合返回值
            Path ShowPath = CH.DicPath[EndNodeId];
            ShowPath.PathNodeList.Add(graph.NodeList.First(m => m.Id == EndNodeId));    //補上結束點
            return Json(ShowPath.PathNodeList);
        }
    }
}

  頁面HTML代碼如下:

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no">
    <meta charset="utf-8">
    <title>Complex icons</title>
    <style>
        html, body, #map-canvas {
            height: 100%;
            margin: 0px;
            padding: 0px;
        }
    </style>
    <script src="/jquery-1.10.2.min.js"></script>
    <script src="http://ditu.google.cn/maps/api/js?sensor=false" type="text/javascript"></script>

    <script>
        var map;
        var lat = 23.144621879424374;
        var lng = 112.81577110290527;

        var myLatlng = new google.maps.LatLng(lat, lng);


        //添加一個標記
        function addMarker(lat, lng, title) {
            var LatLng = new google.maps.LatLng(lat, lng);
            var marker = new google.maps.Marker({
                map: map,
                position: LatLng,
                title: title
            });
            return marker;
        }

        function LatLng(lat, lng) {
            return {
                lat: lat,
                lng: lng
            };
        }

        //線條選項
        function lineOption() {
            var lineOption = {
                strokeColor: "#FF0000",
                strokeOpacity: 1.0,
                strokeWeight: 2,
                coordinates: []
            };
            return lineOption;
        }

        //畫線
        function addLine(lineOption) {
            var linecoordinates = [];
            for (var i = 0; i < lineOption.coordinates.length; i++) {
                linecoordinates.push(new google.maps.LatLng(lineOption.coordinates[i].lat, lineOption.coordinates[i].lng));
            }

            //顯示線
            var line = new google.maps.Polyline({
                path: linecoordinates,
                strokeColor: lineOption.strokeColor,
                strokeOpacity: lineOption.strokeOpacity,
                strokeWeight: lineOption.strokeWeight,
                map: map
            });
            return line;
        }

        var MarkerId = 1;
        //初始化谷歌地圖
        function initialize() {
            //設置地圖中心
            var mapOptions = {
                zoom: 12,
                center: myLatlng
            }
            map = new google.maps.Map(document.getElementById('map-canvas'), mapOptions);

            //google.maps.event.addListener(map, 'click', function (e) {
            //    var str = $("#position").html();
            //    var MID = MarkerId++;
            //    addMarker(e.latLng.lat(), e.latLng.lng(), MID);
            //    $("#position").html(str + " " + MID + " " + e.latLng.lat() + " " + e.latLng.lng() + "<br/>");
            //});

            $.ajax({
                url: "/Home/GetAllNodes",
                dataType: "json",
                type: "post",
                success: function (data) {
                    for (var i = 0; i < data.length; i++)
                    {
                        addMarker(data[i].Lat, data[i].Lng, data[i].Id);
                    }
                }
            })

            $.ajax({
                url: "/Home/GetWaterWay",
                dataType: "json",
                type: "post",
                data:{
                    StartNodeId: "1",
                    EndNodeId: "9"
                },
                success: function (data) {
                    var lo = lineOption();
                    lo.strokeWeight = 4;
                    lo.strokeColor = "Green";
                    lo.strokeOpacity = 0.8;
                    //用返回的路線畫線
                    for (var i = 0; i < data.length; i++)
                    {
                        lo.coordinates.push(LatLng(data[i].Lat, data[i].Lng));
                    }
                    addLine(lo);
                }
            })
        }

        //監聽頁面事件,當頁面加載完畢,加載谷歌地圖
        google.maps.event.addDomListener(window, 'load', initialize);

    </script>
</head>
<body>
    <div id="map-canvas" style="height:600px;"></div>
    <div id="position"></div>
</body>
</html>


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM