簡體   English   中英

dagre-d3中的邊緣定位

[英]Edge positioning in dagre-d3

我正在使用dagre-d3並創建了此示例圖。 是否有可能避免標記為1的樣本中的交叉問題。也許這可以標記到節點底部的邊緣連接。 我不確定如何實現此功能。 有人可以幫忙嗎?

此外,可以拉直邊緣2、3和4。有足夠的空間可以拉直它們。 我只是不知道該怎么做。

任何幫助,將不勝感激。

Zeeshan

在此處輸入圖片說明

這是您要解決的非常重要的問題。 AFAIK dagre使用Brandes-Köpf的算法變體來計算比對。 即使您了解該算法,也很難對其進行調整。 而是使用完全不同的算法可能會給您帶來更好的結果:在yFiles for HTML的分層/ Sugiyama樣式布局的HTML實現中,使用了Simplex網絡等級分配算法,該算法通常不會遇到您所遇到的問題(否則非常好) ) 畫畫。 GraphViz也該算法的實現,因此也許使用該算法也可以為您的示例提供更好的結果。 Simplex方法在計算上要昂貴得多,但是非常易於配置和微調。

關於您的第一點:快速瀏覽資料來源,我不明白為什么問題在您使用Dagre的樣本中出現。 看起來輸入邊緣的端口分配無法正常工作-端口位置應根據上一層中節點的相對位置進行排序。 看起來好像不是貝塞爾曲線控制點是錯誤的。

我認為最新的dagre庫不再有這些問題。 我復制了您的圖表( 單擊此處查看演示 )。 它不完全相同,但非常相似。

該演示站點由美人魚提供動力,而人魚則由dagre提供動力。

在此處輸入圖片說明

// Create a new directed graph
var g = new dagreD3.graphlib.Graph().setGraph({});

// function to shuffle the list...
function shuffle(a) {
  var j, x, i;
  for (i = a.length; i; i -= 1) {
    j = Math.floor(Math.random() * i);
    x = a[i - 1];
    a[i - 1] = a[j];
    a[j] = x;
  }
  return a;
}

var nodes = ["10007154_1100", "148570017_1100", "148570018_1100", "148570019_1100",
  "148570025_1100", "148570010_1100", "148570021_1100", "148570020_1100",
  "148570026_1100", "148570011_1100", "148570022_1100", "148570010_1200", "148570020_1200", "148570026_1200", "148570023_1100", "148570011_1200",
  "148570023_1200"

];

// collect edges to a list
var edgeList = [
  ["10007154_1100", "148570017_1100", {
    "label": ""
  }],
  ["148570017_1100", "148570018_1100", {
    "label": ""
  }],
  ["148570018_1100", "148570019_1100", {
    "label": ""
  }],
  ["148570018_1100", "148570025_1100", {
    "label": ""
  }],
  ["148570019_1100", "148570020_1100", {
    "label": ""
  }],
  ["148570019_1100", "148570021_1100", {
    "label": ""
  }],
  ["148570019_1100", "148570010_1100", {
    "label": ""
  }],
  ["148570025_1100", "148570010_1100", {
    "label": ""
  }],
  ["148570025_1100", "148570026_1100", {
    "label": ""
  }],
  ["148570021_1100", "148570022_1100", {
    "label": ""
  }],
  ["148570010_1100", "148570011_1100", {
    "label": ""
  }],
  ["148570010_1100", "148570010_1200", {
    "label": ""
  }],
  ["148570020_1100", "148570020_1200", {
    "label": ""
  }],
  ["148570026_1100", "148570026_1200", {
    "label": ""
  }],
  ["148570026_1200", "148570011_1200", {
    "label": ""
  }],
  ["148570010_1200", "148570011_1200", {
    "label": ""
  }],
  ["148570022_1100", "148570023_1100", {
    "label": ""
  }],
  ["148570023_1100", "148570023_1200", {
    "label": ""
  }]
];

// Automatically label each of the nodes


var svg = d3.select("svg"),
  inner = svg.select("g");

function render_graph(render) {

  var max_cnt = 100; // try 100 times, if optimal not found, give up
  var iter_cnt = 0;
  var optimalArray, best_result;
  while (max_cnt--) {
    var g = new dagreD3.graphlib.Graph().setGraph({});
    nodes.forEach(function(node) {
      g.setNode(node, {
        label: node
      });
    });

    // set edges... randomize the list
    var list = shuffle(edgeList);
    if (!optimalArray) optimalArray = list;
    edgeList.forEach((edge) => {
      g.setEdge.apply(g, edge);
    })

    // Set the rankdir
    g.graph().rankdir = "LR";
    g.graph().nodesep = 60;

    render(inner, g);

    var nn = svg.select(".edgePaths");
    var paths = nn[0][0];
    var fc = paths.firstChild;
    var boxes = [];
    while (fc) {
      // console.log(fc.firstChild.getAttribute("d"))
      var path = fc.firstChild.getAttribute("d");
      var coords = path.split(/,|L/).map(function(c) {
        var n = c;
        if ((c[0] == "M" || c[0] == "L")) n = c.substring(1);
        return parseFloat(n);
      })
      boxes.push({
        left: coords[0],
        top: coords[1],
        right: coords[coords.length - 2],
        bottom: coords[coords.length - 1]
      });
      // console.log(coords);
      fc = fc.nextSibling;
    }
    // console.log("boxes", boxes);
    var collisionCnt = 0;
    boxes.forEach(function(a) {
      // --> test for collisions against other nodes...
      boxes.forEach(function(b) {
        if (a == b) return;
        // test if outside
        if ((a.right < b.left) ||
          (a.left > b.right) ||
          (a.top > b.bottom) ||
          (a.bottom < b.top)) {

          // test if inside
          if (a.left >= b.left && a.left <= b.right || a.right >= b.left && a.right <= b.right) {
            if (a.top <= b.top && a.top >= b.bottom) {
              collisionCnt++;
            }
            if (a.bottom <= b.top && a.bottom >= b.bottom) {
              collisionCnt++;
            }
          }
        } else {
          collisionCnt++;
        }
      })
    })
    console.log("collisions ", collisionCnt);
    if (collisionCnt == 0) {
      optimalArray = list.slice();
      console.log("Iteration cnt ", iter_cnt);
      break;
    }
    if (typeof(best_result) == "undefined") {
      best_result = collisionCnt;
    } else {
      if (collisionCnt < best_result) {
        optimalArray = list.slice();
        best_result = collisionCnt;
      }
    }
    iter_cnt++;
  }

  // if no optimal was found just render what was found...
  if (best_result >= 0) {
    var g = new dagreD3.graphlib.Graph().setGraph({});
    nodes.forEach(function(node) {
      g.setNode(node, {
        label: node
      });
    });
    optimalArray.forEach((edge) => {
      g.setEdge.apply(g, edge);
    })
    g.graph().rankdir = "LR";
    g.graph().nodesep = 60;
    render(inner, g);
  }

  // Center the graph
  var initialScale = 0.75;
  zoom
    .translate([(svg.attr("width") - g.graph().width * initialScale) / 2, 20])
    .scale(initialScale)
    .event(svg);
  svg.attr('height', g.graph().height * initialScale + 40);

}

// Set up zoom support
var zoom = d3.behavior.zoom().on("zoom", function() {
  inner.attr("transform", "translate(" + d3.event.translate + ")" +
    "scale(" + d3.event.scale + ")");
});
svg.call(zoom);

// Create the renderer
var render = new dagreD3.render();

render_graph(render);

// Run the renderer. This is what draws the final graph.

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM