我想与社区分享一个有用的函数,该函数从坐标(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);
答案 0 :(得分:0)
我使用了您的函数,终于能够获得正交边。 为此需要做两件事:
下面的示例将生成此图:
要添加到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()