有向非循環圖的自動布局演算法

來源:互聯網
上載者:User

最近業餘在做一個基於結點的編輯工具玩, 遇到一個問題, 就是結點和連線多了, 經常會出現重疊交叉的問題, 導致圖看不清楚:

要是這個樣子, 還不如不用圖清楚呢, 所心就需要找一個方法來進行自動布局, 理想情況是這樣的(手動整理結果):

當然, 手動整理的話, 每個人弄出來的結果都不一樣. 自動的演算法肯定沒有100%完美的, 但是總是能方便不少的

在google了一會兒後, 發現這種結點-線組成的圖是一有個學名的: directed acyclic graph, 例如這樣:

無非我這個圖結點上的連接點是有限制的, 但這個對於布局演算法來說, 影響不大. 因為布局只需要大體考慮每個結點的位置

那麼, 這個演算法需要滿足幾個條件: 

  1. 結點之間不能有重疊
  2. 連線之間盡量減少交差
  3. 結點之間是有基本的層次關係對齊的
基於這些限制條件, google到一個比較有名的演算法Sugiyama's layout algorithm初步看了一上, 這個演算法比較複雜, 是多種演算法的集合自己不是很熟悉這方面的理論知識, 所以還是決定採用第三的演算法庫C++可以使用的圖繪製演算法庫, 比較常見的有Graphviz, OGDF, Boost Graph根據這個問題(http://stackoverflow.com/questions/2751826/which-c-graph-library-should-i-use)的推薦, 嘗試了OGDF, 效果還不錯(可惜是GPL協議)
//------------------------------------------------------------------------------voidQNodesEditor::autoLayout(){using namespace ogdf;Graph graph;// setup graphQMap<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 sizeGraphAttributes 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 layoutSugiyamaLayout layout;FastHierarchyLayout* ohl = new FastHierarchyLayout;ohl->layerDistance(30);ohl->nodeDistance(25);layout.setLayout(ohl);layout.call(graphAttr);// update node positionforall_nodes(node, graph){double x = graphAttr.x(node);double y = graphAttr.y(node);QNEBlock* item = nodeMap[node];item->setPos(y, x);}}

最終效果:

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.