close edges

Hello,

I'm trying to find a way to spatially separate edges from each other in
cases where two nodes are connected by many edges. This is done by
default but I'd like them to be even more spread out so that I can put
readable text on each edge. I've a feeling this can be accomplished by
edge_control_points but can't figure out how to specify appropriate
bézier control points.
Any hints would be greatly appreciated !

Best,
-bertrand

Hi Bertrand,

As you correctly guessed you'll need to manually control the Bezier spline
for each edge.

Each edge can be composed of several Bezier segment. Each segment is
controlled by two intermediate control points (x1, y1), (x2, y2) and the
final point (x3, y3). All these points are specified as floats on a [0, 1]
scale where (0, 0) is the position of the source vertex and (1, 0) is the
position of the target vertex. What you'll need is an edge property map of
type vector<double> and each spline segment will be specified by 6
consecutive floats x1, y1, x2, y2, x3, y3 in this array. To get an intuition
about Bezier splines, take a look at https://vimeo.com/106757336

One subtlety that took me a while to figure out is that it looks like the
first two floats in this array should not be the coordinate of the first
control point of the first spline segment, but the initial point wherefrom
the total spline should start start, namely (0, 0) in most cases. This is
not specified in the documentation and I believe it comes from the way
splines segments are incrementally passed to the cairo backend.

Here's an example in IPython notebook

%matplotlib inline
import graph_tool.all as gt

foo = gt.Graph()
newe = foo.add_edge(0, 1)
foo.add_vertex(n=4)
foopos = foo.new_vertex_property('vector<double>')
ctlpts = foo.new_edge_property('vector<double>')
foopos = gt.random_layout(foo)
ctlpts[newe] = [0.0, 0.0,
                      0.2, -0.5,
                      0.3, 0.5,
                      0.5, 0.0,
                      0.7, -0.5,
                      0.8, 0.5,
                      1.0, 0.0]
gt.graph_draw(foo, pos=foopos, edge_control_points=ctlpts, vertex_size=10,
inline=True)

In this case, the edge connecting vertices 0 and 1 is composed of two
splines segments given by

Initial point: (0.0, 0.0)
Segment 1 control point 1: (0.2, -0.5)
Segment 1 control point 2: (0.3, 0.5)
Segment 1 end point: (0.5, 0.0)
Segment 2 control point 1: (0.7, -0.5)
Segment 2 control point 2: (0.8, 0.5)
Segment 2 end point: (1.0, 0.0)

Segment 1 therefore ends half-way (x=0.5) and in line (y=0.0) between the
two vertices.
Because of the way cairo takes splines segment, the end point of a segment
serves as the initial point of the next segment so you don't have to specify
it again.

To actually answer your question, I guess you could iterate the control
point property map and stretch the y coordinate of all control points using
a scale factor.

Philippe