cytoscape.js。对于边缘线段,将坐标转换为线段距离和线段权重

时间:2018-12-04 22:39:20

标签: coordinates cytoscape.js segment

我想与社区分享一个有用的函数,该函数从坐标(PointX,PointY)返回分段距离和分段权重。

我通过工具(例如draw.io)创建图,并在具有多个航点的边线(段样式)时,该免费软件通过其坐标提供航点。不幸的是,最新版本的cytoscape.js(在我写这篇文章时)不包含此功能(如果可以的话,则表示歉意),仅使用段距离和段权重。

因此,我创建了以下函数,该函数使用源(sX,sY),目标(tX,tY)及其航路点(PointX,PointY)返回段距离和段权重值。此功能也可以用于多个航路点。 结果非常好,除了在免费软件(draw.io)上显示正交的线不会通过cytoscape.js完美呈现正交。需要在这方面进行锻炼!

function getDistWeight(sX, sY, tX, tY, PointX, PointY){
    var W, D;

    D = ( PointY - sY + (sX-PointX) * (sY-tY) / (sX-tX) ) /  Math.sqrt( 1 + Math.pow((sY-tY) / (sX-tX), 2) );
    W = Math.sqrt(  Math.pow(PointY-sY,2) + Math.pow(PointX-sX,2) - Math.pow(D,2)  );

    var distAB = Math.sqrt(Math.pow(tX-sX, 2) + Math.pow(tY-sY, 2));
    W = W / distAB;

    //check whether the point (PointX, PointY) is on right or left of the line src to tgt. for instance : a point C(X, Y) and line (AB).  d=(xB-xA)(yC-yA)-(yB-yA)(xC-xA). if d>0, then C is on left of the line. if d<0, it is on right. if d=0, it is on the line.
    var delta1 = (tX-sX)*(PointY-sY)-(tY-sY)*(PointX-sX);
        switch (true) {
          case (delta1 >= 0) :
            delta1 = 1;
            break;
          case (delta1 < 0) :
            delta1 = -1;
            break;
        }
    //check whether the point (PointX, PointY) is "behind" the line src to tgt
    var delta2 = (tX-sX)*(PointX-sX)+(tY-sY)*(PointY-sY);
        switch (true) {
          case (delta2 >= 0) :
            delta2 = 1;
            break;
          case (delta2 < 0) :
            delta2 = -1;
            break;
        }

    D = Math.abs(D) * delta1;   //ensure that sign of D is same as sign of delta1. Hence we need to take absolute value of D and multiply by delta1
    W = W * delta2;

    return {
        ResultDistance: D, 
        ResultWeight: W
    };
}

var point = getDistWeight(10, 5, 25, 15, 9, 6);
console.log(point);

1 个答案:

答案 0 :(得分:0)

我使用了您的函数,终于能够获得正交边。 为此需要做两件事:

  • 您需要以边缘样式将“ edge-distance”声明为“ node-position”
  • 您需要使用Edge的源位置和Edge的目标位置以及所需的点来调用函数,但以Edge的端点位置表示(请参见documentation here)。

下面的示例将生成此图:

enter image description here

要添加到cytoscape配置的样式:

selector: 'edge',
style: {
    'curve-style': 'segments',
    "segment-weights": '0.5',
    'segment-distances': '0',
    'edge-distances': 'node-position',
    'source-endpoint': '180deg',
    'target-endpoint': '0deg'
}

将计算每个边缘的拐点的代码:

// batch modifications to avoid rendering during changes
cytoscape.startBatch()

// get all edges from the graph
let edges = cytoscape.edges()
for (let edge of Object.values(edges)) {
    if (edge.data) {
        // get nodes positions for source and target
        let src = edge.source().position()
        let tgt = edge.target().position()
        // get endpoints positions for source and target
        let srcEp = edge.sourceEndpoint()
        let tgtEp = edge.targetEndpoint()

        if (src.x == tgt.x) {
            // do nothing, nodes are aligned vertically
        }
        else {
            // compute weight and distance for the point that will be added to the edge
            // the point will be added aligned horizontally with "source endpoint", and vertically 25px above target endpoint
            let point = getDistWeight(src.x, src.y, tgt.x, tgt.y, srcEp.x, tgtEp.y - 25);
            // set the values
            edge.style('segment-distances', ''+point.ResultDistance)
            edge.style('segment-weights', ''+point.ResultWeight)
        }
    }
}
cytoscape.endBatch()