| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416 | using System.Collections.Generic;using UnityEngine;namespace XCharts.Runtime{    /// <summary>    /// the data struct of graph.    /// ||数据结构-图。    /// </summary>    public class Graph    {        public bool directed;        public List<GraphNode> nodes = new List<GraphNode>();        public List<GraphEdge> edges = new List<GraphEdge>();        public Dictionary<string, GraphNode> nodeMap = new Dictionary<string, GraphNode>();        public Dictionary<string, GraphEdge> edgeMap = new Dictionary<string, GraphEdge>();        public Graph(bool directed)        {            this.directed = directed;        }        public void Clear()        {            nodes.Clear();            edges.Clear();            nodeMap.Clear();            edgeMap.Clear();        }        public void Refresh()        {            foreach (var node in nodes)            {                node.depth = GetNodeDepth(node);            }        }        public static double GetNodesTotalValue(List<GraphNode> nodes)        {            double totalValue = 0;            foreach (var node in nodes)            {                totalValue += node.totalValues;            }            return totalValue;        }        public List<List<GraphNode>> GetDepthNodes()        {            List<List<GraphNode>> depthNodes = new List<List<GraphNode>>();            var maxDepth = GetMaxDepth();            for (int i = 0; i <= maxDepth; i++)            {                depthNodes.Add(new List<GraphNode>());            }            foreach (var node in nodes)            {                if (node.inDegree == 0)                {                    depthNodes[0].Add(node);                }                else                {                    int deep = GetNodeDepth(node);                    depthNodes[maxDepth - deep].Add(node);                }            }            return depthNodes;        }        public List<GraphNode> GetRootNodes()        {            List<GraphNode> rootNodes = new List<GraphNode>();            foreach (var node in nodes)            {                if (node.inDegree == 0)                {                    rootNodes.Add(node);                }            }            return rootNodes;        }        public int GetMaxDepth()        {            int maxDepth = 0;            foreach (var node in nodes)            {                int deep = GetNodeDepth(node);                if (deep > maxDepth)                {                    maxDepth = deep;                }            }            return maxDepth;        }        // public int GetNodeDepth(GraphNode node)        // {        //     int depth = 0;        //     GetNodeDepth(node, ref depth);        //     return depth;        // }        // public void GetNodeDepth(GraphNode node, ref int depth, int recursiveCount = 0)        // {        //     if (recursiveCount > 50)        //     {        //         XLog.Error("Graph.GetNodeDeep(): recursiveCount > 50, maybe graph is ring");        //         return;        //     }        //     if (node.inDegree == 0)        //     {        //         return;        //     }        //     else        //     {        //         depth += 1;        //         foreach (var edge in node.inEdges)        //         {        //             GetNodeDepth(edge.node1, ref depth, recursiveCount + 1);        //         }        //     }        // }        public int GetNodeDepth(GraphNode node, int recursiveCount = 0)        {            if (recursiveCount > 50)            {                XLog.Error("Graph.GetNodeDeep(): recursiveCount > 50, maybe graph is ring");                return 0;            }            int depth = 0;            if (node.outDegree == 0)            {                return depth;            }            else            {                foreach (var edge in node.outEdges)                {                    int otherDeep = GetNodeDepth(edge.node2, recursiveCount + 1);                    if (otherDeep > depth)                    {                        depth = otherDeep;                    }                }                return depth + 1;            }        }        public GraphNode GetNode(string nodeId)        {            if (nodeMap.ContainsKey(nodeId))            {                return nodeMap[nodeId];            }            else            {                return null;            }        }        public GraphEdge GetEdge(string nodeId1, string nodeId2)        {            if (directed)            {                return edgeMap[nodeId1 + "_" + nodeId2];            }            else            {                var key = nodeId1 + "_" + nodeId2;                if (edgeMap.ContainsKey(key))                {                    return edgeMap[key];                }                else                {                    key = nodeId2 + "_" + nodeId1;                    if (edgeMap.ContainsKey(key))                    {                        return edgeMap[key];                    }                    else                    {                        return null;                    }                }            }        }        public GraphNode AddNode(string nodeId, string nodeName, int dataIndex)        {            if (nodeMap.ContainsKey(nodeId))            {                return nodeMap[nodeId];            }            else            {                GraphNode node = new GraphNode(nodeId, nodeName, dataIndex);                node.hostGraph = this;                nodeMap.Add(nodeId, node);                nodes.Add(node);                return node;            }        }        public GraphEdge AddEdge(string nodeId1, string nodeId2, double value)        {            GraphNode node1, node2;            if (!nodeMap.TryGetValue(nodeId1, out node1))            {                XLog.Warning("Graph.AddEdge(): " + nodeId1 + " not exist");                return null;            }            if (!nodeMap.TryGetValue(nodeId2, out node2))            {                XLog.Warning("Graph.AddEdge(): " + nodeId2 + " not exist");                return null;            }            if (node1 == null)            {                XLog.Warning("Graph.AddEdge(): node1 is null");                return null;            }            if (node2 == null)            {                XLog.Warning("Graph.AddEdge(): node2 is null");                return null;            }            if (node1 == node2)            {                XLog.Warning("Graph.AddEdge(): node1 == node2");                return null;            }            string edgeKey = nodeId1 + "_" + nodeId2;            if (edgeMap.ContainsKey(edgeKey))            {                return edgeMap[edgeKey];            }            else            {                GraphEdge edge = new GraphEdge(node1, node2, value);                edge.key = edgeKey;                edge.hostGraph = this;                if (directed)                {                    node1.outEdges.Add(edge);                    node2.inEdges.Add(edge);                }                node1.edges.Add(edge);                if (node1 != node2)                {                    node2.edges.Add(edge);                }                edgeMap.Add(edgeKey, edge);                edges.Add(edge);                return edge;            }        }        public void EachNode(System.Action<GraphNode> onEach)        {            if (onEach == null) return;            foreach (var node in nodes)            {                onEach(node);            }        }        public void BreadthFirstTraverse(GraphNode startNode, System.Action<GraphNode> onTraverse)        {            if (startNode == null) return;            foreach (var node in nodes)            {                node.visited = false;            }            onTraverse(startNode);            startNode.visited = true;            Queue<GraphNode> queue = new Queue<GraphNode>();            queue.Enqueue(startNode);            while (queue.Count > 0)            {                var currentNode = queue.Dequeue();                foreach (var edge in currentNode.edges)                {                    var otherNode = edge.node1 == currentNode ? edge.node2 : edge.node1;                    if (!otherNode.visited)                    {                        onTraverse(otherNode);                        otherNode.visited = true;                        queue.Enqueue(otherNode);                    }                }            }        }        public void DeepFirstTraverse(GraphNode startNode, System.Action<GraphNode> onTraverse)        {            if (startNode == null) return;            foreach (var node in nodes)            {                node.visited = false;            }            Stack<GraphNode> stack = new Stack<GraphNode>();            stack.Push(startNode);            while (stack.Count > 0)            {                var currentNode = stack.Pop();                if (!currentNode.visited)                {                    onTraverse(currentNode);                    currentNode.visited = true;                }                foreach (var edge in currentNode.edges)                {                    var otherNode = edge.node1 == currentNode ? edge.node2 : edge.node1;                    if (!otherNode.visited)                    {                        stack.Push(otherNode);                    }                }            }        }    }    /// <summary>    /// The node of graph.    /// ||图的节点。    /// </summary>    public class GraphNode    {        public string id;        public string name;        public List<GraphEdge> edges = new List<GraphEdge>();        public List<GraphEdge> inEdges = new List<GraphEdge>();        public List<GraphEdge> outEdges = new List<GraphEdge>();        public Graph hostGraph;        public int dataIndex;        public bool visited;        public int depth = -1;        public GraphNode(string id, string name, int dataIndex)        {            this.id = id;            this.name = name;            this.dataIndex = dataIndex;        }        public int degree { get { return edges.Count; } }        public int inDegree { get { return inEdges.Count; } }        public int outDegree { get { return outEdges.Count; } }        public double totalValues        {            get            {                double totalValue = 0;                if (inEdges.Count == 0)                {                    foreach (var edge in outEdges)                    {                        totalValue += edge.value;                    }                }                else                {                    foreach (var edge in inEdges)                    {                        totalValue += edge.value;                    }                }                return totalValue;            }        }        public override string ToString()        {            return name;        }    }    /// <summary>    /// The edge of graph.    /// ||图的边。    /// </summary>    public class GraphEdge    {        public string key;        public GraphNode node1;        public GraphNode node2;        public double value;        public Graph hostGraph;        public List<Vector3> points = new List<Vector3>();        public float width;        public bool highlight;        public GraphEdge(GraphNode node1, GraphNode node2, double value)        {            this.node1 = node1;            this.node2 = node2;            this.value = value;        }    }}
 |