/// <summary> /// Finds the coords. of the next item in the <see cref="PackedLayout"/> if it's /// added vertically. /// </summary> /// <param name="x">X coord. of previous node</param> /// <param name="y">Y coord. of previous node</param> /// <param name="verts">The list of all nodes</param> /// <param name="v">The index of the previous node in verts</param> /// <param name="newx">Returns the x coord. of the new node</param> /// <param name="newy">Returns the y coord. of the new node</param> /// <param name="dir">Whether the nodes are arranged Clockwise or Counterclockwise</param> /// <returns>true if a node can be added vertically and still be on the ellipse</returns> private bool nextv(double x, double y, CircularVertex[] verts, int v, out double newx, out double newy, CircularDirection dir) { newx = 0; newy = 0; bool inv = false; //true if it changes sides if (x >= 0 ^ dir == CircularDirection.Clockwise) { // y decreases newy = y - ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing); if (newy < -Yradius) { // y increases newy = y + ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing); if (newy > Yradius) { return false; } inv = true; } } else { // y increases newy = y + ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing); if (newy > Yradius) { // y decreases newy = y - ((verts[v].Height + verts[v + 1].Height) / 2 + ESpacing); if (newy < -Yradius) { return false; } inv = true; } } newx = Math.Sqrt(1 - newy * newy / (Yradius * Yradius)) * ERadius; if (x < 0 ^ inv) { newx = -newx; } if (Math.Abs(x - newx) > (verts[v].Width + verts[v + 1].Width) / 2) { return false; } else return true; }
private Random rand; // Packed layout sometimes alternates between 2 radii. If this happens, a random value is added to stop the cycle. /// <summary> /// Finds the coords. of the next item in the <see cref="PackedLayout"/> if it's /// added horizontally. /// </summary> /// <param name="x">X coord. of previous node</param> /// <param name="y">Y coord. of previous node</param> /// <param name="verts">The list of all nodes</param> /// <param name="v">The index of the previous node in verts</param> /// <param name="newx">Returns the x coord. of the new node</param> /// <param name="newy">Returns the y coord. of the new node</param> /// <param name="dir">Whether the nodes are arranged Clockwise or Counterclockwise</param> /// <returns>true if a node can be added horizontally and still be on the ellipse</returns> private bool nexth(double x, double y, CircularVertex[] verts, int v, out double newx, out double newy, CircularDirection dir) { newx = 0; newy = 0; bool inv = false; //true if it changes sides if (y >= 0 ^ dir == CircularDirection.Clockwise) { // x increases newx = x + ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing); if (newx > ERadius) { // x decreases newx = x - ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing); if (newx < -ERadius) { return false; } inv = true; } } else { // x decreases newx = x - ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing); if (newx < -ERadius) { newx = x + ((verts[v].Width + verts[v + 1].Width) / 2 + ESpacing); if (newx > ERadius) { return false; } inv = true; } } newy = Math.Sqrt(1 - newx * newx / (ERadius * ERadius)) * Yradius; if (y < 0 ^ inv) { newy = -newy; } if (Math.Abs(y - newy) > (verts[v].Height + verts[v + 1].Height) / 2) { return false; } else return true; }
public Subset(CircularVertex n, List<Subset> gs) { List = new List<CircularVertex>(); Conns = new List<CircularVertex>(); Head = n; List.Add(n); foreach (Subset g in gs) { foreach (CircularVertex nd in g.List) { this.List.Add(nd); } } foreach (CircularEdge li in n.SourceEdgesList) { CircularVertex nd = li.FromVertex; if (List.IndexOf(nd) < 0) { Conns.Add(nd); } } foreach (CircularEdge li in n.DestinationEdgesList) { CircularVertex nd = li.ToVertex; if (List.IndexOf(nd) < 0) { Conns.Add(nd); } } }
/// <summary> /// Sorts the nodes based on connectivity. The oth node is the one with the highest /// connectivity, and each subsequent node it the one with the greatest number of links with nodes /// already in the list /// </summary> /// <param name="l">The nodes to sort</param> /// <returns>The sorted list</returns> /// <remarks>This is used for cross reduction before <see cref="Optimize"/> is called because /// it makes the cross reduction much more effective. /// </remarks> private List<CircularVertex> ConnectivityArrange(CircularVertex[] l) { int[] conns = new int[l.Length]; List<CircularVertex> res = new List<CircularVertex>(); for (int i = 0; i < l.Length; i++) { int maxconn = -1; int maxind = -1; if (i == 0) { for (int j = 0; j < l.Length; j++) { CircularVertex vtx = l[j]; int nconn = vtx.SourceEdgesCount + vtx.DestinationEdgesCount; if (nconn > maxconn) { maxconn = nconn; maxind = j; } } } else for (int j = 0; j < l.Length; j++) { int nconn = conns[j]; if (nconn > maxconn) { maxconn = nconn; maxind = j; } } res.Add(l[maxind]); conns[maxind] = -1; CircularVertex v = l[maxind]; foreach (CircularEdge li in v.SourceEdgesList) { CircularVertex f = li.FromVertex; int ind = Array.IndexOf(l, f); if (ind < 0) { continue; } if (conns[ind] >= 0) { conns[ind]++; } } foreach (CircularEdge li in v.DestinationEdgesList) { CircularVertex f = li.ToVertex; int ind = Array.IndexOf(l, f); if (ind < 0) { continue; } if (conns[ind] >= 0) { conns[ind]++; } } } return res; }
/// <summary> /// Sorts the vertexes based on whatever <see cref="Sorting"/> specifies. /// </summary> /// <param name="vertexes">The vertexes to sort</param> private List<CircularVertex> Sort(CircularVertex[] vertexes) { switch (Sorting) { case CircularSorting.Forwards: break; case CircularSorting.Reverse: Array.Reverse(vertexes, 0, vertexes.Length); break; case CircularSorting.Ascending: if (Comparer != null) { Array.Sort(vertexes, Comparer); } break; case CircularSorting.Descending: if (Comparer != null) { Array.Sort(vertexes, Comparer); } Array.Reverse(vertexes, 0, vertexes.Length); break; case CircularSorting.Optimized: return Optimize(ConnectivityArrange(vertexes)); //case CircularSorting.GroupedOptimized: return OptimizeGroup(ConnectivityArrange(new List<CircularVertex>(nodes))); default: throw new NotImplementedException("This CircularSorting is not yet implemented"); } return new List<CircularVertex>(vertexes); }
/// <summary> /// Compares a new gap with the current one. If it's better, it updates <see cref="gap"/>, <see cref="xcoords"/>,and <see cref="ycoords"/>. /// This is for a partial sweep, where overshooting (gap less than 0) is no worse than undershooting (gap > 0). /// </summary> /// <param name="gap"></param> /// <param name="verts"></param> public void compare2(double gap, CircularVertex[] verts) { if (Math.Abs(gap) < Math.Abs(this.gap)) { this.gap = gap; xcoords = new double[verts.Length]; ycoords = new double[verts.Length]; for (int i = 0; i < verts.Length; i++) { xcoords[i] = verts[i].Position.X; ycoords[i] = verts[i].Position.Y; } } }