绘制有向无环图:最小化边缘交叉?

在没有图形绘制算法(例如高效Sugiyama)的情况下,以树形式在DAG中布置顶点(即,顶部没有边缘的顶点,仅依赖于下一级的顶点等)非常简单。但是,是否有一种简单的算法可以做到最小化边缘交叉?(对于某些图形,可能无法完全消除边缘交叉。)一张图片说一千个单词,所以有一种算法可以建议某些不交叉边缘的东西。(与此相比)。

回答:

我已经接受了Senthil提出的graphviz / dot的建议-

快速浏览文档即可确认将它用作库或外部工具非常容易,并且输出格式也非常容易解析。但是,我最终选择使用GraphSharp,因为我已经在使用.NET等(尽管它绝对不如点强大)。结果是“足够好”,并且可以通过进行一些边缘布线和调整来变得更好(模糊文本是由于3.5

WPF造成的)。

自动布局的图形

这是 完整的 C#代码(这是引用QuickGraph或GraphSharp的所有代码-是的,就这么简单):

internal static class LayoutManager

{

private const string ALGORITHM_NAME = "EfficientSugiyama";

private const bool MINIMIZE_EDGE_LENGTH = true;

private const double VERTEX_DISTANCE = 25;

private const double LAYER_DISTANCE = 25;

private const double MIN_CANVAS_OFFSET = 20;

public static void doLayout(GraphCanvas canvas)

{

// TODO use a background thread

// TODO add comments

canvas.IsEnabled = false;

canvas.Cursor = Cursors.Wait;

var graph = new BidirectionalGraph<GraphNode, LayoutEdge>();

var positions = new Dictionary<GraphNode, Point>();

var sizes = new Dictionary<GraphNode, Size>();

foreach(var node in canvas.nodes)

{

var size = node.RenderSize;

graph.AddVertex(node);

positions.Add(node, new Point(node.left + size.Width / 2, node.top + size.Height / 2));

sizes.Add(node, size);

}

foreach(var edge in canvas.edges)

{

graph.AddEdge(new LayoutEdge(edge));

}

var context = new LayoutContext<GraphNode, LayoutEdge, BidirectionalGraph<GraphNode, LayoutEdge>>(graph, positions, sizes, LayoutMode.Simple);

var parameters = new EfficientSugiyamaLayoutParameters();

parameters.VertexDistance = VERTEX_DISTANCE;

parameters.MinimizeEdgeLength = MINIMIZE_EDGE_LENGTH;

parameters.LayerDistance = LAYER_DISTANCE;

var factory = new StandardLayoutAlgorithmFactory<GraphNode, LayoutEdge, BidirectionalGraph<GraphNode, LayoutEdge>>();

var algorithm = factory.CreateAlgorithm(ALGORITHM_NAME, context, parameters);

algorithm.Compute();

canvas.deselectAll();

var minx = algorithm.VertexPositions.Select(kvp => kvp.Value.X - (kvp.Key.RenderSize.Width / 2)).Aggregate(Math.Min);

var miny = algorithm.VertexPositions.Select(kvp => kvp.Value.Y - (kvp.Key.RenderSize.Height / 2)).Aggregate(Math.Min);

minx -= MIN_CANVAS_OFFSET;

miny -= MIN_CANVAS_OFFSET;

minx = minx < 0 ? -minx : 0;

miny = miny < 0 ? -miny : 0;

foreach(var kvp in algorithm.VertexPositions)

{

var node = kvp.Key;

var pos = kvp.Value;

node.left = (pos.X - (node.RenderSize.Width / 2)) + minx;

node.top = (pos.Y - (node.RenderSize.Height / 2)) + miny;

}

canvas.Cursor = Cursors.Arrow;

canvas.IsEnabled = true;

}

private sealed class LayoutEdge : IEdge<GraphNode>

{

private readonly ConnectingEdge _edge;

public LayoutEdge(ConnectingEdge edge) { _edge = edge; }

public GraphNode Source { get { return _edge.output.node; } }

public GraphNode Target { get { return _edge.input.node; } }

}

回答:

Dot似乎很合适:

点-有向图的``分层’‘或分层图。布局算法将边缘对准同一方向(从上到下或从左到右),然后尝试避免边缘交叉并减小边缘长度。

https://docs.google.com/viewer?url=http://www.graphviz.org/pdf/dotguide.pdf

以上是 绘制有向无环图:最小化边缘交叉? 的全部内容, 来源链接: utcz.com/qa/399729.html

回到顶部