首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >dagre-d3中的边缘定位

dagre-d3中的边缘定位
EN

Stack Overflow用户
提问于 2015-10-30 18:37:34
回答 3查看 3.3K关注 0票数 3

我使用dagre-d3并创建了这个示例图形。是否有可能避免标记为1的样本中的交叉问题。也许这可以标记到节点底部的边连接。我不确定如何实现此功能。有人能帮上忙吗?

此外,是否有可能拉直边缘2、3和4。有足够的空间来拉直它们。我只是不知道该怎么做。

任何帮助都将不胜感激。

泽山

EN

回答 3

Stack Overflow用户

发布于 2015-10-30 19:03:57

这是您试图解决的一个非常重要的问题。AFAIK dagre使用Brandes-Köpf算法的变体来计算比对。即使你能理解这个算法,调整它也是非常困难的。相反,使用完全不同的算法可能会给你带来更好的结果:在yFiles for HTML's实现的hierarchic/Sugiyama风格的布局中,使用了单工网络等级分配算法,它通常不会出现你在绘图中看到的问题(否则非常好)。GraphViz也对该算法进行了has an implementation,所以也许使用它也能为你的例子提供更好的结果。Simplex方法在计算上要昂贵得多,但非常容易配置和微调。

关于你的第一点:快速浏览一下来源,我不明白为什么这个问题会出现在你的Dagre样本中。看起来传入边的端口分配不能正常工作-端口的位置应该根据上一层中节点的相对位置进行排序。看起来不仅仅是贝塞尔控制点错了。

票数 1
EN

Stack Overflow用户

发布于 2018-04-08 17:53:43

我认为最新的dagre库不再有这些问题。我复制了你的图表(click here for the demo)。它们并不完全相同,但却非常相似。

演示站点由美人鱼提供支持,由dagre提供支持。

票数 1
EN

Stack Overflow用户

发布于 2018-07-24 02:50:38

代码语言:javascript
复制
// 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.
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33433979

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档