如何在 d3 中绘制 graphviz 样条曲线
How to draw a graphviz spline in d3
背景
graphviz 非常适合布置图表。当我用 graphviz“点”布局我的图形时,它会生成一个文件,其中的节点和边缘标有位置。例如。一条边:
"a" -> "b" [pos="e,152.13,411.67 91.566,463.4 108.12,449.26 127.94,432.34 144.37,418.3"];
spline = (endp)? (startp)? point (triple)+
and triple = point point point
and endp = "e,%f,%f"
and startp = "s,%f,%f"
If a spline has points p1 p2 p3 ... pn
, (n = 1 (mod 3)), the points correspond to the control points of a cubic B-spline from p1
to pn
. If startp
is given, it touches one node of the edge, and the arrowhead goes from p1
to startp
. If startp
is not given, p1
touches a node. Similarly for pn
and endp
.
所以分解上面的字符串,
e,152.13,411.67 // This is an endpoint.
91.566,463.4 // p1
108.12,449.26 // the following three points are control points for a cubic b-spline
127.94,432.34
144.37,418.3
问题
我想通过d3画这条样条线。 d3 似乎 cubic b-splines 具有以下签名:
d3.curveBasis(context)
Produces a cubic basis spline using the specified control points. The first and last points are triplicated such that the spline starts at the first point and ends at the last point, and is tangent to the line between the first and second points, and to the line between the penultimate and last points.
那么我该如何取字符串
[pos="e,152.13,411.67 91.566,463.4 108.12,449.26 127.94,432.34 144.37,418.3"];
然后绘制 graphviz 在 d3 中绘制的样条线?
原来是我想多了。
如果将 e
(端点)移动到点数组的末尾,d3.curveBasis()
会完美地呈现它。
# G is a networkx graph and A is a pygraphviz graph
for e in G.edges():
points = A.get_edge(e[0], e[1]).attr["pos"].lstrip('e,').split(' ')
points.append(points.pop(0))
G.edges[e[0], e[1]].update({'points': [{'x':float(p.split(',')[0]), 'y':float(p.split(',')[1])} for p in points]})
之后:
var lineGenerator = d3.line().y(d => d.y).x(d => d.x).curve(d3.curveBasis);
link.enter()
.append('path')
.attr('d', l => lineGenerator(l.points))
背景
graphviz 非常适合布置图表。当我用 graphviz“点”布局我的图形时,它会生成一个文件,其中的节点和边缘标有位置。例如。一条边:
"a" -> "b" [pos="e,152.13,411.67 91.566,463.4 108.12,449.26 127.94,432.34 144.37,418.3"];
spline = (endp)? (startp)? point (triple)+ and triple = point point point and endp = "e,%f,%f" and startp = "s,%f,%f"
If a spline has points
p1 p2 p3 ... pn
, (n = 1 (mod 3)), the points correspond to the control points of a cubic B-spline fromp1
topn
. Ifstartp
is given, it touches one node of the edge, and the arrowhead goes fromp1
tostartp
. Ifstartp
is not given,p1
touches a node. Similarly forpn
andendp
.
所以分解上面的字符串,
e,152.13,411.67 // This is an endpoint.
91.566,463.4 // p1
108.12,449.26 // the following three points are control points for a cubic b-spline
127.94,432.34
144.37,418.3
问题
我想通过d3画这条样条线。 d3 似乎 cubic b-splines 具有以下签名:
d3.curveBasis(context)
Produces a cubic basis spline using the specified control points. The first and last points are triplicated such that the spline starts at the first point and ends at the last point, and is tangent to the line between the first and second points, and to the line between the penultimate and last points.
那么我该如何取字符串
[pos="e,152.13,411.67 91.566,463.4 108.12,449.26 127.94,432.34 144.37,418.3"];
然后绘制 graphviz 在 d3 中绘制的样条线?
原来是我想多了。
如果将 e
(端点)移动到点数组的末尾,d3.curveBasis()
会完美地呈现它。
# G is a networkx graph and A is a pygraphviz graph
for e in G.edges():
points = A.get_edge(e[0], e[1]).attr["pos"].lstrip('e,').split(' ')
points.append(points.pop(0))
G.edges[e[0], e[1]].update({'points': [{'x':float(p.split(',')[0]), 'y':float(p.split(',')[1])} for p in points]})
之后:
var lineGenerator = d3.line().y(d => d.y).x(d => d.x).curve(d3.curveBasis);
link.enter()
.append('path')
.attr('d', l => lineGenerator(l.points))