private double calcAngularWidth(Representation.node n, int d) { Pars[n.name].visited = true; if (d > m_maxDepth) { m_maxDepth = d; } double aw = 0; double w = n.DisplayShape.Width, h = n.DisplayShape.Height; double diameter = d == 0 ? 0 : Math.Sqrt(w * w + h * h) / d; if ((n.arcs.Count > 1) || (n == root)) { foreach (Representation.arc a in n.arcs) { if (!Pars[a.otherNode(n).name].visited) { aw += calcAngularWidth(a.otherNode(n), d + 1); } } aw = Math.Max(diameter, aw); } else { aw = diameter; } Pars[n.name].width = aw; return(aw); }
private List <Representation.node> sortedChildren(Representation.node n, Representation.node p) { double basevalue = 0; int cc; // update basevalue angle for node ordering if (p != null) { cc = n.arcs.Count - 1; basevalue = normalize(Math.Atan2(p.Y - n.Y, p.X - n.X)); } else { cc = n.arcs.Count; } if ((cc == 0) && (n != root)) { return(null); } Representation.arc arc0 = (Representation.arc)n.arcs[0]; Representation.node c = arc0.otherNode(n); if (c == p) { Representation.arc arc1 = (Representation.arc)n.arcs[1]; c = arc1.otherNode(n); } double[] angle = new double[n.arcs.Count]; int[] idx = new int[n.arcs.Count]; for (int i = 0; i < n.arcs.Count; ++i) { Representation.arc arc = (Representation.arc)n.arcs[i]; c = arc.otherNode(n); idx[i] = i; if (c != p) { angle[i] = normalize(-basevalue + Math.Atan2(c.Y - n.Y, c.X - n.X)); } else { angle[i] = Double.MaxValue; } } Array.Sort(angle, idx); //or is it the other way around? List <Representation.node> col = new List <Representation.node>(); //List<node> children = n.Children; for (int i = 0; i < cc; ++i) { Representation.arc arc = (Representation.arc)n.arcs[idx[i]]; col.Add(arc.otherNode(n)); } return(col); }
protected void setPolarLocation(Representation.node n, Representation.node p, double r, double t) { for (int i = 0; i < graph.nodes.Count; i++) { if (graph.nodes[i].name == n.name) { graph.nodes[i].X = (float)(m_origin.X + r * Math.Cos(t)); graph.nodes[i].Y = (float)(m_origin.Y + r * Math.Sin(t)); } } }
private void AdjustChildren(Representation.node v, BalloonData data, float s) { if (s > Math.PI) { data.c = (float)Math.PI / s; data.f = 0; } else { data.c = 1; data.f = (float)Math.PI - s; } }
private void calcAngularBounds(Representation.node r, Representation.node ParentNode) { if (m_prevRoot == null || r == m_prevRoot) { m_prevRoot = r; return; } // try to find previous parent of root Representation.node p = m_prevRoot; while (true) { Representation.node pp = ParentNode; if (pp == r) { break; } else if (pp == null) { m_prevRoot = r; return; } p = pp; } // compute offset due to children's angular width double dt = 0; List <Representation.node> iter = sortedChildren(r, ParentNode); foreach (Representation.node n in iter) { if (n == p) { break; } dt += Pars[n.name].width; } double rw = Pars[r.name].width; double pw = Pars[p.name].width; dt = -Math.PI * 2 * (dt + pw / 2) / rw; // set angular bounds m_theta1 = dt + Math.Atan2(p.Y - r.Y, p.X - r.X); m_theta2 = m_theta1 + Math.PI * 2; m_prevRoot = r; }
/// <summary> /// Finds the the closest vertex to the given position. /// </summary> /// <param name="tempPos">The position.</param> /// <returns>Returns with the reference of the closest vertex.</returns> private Representation.node GetClosest(Point tempPos) { Representation.node vertex = default(Representation.node); double distance = double.MaxValue; //find the closest vertex for (var i = 0; i < nodeList.Count; i++) { Point nodeLocation = new Point(nodeList[i].X, nodeList[i].Y); double d = (tempPos - nodeLocation).Length; if (d < distance) { vertex = nodeList[i]; distance = d; } } return(vertex); }
protected int num_descendents(Representation.node node) { if (node.arcsFrom.Count == 0) { return(0); } else if (node.arcsFrom.Count == 1) { return(num_descendents(node.arcsFrom[0].To)); } else { var total_desc_count = 0; for (int i = 0; i < node.arcsFrom.Count; i++) { total_desc_count += num_descendents(node.arcsFrom[i].To); } return(node.arcsFrom.Count + total_desc_count); } }
protected void outputchild(Representation.node node, int x_val, int y_val) { node.X = x_val; node.Y = y_val; var x_offset = 0; for (int i = 0; i < node.arcsFrom.Count; i++) { if (i > 0) { if (num_descendents(node.arcsFrom[i - 1].To) > 0) { x_offset += (int)HorizontalSpacing * (num_descendents(node.arcsFrom[i - 1].To) - 1); } } outputchild(node.arcsFrom[i].To, (x_val + x_offset), (y_val + (int)VerticalSpacing)); x_offset = x_offset + (int)HorizontalSpacing; } }
private void SecondWalk(Representation.node v, Representation.node r, double x, double y, float l, float t) { visitedVertices.Add(v); BalloonData data = datas[v]; for (var i = 0; i < graph.nodes.Count; i++) { if (graph.nodes[i].name == v.name) { graph.nodes[i].X = x * HorizontalSpacing; graph.nodes[i].Y = y * VerticalSpacing; } } float dd = l * data.d; float p = (float)(t + Math.PI); int degree = v.degree; float fs = (degree == 0 ? 0 : data.f / degree); float pr = 0; foreach (var edge in v.arcsFrom) { var otherVertex = edge.To; if (visitedVertices.Contains(otherVertex)) { continue; } var otherData = datas[otherVertex]; float aa = data.c * otherData.a; float rr = (float)(data.d * Math.Tan(aa) / (1 - Math.Tan(aa))); p += pr + aa + fs; float xx = (float)((l * rr + dd) * Math.Cos(p)); float yy = (float)((l * rr + dd) * Math.Sign(p)); pr = aa;; SecondWalk(otherVertex, v, x + xx, y + yy, l * data.c, p); } }
protected void Adjust() { _tempPos = new Point(); //get a random point in the container _tempPos.X = 0.1 * (HorizontalSpacing * 9) + (_rnd.NextDouble() * 0.8 * (HorizontalSpacing * 9)); _tempPos.Y = 0.1 * (VerticalSpacing * 9) + (_rnd.NextDouble() * 0.8 * (VerticalSpacing * 9)); //find the closest vertex to this random point Representation.node closest = GetClosest(_tempPos); //adjust the vertices to the selected vertex for (var i = 0; i < nodeList.Count; i++) { if (_isomDataDict.Keys.Contains(nodeList[i])) { ISOMData vid = _isomDataDict[nodeList[i]]; vid.Distance = 0; vid.Visited = false; } } AdjustVertex(closest); }
protected void layout(Representation.node n, double r, double theta1, double theta2, Representation.node ParentNode) { Pars[n.name].visited = true; double dtheta = (theta2 - theta1); double dtheta2 = dtheta / 2.0; double width = Pars[n.name].width; double cfrac, nfrac = 0.0; foreach (Representation.node c in sortedChildren(n, ParentNode)) { Params cp = Pars[c.name]; cfrac = cp.width / width; if (!Pars[c.name].visited && ((c.arcs.Count > 1) || (c == root))) { layout(c, r + m_radiusInc, theta1 + nfrac * dtheta, theta1 + (nfrac + cfrac) * dtheta, n); } setPolarLocation(c, n, r, theta1 + nfrac * dtheta + cfrac * dtheta2); cp.angle = cfrac * dtheta; nfrac += cfrac; } }
private void FirstWalk(Representation.node v) { var data = datas[v]; visitedVertices.Add(v); data.d = 0; float s = 0; foreach (var edge in v.arcsFrom) { var otherVertex = edge.To; var otherData = datas[otherVertex]; if (!visitedVertices.Contains(otherVertex)) { FirstWalk(otherVertex); data.d = Math.Max(data.d, otherData.r); otherData.a = (float)Math.Atan(((float)otherData.r) / (data.d + otherData.r)); s += otherData.a; } } AdjustChildren(v, data, s); SetRadius(v, data); }
private void SetRadius(Representation.node v, BalloonData data) { data.r = (int)Math.Max(data.d / 2, minRadius); }
protected override bool RunLayout() { bool istree = FindRoot(); if (istree == false) { backgroundWorker.ReportProgress(100); throw new Exception("The input graph is not a tree. This layout only works on tree structures."); } backgroundWorker.ReportProgress(25); if (backgroundWorker.CancellationPending) { return(false); } m_origin.X = 0; m_origin.Y = 0; int minNumArcsFrom = int.MaxValue; int rootIndex = 0; int[] numArcsFrom = new int[graph.nodes.Count]; for (int i = 0; i != graph.nodes.Count; i++) { numArcsFrom[i] = graph.nodes[i].arcsFrom.Count; if (numArcsFrom[i] < minNumArcsFrom) { minNumArcsFrom = numArcsFrom[i]; rootIndex = i; } } backgroundWorker.ReportProgress(40); if (backgroundWorker.CancellationPending) { return(false); } root = graph.nodes[rootIndex]; m_radiusInc = RadialInc; //Make default radius the value of spacing slider m_prevRoot = null; m_theta1 = 0; m_theta2 = m_theta1 + Math.PI * 2; Pars = new Dictionary <string, Params>(); Params par; foreach (Representation.node node in graph.nodes) { par = new Params(); Pars.Add(node.name, par); } foreach (Params p in Pars.Values) { p.visited = false; } Representation.node n = root; Params np = Pars[n.name]; // calc relative widths and maximum tree depth // performs one pass over the tree m_maxDepth = 0; calcAngularWidth(n, 0); backgroundWorker.ReportProgress(50); if (backgroundWorker.CancellationPending) { return(false); } foreach (Params p in Pars.Values) { p.visited = false; } if (!m_setTheta) { calcAngularBounds(n, null); } // perform the layout if (m_maxDepth > 0) { layout(n, m_radiusInc, m_theta1, m_theta2, null); } // update properties of the root node for (int i = 0; i < graph.nodes.Count; i++) { if (graph.nodes[i].name == n.name) { graph.nodes[i].X = m_origin.X; graph.nodes[i].Y = m_origin.Y; } } backgroundWorker.ReportProgress(90); if (backgroundWorker.CancellationPending) { return(false); } np.angle = m_theta2 - m_theta1; return(true); }
private void AdjustVertex(Representation.node closest) { if (_isomDataDict.Keys.Contains(closest)) { _queue.Clear(); ISOMData vid = _isomDataDict[closest]; vid.Distance = 0; vid.Visited = true; _queue.Enqueue(closest); while (_queue.Count > 0) { if (_queue.Count != 0) { Representation.node current = _queue.Dequeue(); if (current != null) { ISOMData currentVid = _isomDataDict[current]; Point pos = VertexPositions[current]; Vector force = _tempPos - pos; double factor = adaptation / Math.Pow(2, currentVid.Distance); pos += factor * force; VertexPositions[current] = pos; List <node> neighbors = new List <node>(GetNeighbors(current)); if (currentVid.Distance < radius) { for (int i = 0; i < neighbors.Count; i++) { ISOMData nvid = _isomDataDict[neighbors[i]]; if (!nvid.Visited) { nvid.Visited = true; nvid.Distance = currentVid.Distance + 1; _queue.Enqueue(neighbors[i]); } } } int index = 0; /* * for (int i = 0; graph.nodes[i] != current; i++) * { * index++; * } * * graph.nodes[index].X = VertexPositions[current].X; * graph.nodes[index].Y = VertexPositions[current].Y; */ //PORT VERTEXPOSITIONS TO graph.node (UPDATE LOCATIONS OF NODES) foreach (Point point in VertexPositions.Values.ToList()) { if (graph.nodes[index].name != null) { if (graph.nodes[index].arcs != null) { if (point.X == double.NaN || point.Y == double.NaN) { return; } graph.nodes[index].X = point.X; graph.nodes[index].Y = point.Y; index++; } } } } } } } }