2014-08-31 80 views
1

我有一个d3网络,点通过线连接。我想用弯曲的SVG路径替换线条。我忘记了计算控制点坐标的算术。有谁知道如何做到这一点?d3.js:如何在网络可视化中将直线转换为曲线路径?

例如,看看下面的图像:

Example diagram of spline math

存在着点A和B.我已经他们目前由线L.我想以曲线,C至l替换连接。要做到这一点,我需要找到一条垂直于线L中点的长度为M(长度设为L的百分比)的线作为样条线C的控制点。然后,我需要定义一个SVG路径来定义C.

我该如何在d3中使用SVG来做到这一点?我很久以前就在Raphael/SVG做过这个,但数学逃避了我。我不确定它在D3中是如何完成的。

+0

第二部分无法帮助您,但我可以告诉您如何获得中点和偏移量,如果这很有用。 – dbc 2014-08-31 20:11:09

+1

如果你没有绑定到d3/svg,我会检查sigma.js,一个图形可视化库。它具有对曲线边缘的内置支持...(defaultEdgeType:'curve') – 2014-08-31 22:00:25

+2

“我已经忘记了计算控制点坐标的算术。”真?你如何提醒自己它是如何工作的,而不是要求我们为你做你的工作? – 2014-09-01 07:58:54

回答

5

为了让别人清楚,我们所说的是二次贝塞尔曲线。这给你一个控制点两点之间的平滑曲线。

的基本方法是:

  1. 找到你的AB中点,称之为J.
  2. 做一些三角函数找到的线段M的结束点,称之为ķ
  3. 使用SVG Q或T路径命令绘制二次贝塞尔曲线,从A开始,到B,控制点K.(注意,这看起来不像你的图,但可以通过改变长度M)。

enter image description here

这里是一个JavaScript函数返回的路径,你需要:

function draw_curve(Ax, Ay, Bx, By, M) { 

    // Find midpoint J 
    var Jx = Ax + (Bx - Ax)/2 
    var Jy = Ay + (By - Ay)/2 

    // We need a and b to find theta, and we need to know the sign of each to make sure that the orientation is correct. 
    var a = Bx - Ax 
    var asign = (a < 0 ? -1 : 1) 
    var b = By - Ay 
    var bsign = (b < 0 ? -1 : 1) 
    var theta = Math.atan(b/a) 

    // Find the point that's perpendicular to J on side 
    var costheta = asign * Math.cos(theta) 
    var sintheta = asign * Math.sin(theta) 

    // Find c and d 
    var c = M * sintheta 
    var d = M * costheta 

    // Use c and d to find Kx and Ky 
    var Kx = Jx - c 
    var Ky = Jy + d 

    return "M" + Ax + "," + Ay + 
      "Q" + Kx + "," + Ky + 
      " " + Bx + "," + By 
} 

您可以在this jsfiddle行动看到这一点。

编辑:如果一个二次曲线不适合,你可以很容易地调整函数做立方贝塞尔或弧段。