在D3中从圆计算中优化路径距离 [英] Optimize path distance from circle calculation in D3

查看:123
本文介绍了在D3中从圆计算中优化路径距离的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这个D3.js图中,我使用了魔术数字 20 当直线是直线时, 30 当直线处于一个角度时,为了添加(图形节点)和路径(图形边缘)之间的余量。

我也使用相当随机的数字 1.5

code>作为一个乘数来增加距离路径末端圆的距离,因为它有一个 marker-end 附加到它。



给定圆弧半径 19 和箭头路径坐标 M0,0 V4 L2,2 Z ,我认为应该有可能计算路径应该从圈子中得到的确切距离(边距),但是我的数学技能只是不适合它。我还假设有可能找出路径的方向,因此不再需要保证金反转。



如果您有关于如何计算距离和保证金计算的想法 withMargins()函数可以优化,请提供答案。所有优化和代码减少都是受欢迎的。以下是相关的代码:

  this.withMargins = function(){
var diff = {
x: edge.end.x - edge.start.x,
y:edge.end.y - edge.start.y
};

var margin = {
start:{
x:0,
y:0
},
end:{
x: 0,
y:0
}
};

if(diff.x> 0&& diff.y === 0){
margins.start.x = 30;
} else if(diff.x< 0&& diff.y === 0){
margins.start.x = -30;
} else if(diff.x> 0){
margins.start.x = 20;
} else if(diff.x< 0){
margins.start.x = -20;
}

if(diff.y> 0&& diff.x === 0){
margins.start.y = 30;
} else if(diff.y< 0&& diff.x === 0){
margins.start.y = -30;
} else if(diff.y> 0){
margins.start.y = 20;
} else if(diff.y <0){
margins.start.y = -20;
}

if(margins.start.x!= 0){
margins.end.x = margins.start.x< 0?
Math.abs(margins.start.x * 1.5):
margins.start.x * -1.5;
}

if(margins.start.y!= 0){
margins.end.y = margins.start.y< 0?
Math.abs(margins.start.y * 1.5):
margins.start.y * -1.5;
}

//顶部分支边缘是倒置的,所以它们的边距
//也需要倒置。
if(edge.branch ==='top'){
var startX = margins.start.x;
var startY = margins.start.y;
margins.start.x = margins.end.x * -1;
margins.start.y = margins.end.y * -1;
margins.end.x = startX * -1;
margins.end.y = startY * -1;
}

edge.start.x + = margins.start.x;
edge.start.y + = marginins.start.y;
edge.end.x + = margins.end.x;
edge.end.y + = margins.end.y;

返回边缘;
};

代码可能看起来有些诡异,但这可以从很大程度上解释为它被删除我正在处理的 Reveal.js 演示文稿。我对如何改进代码的其他部分也有所了解,但是特别是 withMargins()函数的主体我很不满意。

解决方案

据我所知,你有第一个圆的中心(x0,y0),第二个圆的中心(x1, y1),圆弧半径R,圆周M所需的边距,并且希望找到箭头的起始和结束坐标。



(看起来你正在使用距离圆心的全距离,在这种情况下设置Marg)

  dx = x1  -  x0 
dy = y1 - y0
Len = math.sqrt(dx * dx + dy * dy)//使用math.hypot(如果可用)
Marg = R + M //圆心到箭头结束的全部距离。 30您的情况
Coeff = Marg / Len
ax0 = x0 + Coeff * dx //箭头开始坐标
ay0 = y0 + Coeff * dy
ax1 = x1 - Coeff * dx // arrow end
ay1 = y1 - Coeff * dy

就是这样。


In this D3.js graph I'm using the magic numbers 20 when the line is straight and 30 when the line is at an angle as the margin to withdraw from the path in order to add a margin between the circles (graph nodes) and the paths (graph edges).

I'm also using the fairly random number 1.5 as a multiplier to further the distance from the circle of the path's end, since it has a marker-end attached to it.

Given the circle radius of 19 and the arrow path coordinates M0,0 V4 L2,2 Z, I assume it should be possible to calculate the exact distance ("margin") the paths should have from the circles, but my math skills just aren't up for it. I also assume it's possible to figure out the direction of the paths so the margin inversion is no longer required.

If you have ideas on how the distance and margin calculation within the withMargins() function can be optimized, please provide an answer. All optimizations and code reductions are welcome. Here's the relevant code:

this.withMargins = function() {
    var diff = {
        x: edge.end.x - edge.start.x,
        y: edge.end.y - edge.start.y
    };

    var margins = {
        start: {
            x: 0,
            y: 0
        },
        end: {
            x: 0,
            y: 0
        }
    };

    if (diff.x > 0 && diff.y === 0) {
        margins.start.x = 30;
    } else if (diff.x < 0 && diff.y === 0) {
        margins.start.x = -30;
    } else if (diff.x > 0) {
        margins.start.x = 20;
    } else if (diff.x < 0) {
        margins.start.x = -20;
    }

    if (diff.y > 0 && diff.x === 0) {
        margins.start.y = 30;
    } else if (diff.y < 0 && diff.x === 0) {
        margins.start.y = -30;
    } else if (diff.y > 0) {
        margins.start.y = 20;
    } else if (diff.y < 0) {
        margins.start.y = -20;
    }

    if (margins.start.x != 0) {
        margins.end.x = margins.start.x < 0 ?
            Math.abs(margins.start.x * 1.5) :
            margins.start.x * -1.5;
    }

    if (margins.start.y != 0) {
        margins.end.y = margins.start.y < 0 ?
            Math.abs(margins.start.y * 1.5) :
            margins.start.y * -1.5;
    }

    // The top branch edges are inverted, so their margins
    // needs to be inverted too.
    if (edge.branch === 'top') {
        var startX = margins.start.x;
        var startY = margins.start.y;
        margins.start.x = margins.end.x * -1;
        margins.start.y = margins.end.y * -1;
        margins.end.x = startX * -1;
        margins.end.y = startY * -1;
    }

    edge.start.x += margins.start.x;
    edge.start.y += margins.start.y;
    edge.end.x += margins.end.x;
    edge.end.y += margins.end.y;

    return edge;
};

The code might look a bit wonky, but that can largely be explained by it being torn out of a Reveal.js presentation I'm working on. I'm all up for ideas on how to improve other parts of the code as well, but it's particularly the body of the withMargins() function I'm unhappy with.

解决方案

As far I understand - you have center of the first circle (x0,y0), center of the second circle (x1,y1), circle radius R, desired margin from circle circumference M, and want to find starting and ending coordinates of arrow.

(Seems you are using full distance from circle center, in this case set Marg)

dx = x1 - x0
dy = y1 - y0
Len = math.sqrt(dx * dx + dy * dy)  //use math.hypot if available
Marg = R + M  //full distance from circle center to arrow end. 30 in your case
Coeff = Marg / Len
ax0 = x0 + Coeff * dx   //arrow start coords
ay0 = y0 + Coeff * dy
ax1 = x1 - Coeff * dx   //arrow end
ay1 = y1 - Coeff * dy

That's all.

这篇关于在D3中从圆计算中优化路径距离的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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