最近业余在做一个基于结点的编辑工具玩, 遇到一个问题, 就是结点和连线多了, 经常会出现重叠交叉的问题, 导致图看不清楚:
要是这个样子, 还不如不用图清楚呢, 所心就需要找一个方法来进行自动布局, 理想情况是这样的(手动整理结果):
当然, 手动整理的话, 每个人弄出来的结果都不一样. 自动的算法肯定没有100%完美的, 但是总是能方便不少的
在google了一会儿后, 发现这种结点-线组成的图是一有个学名的: directed acyclic graph, 例如这样:
无非我这个图结点上的连接点是有限制的, 但这个对于布局算法来说, 影响不大. 因为布局只需要大体考虑每个结点的位置
那么, 这个算法需要满足几个条件:
//------------------------------------------------------------------------------ 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); } }最终效果: