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); }
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); }