1

背景

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"

如果样条具有点(n = 1 (mod 3)),则这些点对应于从到p1 p2 p3 ... pn的三次 B 样条的控制点。如果给定,它接触边缘的一个节点,箭头从到。如果没有给出,触摸一个节点。同样对于和。p1pnstartpp1startpstartpp1pnendp

所以分解上面的字符串,

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中绘制的样条曲线?

4

1 回答 1

1

原来我在想这个。

如果将e(endpoint) 移动到点数组的末尾,则可以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))
于 2018-12-26T17:12:03.450 回答