/// <summary>Default ctor</summary> public Graph() { _NodeRegistry = 0; _Nodes = new List<Node>(); _Edges = new List<Edge>(); DragNode = null; }
/// <summary>Creates a new node and adds it to the graph </summary> /// <param name="label">Label of the new node</param> /// <param name="magnet">Movement speed</param> /// <returns>the newly created node</returns> public Node AddNode(string label, double magnet = 60.0) { Node result = FindNode(label); if (result != null) // already existing return result; result = new Node(++_NodeRegistry, label, magnet); _Nodes.Add(result); return result; }
/// <summary>Initialization ctor</summary> /// <param name="from">Node where this edge begins</param> /// <param name="to">Node where this edge ends</param> /// <param name="len">Virtual length of this edge</param> public Edge(Node from, Node to, double len = 40.0) { From = from; To = to; Length = len; }
/// <summary>Creates a new egde and adds it to the graph</summary> /// <param name="from">Starting node</param> /// <param name="to">Ending node</param> /// <returns>the newly created edge</returns> public Edge AddEdge(Node from, Node to) { Edge result = new Edge(from, to); _Edges.Add(result); return result; }
private void ForAllNodePairs(Node n1, Node n2) { double dx = 0; double dy = 0; double vx = n1.x - n2.x; double vy = n1.y - n2.y; double len = vx * vx + vy * vy; //so it's length squared if (len == 0) { Random rand = new Random(); dx = rand.NextDouble(); //If two nodes are right on top of each other, randomly separate dy = rand.NextDouble(); } else if (len < 600 * 600) { // 600, because we don't want deleted nodes to fly too far away dx = vx / len; // If it was sqrt(len) then a single node surrounded by many others will dy = vy / len; // always look like a circle. This might look good at first, but I think // it makes large graphs look ugly + it contributes to oscillation. A // linear function does not fall off fast enough, so you get rough edges // in the 'force field' } double repSum = n1.repulsion * n2.repulsion / 100; n1.dx += dx * repSum * rigidity; n1.dy += dy * repSum * rigidity; n2.dx -= dx * repSum * rigidity; n2.dy -= dy * repSum * rigidity; }
private void ForAllNodes(Node node) { double dx = node.dx; double dy = node.dy; dx *= damper; //The damper slows things down. It cuts down jiggling at the last moment, and optimizes dy *= damper; //layout. As an experiment, get rid of the damper in these lines, and make a //long straight line of nodes. It wiggles too much and doesn't straighten out. node.dx = dx / 2; //Slow down, but don't stop. Nodes in motion store momentum. This helps when the force node.dy = dy / 2; //on a node is very low, but you still want to get optimal layout. double distMoved = Math.Sqrt(dx * dx + dy * dy); //how far did the node actually move? if (!node.IsFixed) { node.x += Math.Max(-30, Math.Min(30, dx)); //don't move faster then 30 units at a time. node.y += Math.Max(-30, Math.Min(30, dy)); //I forget when this is important. Stopping severed nodes from //flying away? } maxMotionA = Math.Max(distMoved, maxMotionA); }