有向无环图的自动布局算法
来源:互联网 发布:node.js 后端还是前端 编辑:程序博客网 时间:2024/05/16 19:18
原文地址:http://blog.csdn.net/xoyojank/article/details/8249719
最近业余在做一个基于结点的编辑工具玩, 遇到一个问题, 就是结点和连线多了, 经常会出现重叠交叉的问题, 导致图看不清楚:
要是这个样子, 还不如不用图清楚呢, 所心就需要找一个方法来进行自动布局, 理想情况是这样的(手动整理结果):
当然, 手动整理的话, 每个人弄出来的结果都不一样. 自动的算法肯定没有100%完美的, 但是总是能方便不少的
在google了一会儿后, 发现这种结点-线组成的图是一有个学名的: directed acyclic graph, 例如这样:
无非我这个图结点上的连接点是有限制的, 但这个对于布局算法来说, 影响不大. 因为布局只需要大体考虑每个结点的位置
那么, 这个算法需要满足几个条件:
- 结点之间不能有重叠
- 连线之间尽量减少交差
- 结点之间是有基本的层次关系对齐的
基于这些限制条件, google到一个比较有名的算法Sugiyama's layout algorithm
初步看了一上, 这个算法比较复杂, 是多种算法的集合
自己不是很熟悉这方面的理论知识, 所以还是决定采用第三的算法库
C++可以使用的图绘制算法库, 比较常见的有Graphviz, OGDF, Boost Graph
根据这个问题(http://stackoverflow.com/questions/2751826/which-c-graph-library-should-i-use)的推荐, 尝试了OGDF, 效果还不错(可惜是GPL协议)
- //------------------------------------------------------------------------------
- void
- QNodesEditor::autoLayout()
- {
- using namespace ogdf;
- Graph graph;
- // setup graph
- QMap<NodeElement*, QNEBlock*> nodeMap;
- foreach(QGraphicsItem * item, scene->items())
- {
- if (item->type() == QNEBlock::Type)
- {
- NodeElement* node = graph.newNode();
- item->setData(QNEBlock::Type, qVariantFromValue((void*)node));
- nodeMap[node] = (QNEBlock*)item;
- }
- }
- foreach(QGraphicsItem * item, scene->items())
- {
- if (item->type() == QNEConnection::Type)
- {
- QNEConnection* connection = (QNEConnection*)item;
- NodeElement* node1 = (NodeElement*)connection->port1()->block()->data(QNEBlock::Type).value<void*>();
- NodeElement* node2 = (NodeElement*)connection->port2()->block()->data(QNEBlock::Type).value<void*>();
- graph.newEdge(node1, node2);
- }
- }
- // node size
- GraphAttributes graphAttr(graph,
- GraphAttributes::nodeGraphics | GraphAttributes::edgeGraphics |
- GraphAttributes::nodeLabel | GraphAttributes::nodeColor |
- GraphAttributes::edgeColor | GraphAttributes::edgeStyle |
- GraphAttributes::nodeStyle | GraphAttributes::nodeTemplate);
- NodeElement* node;
- forall_nodes(node, graph)
- {
- QNEBlock* item = nodeMap[node];
- graphAttr.width(node) = item->getHeight();
- graphAttr.height(node) = item->getWidth();
- }
- // compute layout
- SugiyamaLayout layout;
- FastHierarchyLayout* ohl = new FastHierarchyLayout;
- ohl->layerDistance(30);
- ohl->nodeDistance(25);
- layout.setLayout(ohl);
- layout.call(graphAttr);
- // update node position
- forall_nodes(node, graph)
- {
- double x = graphAttr.x(node);
- double y = graphAttr.y(node);
- QNEBlock* item = nodeMap[node];
- item->setPos(y, x);
- }
- }
0 0
- 有向无环图的自动布局算法
- 有向无环图的自动布局算法
- 有向有环图的层次布局算法(一)
- 【算法】有向无环图
- 算法导论22.4-2 有向无环图的路径数目
- 算法: 有向无环图(DAG)的拓扑排序
- C语言实现有向无环图的拓扑排序算法
- 有向图的Dijkstra算法
- 有向连通分量的Tarjan算法
- 有向图的遍历算法
- 有向图的Dijkstra算法
- 图算法--有向无环图(DAG)
- 算法 有向无环图 拓扑排序
- 有向图的强连通算法 -- tarjan算法
- 图之有向无环图的应用--拓扑排序算法的实现
- 有向图的强连通分量的三个算法
- 有向图的强连通分量的Tarjan算法
- 有向无环图两点之间的路径数目(算法导论22.4-2)
- 【OpenGL】使用Unity来学习OpenGL
- 使用MLP解决OCR问题(OpenCV)(上)
- 又一次意识到 离散数学 在程序逻辑中的应用
- 如何实现android和服务器长连接呢?推送消息的原理
- Android 百度地图 java.lang.UnsatisfiedLinkError: Couldn't load vi_voslib: findLibrary returned null
- 有向无环图的自动布局算法
- Eclipse中离线安装ADT插件
- UI设计规范
- 不定式方程求整数解(百钱百鸡问题)(百马百货问题)
- Android中Matrix的set、pre、post的区别
- 关于userInteractionEnabled的属性的理解
- PHPStrom使用的几个设置
- Android判断设备网络连接状态,并判断连接方式
- 【EXKMP】AHOI 2007 D1T3 灯阵