cytoscape.js.对于边缘线段,将坐标转换为线段距离和线段权重 [英] cytoscape.js. For edge segment, transforming coordinates onto segment-distances and segment-weights

查看:56
本文介绍了cytoscape.js.对于边缘线段,将坐标转换为线段距离和线段权重的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

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

 函数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;//检查点(PointX,PointY)在src到tgt线的右边还是左边.例如:点C(X,Y)和线(AB).d =(xB-xA)(yC-yA)-(yB-yA)(xC-xA).如果d> 0,则C在该行的左侧.如果d <0,则在右边.如果d = 0,则为在线.var delta1 =(tX-sX)*(PointY-sY)-(tY-sY)*(PointX-sX);切换(true){情况(delta1> = 0):delta1 = 1;休息;情况(delta1< 0):delta1 = -1;休息;}//检查点(PointX,PointY)是否在src到tgt线的后面"var delta2 =(tX-sX)*(PointX-sX)+(tY-sY)*(PointY-sY);切换(true){大小写(delta2> = 0):delta2 = 1;休息;情况(delta2< 0):delta2 = -1;休息;}D = Math.abs(D)* delta1;//确保D的符号与delta1的符号相同.因此,我们需要取D的绝对值并乘以delta1W = W * delta2;返回 {结果距离:D,结果重量:W};}var point = getDistWeight(10,5,25,15,9,6);console.log(point); 

解决方案

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

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

    要添加到cytoscape配置的样式:

     选择器:"edge",风格: {'曲线样式':'分段',段权重":"0.5",'segment-distances':'0','edge-distances':'node-position','source-endpoint':'180deg','目标端点':'0deg'} 

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

     //批量修改以避免在更改期间呈现cytoscape.startBatch()//从图中获取所有边让边= cytoscape.edges()for(让Object.values(edges)的边){如果(edge.data){//获取源和目标的节点位置让src = edge.source().position()让tgt = edge.target().position()//获取源和目标的端点位置让srcEp = edge.sourceEndpoint()让tgtEp = edge.targetEndpoint()如果(src.x == tgt.x){//不执行任何操作,节点垂直对齐}别的 {//计算将添加到边缘的点的权重和距离//该点将与源端点"水平对齐,并在目标端点上方垂直25px处添加让点= getDistWeight(src.x,src.y,tgt.x,tgt.y,srcEp.x,tgtEp.y-25);//设置值edge.style('segment-distances',''+ point.ResultDistance)edge.style('segment-weights',''+ point.ResultWeight)}}}cytoscape.endBatch() 

    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);
    

    解决方案

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

    这篇关于cytoscape.js.对于边缘线段,将坐标转换为线段距离和线段权重的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆