cytoscape.js. For edge segment, transforming coordinates onto segment-distances and segment-weights

喜欢而已 提交于 2021-01-27 11:39:45

问题


I'd like to share with community an useful function that returns segment-distances and segment-weights from a coordinate (PointX, PointY).

I create diagrams from tool (such as draw.io) and when making edge (segment style) with multiple waypoints, the freeware provides waypoints by its coordinates. Unfortunately latest version of cytoscape.js (at the time I wrote this post) dont include this capability (apologies if it does) and only segment-distances and segment-weights are used.

Therefore I created the below function that returns both segment-distances and segment-weights values using source (sX, sY), target (tX, tY) and its waypoint (PointX, PointY). This function could also be used for multiple waypoints as well. The result is pretty good except that lines appearing orthogonals on freeware (draw.io) dont appear perfectly orthogonals via cytoscape.js. Need to work out on that aspect !

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:


I used your function and was finally able to get orthogonal edges. There are 2 things that are needed for this:

  • You need to declare "edge-distance" in your edge's style as "node-position"
  • You need to call your function with edge's source position and edge's target position, and the point you wants, but expressed with edge's endpoints position (see documentation here).

Example below will produce this graph:

The style to add to cytoscape config:

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

The code that will compute the inflection point for each edge:

// 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()


来源:https://stackoverflow.com/questions/53622515/cytoscape-js-for-edge-segment-transforming-coordinates-onto-segment-distances

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!