public DrawingData DrawRadial() { DrawingData data = InitDrawingData(); TreeBorders borders = DrawSubtree(rootId, data, data.Height[rootId] + 1); double maxWidth = 0.0; double left = 0.0; double right = 0.0; for (int i = 0; i <= data.Height[rootId]; i++) { left += borders[i, BorderSide.Left]; right += borders[i, BorderSide.Right]; maxWidth = Math.Max(maxWidth, right - left); } maxWidth += 1.0; // 1 unit space. double scale = 360.0 / maxWidth; CalculateAbsuluteValues(data, scale, true); return(data); }
public DrawingData DrawLayered() { DrawingData data = InitDrawingData(); DrawSubtree(rootId, data, data.Height[rootId] + 1); CalculateAbsuluteValues(data, 1.0, false); return(data); }
private DrawingData InitDrawingData() { // Preprocessing int size = forest.Size; DrawingData data = new DrawingData(size, rootId, isDummyRoot); Stack <int> vStack = new Stack <int>(size); vStack.Push(rootId); data.Depth[rootId] = 0; while (vStack.Count > 0) { int vId = vStack.Peek(); int pId = forest.GetParent(vId); int[] neighs = forest[vId]; int maxHeight = -1; bool maxFound = true; foreach (int nId in neighs) { if (nId == pId) { continue; } data.Depth[nId] = data.Depth[vId] + 1; int nH = data.Height[nId]; if (nH == -1) { vStack.Push(nId); maxFound = false; } else { maxHeight = Math.Max(nH, maxHeight); } } if (maxFound) { data.Height[vId] = maxHeight + 1; vStack.Pop(); } } // while -- calculates height and depth for each vertex. return(data); }
private void Preprocess() { hypertree.TransformToDual(); // Generate and "draw" underlying tree. joinForest = hypertree.GetJoinTree(); drawer = new RootedDrawing(joinForest); data = drawer.DrawRadial(); // Computes colouring and max colour. colouring = hypertree.GetVertexColouring(); hypertree.TransformToDual(); maxCol = 0; for (int i = 0; i < colouring.Length; i++) { maxCol = Math.Max(colouring[i], maxCol); } // Counting sort to sort edges by their colour. edgeByColour = new int[colouring.Length]; int[] colCounter = new int[maxCol + 1]; for (int i = 0; i < colouring.Length; i++) { colCounter[colouring[i]]++; } for (int i = 1; i < colCounter.Length; i++) { colCounter[i] += colCounter[i - 1]; } for (int i = colouring.Length - 1; i >= 0; i--) { int col = colouring[i]; colCounter[col]--; int ind = colCounter[col]; edgeByColour[ind] = i; } // End of counting sort. Array.Reverse(edgeByColour); edges = new List <int> [hypertree.NoOfEdges]; for (int i = 0; i < edges.Length; i++) { edges[i] = new List <int>(Math.Max(hypertree.GetCardinality(i) * 2 - 2, 0)); } // Use a DFS to determine the tree-edges of each hyperedge. // The search starts at the root. // Each time the search reaces a vertex v, it checks for all edges e containing v, if e is already activated. // If e is already activated, the tree-edge from v to its parent is part of the edge. bool[] activeEdges = new bool[hypertree.NoOfEdges]; Stack <int> verStack = new Stack <int>(); Stack <int> parStack = new Stack <int>(); int[] rootIds = joinForest.GetRoots(); foreach (int rId in rootIds) { verStack.Push(rId); parStack.Push(-1); while (verStack.Count > 0) { int vId = verStack.Pop(); int pId = parStack.Pop(); int[] edgeIds = hypertree.GetEdges(vId); foreach (int eId in edgeIds) { if (activeEdges[eId]) { edges[eId].Add(pId); edges[eId].Add(vId); } activeEdges[eId] = true; } int[] neighs = joinForest[vId]; foreach (int nId in neighs) { if (nId == pId) { continue; } verStack.Push(nId); parStack.Push(vId); } } } // Now, data contains the radial coordinates of each vertex, // edges contains the list of tree-edges of each hyperedge, // colouring contains the colours of each hyperedge, // and edgeByColur has the edges ordered by their colour. }
private void CalculateAbsuluteValues(DrawingData data, double scale, bool radial) { Stack <int> vStack = new Stack <int>(forest.Size); Stack <double> sStack = new Stack <double>(forest.Size); vStack.Push(rootId); sStack.Push(scale); while (vStack.Count > 0) { double maxScale = sStack.Pop(); int vId = vStack.Pop(); int pId = forest.GetParent(vId); double xShift = data.XShift[vId]; int[] neighs = forest[vId]; data.XShift[vId] = (pId >= 0 ? data.XShift[pId] : 0) + xShift * maxScale; if (radial) { double minX = 0.0; double maxX = 0.0; foreach (int nId in neighs) { if (nId == pId) { continue; } minX = Math.Min(minX, data.XShift[nId]); maxX = Math.Max(maxX, data.XShift[nId]); } double difX = maxX - minX; if (difX > 0 && data.Depth[vId] > 0) { double rad = (double)data.Depth[vId]; double maxDif = 2 * Math.Acos(rad / (rad + 1.0)); maxDif *= (180 / Math.PI); maxScale = Math.Min(maxScale, maxDif / difX); } } foreach (int nId in neighs) { if (nId == pId) { continue; } vStack.Push(nId); sStack.Push(maxScale); } data.MinX = Math.Min(data.MinX, data.XShift[vId]); data.MaxX = Math.Max(data.MaxX, data.XShift[vId]); } }
private TreeBorders DrawSubtree(int vId, DrawingData data, int borderCap) { TreeBorders borders; if (data.Height[vId] == 0) { borders = new TreeBorders(borderCap); borders.Add(0.0, 0.0); return(borders); } int maxHeigtIndex = -1; int maxHeigtId = -1; int maxHeigt = -1; int pId = forest.GetParent(vId); int[] neighs = forest[vId]; for (int i = 0; i < neighs.Length; i++) { int nId = neighs[i]; if (nId == pId) { continue; } if (data.Height[nId] > maxHeigt) { maxHeigtIndex = i; maxHeigtId = nId; maxHeigt = data.Height[nId]; } } // Draw largest subtree with full capacity for borders. borders = DrawSubtree(maxHeigtId, data, borderCap); // Draw trees left of largest subtree. for (int i = maxHeigtIndex - 1; i >= 0; i--) { int leftId = neighs[i]; int leftHeight = data.Height[leftId]; int hDif = maxHeigt - leftHeight; if (leftId == pId) { continue; } TreeBorders leftBorders = DrawSubtree(leftId, data, leftHeight + 1); // The distance the left tree is moved. // Because it will move to the left, shiftDist will become negative. double shiftDist = 0.0; double totalLeftShift = 0.0; double totalMaxShift = 0.0; for (int h = 0; h <= leftHeight; h++) { totalLeftShift += leftBorders[h, BorderSide.Right]; totalMaxShift += borders[h, BorderSide.Left]; double dist = totalMaxShift - totalLeftShift; shiftDist = Math.Min(shiftDist, dist); } // Have 1 unit space between both trees. shiftDist -= 1.0; // Move tree. data.XShift[leftId] = shiftDist; borders[0, BorderSide.Left] = shiftDist; totalLeftShift = shiftDist; for (int h = 1; h <= leftHeight; h++) { double localShift = leftBorders[h, BorderSide.Left]; totalLeftShift += localShift; borders[h, BorderSide.Left] = localShift; } if (leftHeight < maxHeigt) { totalMaxShift += borders[leftHeight + 1, BorderSide.Left]; borders[leftHeight + 1, BorderSide.Left] = totalMaxShift - totalLeftShift; } } // Draw trees right of largest subtree. for (int i = maxHeigtIndex + 1; i < neighs.Length; i++) { int rightId = neighs[i]; int rightHeight = data.Height[rightId]; int hDif = maxHeigt - rightHeight; if (rightId == pId) { continue; } TreeBorders rightBorders = DrawSubtree(rightId, data, rightHeight + 1); // The distance the right tree is moved. // Because it will move to the right, shiftDist will become positive. double shiftDist = 0.0; double totalRightShift = 0.0; double totalMaxShift = 0.0; for (int h = 0; h <= rightHeight; h++) { totalRightShift += rightBorders[h, BorderSide.Left]; totalMaxShift += borders[h, BorderSide.Right]; double dist = totalMaxShift - totalRightShift; shiftDist = Math.Max(shiftDist, dist); } // Have 1 unit space between both trees. shiftDist += 1.0; // Move tree. data.XShift[rightId] = shiftDist; borders[0, BorderSide.Right] = shiftDist; totalRightShift = shiftDist; for (int h = 1; h <= rightHeight; h++) { double localShift = rightBorders[h, BorderSide.Right]; totalRightShift += localShift; borders[h, BorderSide.Right] = localShift; } if (rightHeight < maxHeigt) { totalMaxShift += borders[rightHeight + 1, BorderSide.Right]; borders[rightHeight + 1, BorderSide.Right] = totalMaxShift - totalRightShift; } } // Move trees such that center is 0. double xShift = -(borders[0, BorderSide.Right] + borders[0, BorderSide.Left]) / 2.0; borders[0, BorderSide.Right] += xShift; borders[0, BorderSide.Left] += xShift; for (int i = 0; i < neighs.Length; i++) { int nId = neighs[i]; if (nId == pId) { continue; } data.XShift[nId] += xShift; } borders.Add(0.0, 0.0); return(borders); }