背景
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"];
Graphviz样条语言如下:
spline = (endp)? (startp)? point (triple)+ and triple = point point point and endp = "e,%f,%f" and startp = "s,%f,%f"
如果样条曲线具有点
p1 p2 p3 ... pn
,(n=1(mod 3)),则这些点对应于从p1
到pn
的三次B样条曲线的控制点。如果给定startp
,则它会接触边的一个节点,箭头从p1
转到startp
。如果未给出startp
,则p1
触摸节点。对于CCD_ 9和CCD_。
所以分解上面的字符串,
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似乎具有具有以下特征的三次b样条:
d3.curveBasis(上下文)
使用指定的控制点生成三次样条曲线。第一点和最后一点是三重的,这样样条曲线从第一点开始,到最后一点结束,并与第一点和第二点之间的直线以及倒数第二点和最后点之间的线相切。
那么我如何获取字符串
[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))