Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
Tiago Peixoto
graph-tool
Commits
6cb45f26
Commit
6cb45f26
authored
Sep 19, 2013
by
Tiago Peixoto
Browse files
Implement get_hierarchy_control_points()
parent
ed228c88
Changes
6
Hide whitespace changes
Inline
Side-by-side
doc/draw.rst
View file @
6cb45f26
...
...
@@ -16,6 +16,7 @@
.. autofunction:: graph_draw
.. autofunction:: graphviz_draw
.. autofunction:: prop_to_size
.. autofunction:: get_hierarchy_control_points
Low-level graph drawing
...
...
src/graph/draw/Makefile.am
View file @
6cb45f26
...
...
@@ -15,6 +15,7 @@ libgraph_tool_draw_la_LIBADD = $(MOD_LIBADD)
libgraph_tool_draw_la_LDFLAGS
=
$(MOD_LDFLAGS)
$(CAIROMM_LIBS)
libgraph_tool_draw_la_SOURCES
=
\
graph_cairo_draw.cc
graph_cairo_draw.cc
\
graph_tree_cts.cc
libgraph_tool_draw_la_include_HEADERS
=
src/graph/draw/graph_cairo_draw.cc
View file @
6cb45f26
...
...
@@ -1656,6 +1656,8 @@ struct enum_from_int
}
};
void
get_cts
(
GraphInterface
&
gi
,
GraphInterface
&
tgi
,
boost
::
any
otpos
,
double
beta
,
boost
::
any
octs
);
BOOST_PYTHON_MODULE
(
libgraph_tool_draw
)
{
...
...
@@ -1738,6 +1740,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_draw)
enum_from_int
<
edge_attr_t
>
();
enum_from_int
<
vertex_shape_t
>
();
enum_from_int
<
edge_marker_t
>
();
def
(
"get_cts"
,
&
get_cts
);
}
#else
...
...
src/graph/draw/graph_tree_cts.cc
0 → 100644
View file @
6cb45f26
// graph-tool -- a general graph modification and manipulation thingy
//
// Copyright (C) 2006-2013 Tiago de Paula Peixoto <tiago@skewed.de>
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 3
// of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "graph.hh"
#include "graph_filtering.hh"
#include "graph_selectors.hh"
#include "graph_properties.hh"
#include <cmath>
using
namespace
std
;
using
namespace
boost
;
using
namespace
graph_tool
;
typedef
pair
<
double
,
double
>
point_t
;
point_t
interpolate
(
const
point_t
&
p1
,
const
point_t
&
p2
,
double
r
=
0.5
)
{
point_t
ret
;
ret
.
first
=
(
1
-
r
)
*
p1
.
first
+
p2
.
first
*
r
;
ret
.
second
=
(
1
-
r
)
*
p1
.
second
+
p2
.
second
*
r
;
return
ret
;
}
void
to_bezier
(
const
vector
<
point_t
>
&
x
,
vector
<
point_t
>&
ncp
)
{
vector
<
point_t
>
cp
(
x
.
size
()
+
6
);
for
(
size_t
i
=
0
;
i
<
3
;
++
i
)
cp
[
i
]
=
x
[
0
];
for
(
size_t
i
=
0
;
i
<
x
.
size
();
++
i
)
cp
[
i
+
3
]
=
x
[
i
];
for
(
size_t
i
=
cp
.
size
()
-
3
;
i
<
cp
.
size
();
++
i
)
cp
[
i
]
=
x
.
back
();
vector
<
point_t
>
one_thirds
(
cp
.
size
()
-
1
);
vector
<
point_t
>
two_thirds
(
cp
.
size
()
-
1
);
for
(
size_t
i
=
0
;
i
<
cp
.
size
()
-
1
;
++
i
)
{
const
point_t
&
p1
=
cp
[
i
];
const
point_t
&
p2
=
cp
[
i
+
1
];
one_thirds
[
i
]
=
interpolate
(
p1
,
p2
,
1.
/
3
);
two_thirds
[
i
]
=
interpolate
(
p2
,
p1
,
1.
/
3
);
}
ncp
.
resize
((
cp
.
size
()
-
3
)
*
3
);
for
(
size_t
i
=
0
;
i
<
cp
.
size
()
-
3
;
++
i
)
{
size_t
pos
=
i
*
3
;
ncp
[
pos
]
=
one_thirds
[
i
+
1
];
ncp
[
pos
+
1
]
=
two_thirds
[
i
+
1
];
ncp
[
pos
+
2
]
=
interpolate
(
two_thirds
[
i
+
1
],
one_thirds
[
i
+
2
]);
}
}
void
transform
(
vector
<
point_t
>&
cp
)
{
point_t
origin
=
cp
[
0
];
for
(
size_t
i
=
0
;
i
<
cp
.
size
();
++
i
)
{
cp
[
i
].
first
-=
origin
.
first
;
cp
[
i
].
second
-=
origin
.
second
;
}
double
t
=
atan2
(
cp
.
back
().
second
-
cp
.
front
().
second
,
cp
.
back
().
first
-
cp
.
front
().
first
);
for
(
size_t
i
=
0
;
i
<
cp
.
size
();
++
i
)
{
double
x
=
cp
[
i
].
first
;
double
y
=
cp
[
i
].
second
;
cp
[
i
].
first
=
cos
(
t
)
*
x
+
sin
(
t
)
*
y
;
cp
[
i
].
second
=
-
sin
(
t
)
*
x
+
cos
(
t
)
*
y
;
}
point_t
d
;
d
.
first
=
cp
.
back
().
first
-
cp
.
front
().
first
;
d
.
second
=
cp
.
back
().
second
-
cp
.
front
().
second
;
double
r
=
sqrt
(
d
.
first
*
d
.
first
+
d
.
second
*
d
.
second
);
for
(
size_t
i
=
0
;
i
<
cp
.
size
();
++
i
)
cp
[
i
].
first
/=
r
;
}
template
<
class
PosProp
>
void
get_control_points
(
vector
<
size_t
>&
path
,
PosProp
pos
,
double
beta
,
vector
<
point_t
>&
ncp
)
{
size_t
L
=
path
.
size
();
vector
<
point_t
>
cp
(
L
);
for
(
size_t
i
=
0
;
i
<
L
;
++
i
)
cp
[
i
]
=
make_pair
(
double
(
pos
[
path
[
i
]][
0
]),
double
(
pos
[
path
[
i
]][
1
]));
ncp
.
resize
(
L
);
for
(
size_t
i
=
0
;
i
<
L
;
++
i
)
{
ncp
[
i
].
first
=
beta
*
cp
[
i
].
first
+
(
1
-
beta
)
*
(
cp
[
0
].
first
+
(
cp
.
back
().
first
-
cp
[
0
].
first
)
*
i
/
(
L
-
1.
));
ncp
[
i
].
second
=
beta
*
cp
[
i
].
second
+
(
1
-
beta
)
*
(
cp
[
0
].
second
+
(
cp
.
back
().
second
-
cp
[
0
].
second
)
*
i
/
(
L
-
1.
));
}
}
template
<
class
Graph
>
void
tree_path
(
Graph
&
g
,
size_t
s
,
size_t
t
,
vector
<
size_t
>&
path
)
{
vector
<
size_t
>
s_root
;
vector
<
size_t
>
t_root
;
s_root
.
push_back
(
s
);
t_root
.
push_back
(
t
);
size_t
v
=
s
;
size_t
u
=
t
;
while
(
v
!=
u
)
{
typename
graph_traits
<
Graph
>::
in_edge_iterator
e
,
e_end
;
tie
(
e
,
e_end
)
=
in_edges
(
v
,
g
);
if
(
e
==
e_end
)
throw
GraphException
(
"Invalid hierarchical tree: No path from source to target."
);
v
=
source
(
*
e
,
g
);
s_root
.
push_back
(
v
);
tie
(
e
,
e_end
)
=
in_edges
(
u
,
g
);
if
(
e
==
e_end
)
throw
GraphException
(
"Invalid hierarchical tree: No path from source to target."
);
u
=
source
(
*
e
,
g
);
if
(
u
!=
v
)
t_root
.
push_back
(
u
);
}
path
=
s_root
;
for
(
typeof
(
t_root
.
rbegin
())
iter
=
t_root
.
rbegin
();
iter
!=
t_root
.
rend
();
++
iter
)
path
.
push_back
(
*
iter
);
}
template
<
class
T
>
void
pack
(
vector
<
point_t
>&
cp
,
vector
<
T
>&
ncp
)
{
ncp
.
resize
(
cp
.
size
()
*
2
);
for
(
size_t
i
=
0
;
i
<
cp
.
size
();
++
i
)
{
ncp
[
2
*
i
]
=
cp
[
i
].
first
;
ncp
[
2
*
i
+
1
]
=
cp
[
i
].
second
;
}
}
struct
do_get_cts
{
template
<
class
Graph
,
class
Tree
,
class
PosProp
,
class
CMap
>
void
operator
()(
Graph
&
g
,
Tree
*
t
,
PosProp
tpos
,
double
beta
,
CMap
cts
)
const
{
vector
<
size_t
>
path
;
vector
<
point_t
>
cp
;
vector
<
point_t
>
ncp
;
typename
graph_traits
<
Graph
>::
edge_iterator
e
,
e_end
;
for
(
tie
(
e
,
e_end
)
=
edges
(
g
);
e
!=
e_end
;
++
e
)
{
typename
graph_traits
<
Graph
>::
vertex_descriptor
u
,
v
;
u
=
source
(
*
e
,
g
);
v
=
target
(
*
e
,
g
);
if
(
u
==
v
)
continue
;
path
.
clear
();
tree_path
(
*
t
,
u
,
v
,
path
);
cp
.
clear
();
get_control_points
(
path
,
tpos
,
beta
,
cp
);
ncp
.
clear
();
to_bezier
(
cp
,
ncp
);
transform
(
ncp
);
pack
(
ncp
,
cts
[
*
e
]);
}
}
};
struct
get_pointers
{
template
<
class
List
>
struct
apply
{
typedef
typename
mpl
::
transform
<
List
,
mpl
::
quote1
<
add_pointer
>
>::
type
type
;
};
};
void
get_cts
(
GraphInterface
&
gi
,
GraphInterface
&
tgi
,
boost
::
any
otpos
,
double
beta
,
boost
::
any
octs
)
{
typedef
property_map_type
::
apply
<
vector
<
double
>
,
GraphInterface
::
edge_index_map_t
>::
type
eprop_t
;
eprop_t
cts
=
boost
::
any_cast
<
eprop_t
>
(
octs
);
run_action
<
graph_tool
::
detail
::
always_directed
,
mpl
::
true_
>
()
(
gi
,
bind
<
void
>
(
do_get_cts
(),
_1
,
_2
,
_3
,
beta
,
cts
),
get_pointers
::
apply
<
graph_tool
::
detail
::
always_directed
>::
type
(),
vertex_scalar_vector_properties
())
(
tgi
.
GetGraphView
(),
otpos
);
}
src/graph_tool/draw/__init__.py
View file @
6cb45f26
...
...
@@ -35,7 +35,7 @@ Layout algorithms
fruchterman_reingold_layout
arf_layout
random_layout
get_hierarchy_control_points
Graph drawing
=============
...
...
@@ -82,7 +82,7 @@ dl_import("from . import libgraph_tool_layout")
__all__
=
[
"graph_draw"
,
"graphviz_draw"
,
"fruchterman_reingold_layout"
,
"arf_layout"
,
"sfdp_layout"
,
"random_layout"
,
"cairo_draw"
,
"prop_to_size"
]
"cairo_draw"
,
"prop_to_size"
,
"get_hierarchy_control_points"
]
def
random_layout
(
g
,
shape
=
None
,
pos
=
None
,
dim
=
2
):
...
...
@@ -700,7 +700,7 @@ def sfdp_layout(g, vweight=None, eweight=None, pin=None, groups=None, C=0.2,
return
pos
try
:
from
.cairo_draw
import
graph_draw
,
cairo_draw
from
.cairo_draw
import
graph_draw
,
cairo_draw
,
get_hierarchy_control_points
except
ImportError
:
pass
...
...
src/graph_tool/draw/cairo_draw.py
View file @
6cb45f26
...
...
@@ -1009,6 +1009,63 @@ def transform_scale(M, scale):
scale
/
np
.
sqrt
(
2
))
return
np
.
sqrt
(
p
[
0
]
**
2
+
p
[
1
]
**
2
)
def
get_hierarchy_control_points
(
g
,
t
,
tpos
,
beta
=
0.8
):
r
"""Return the Bézier spline control points for the edges in ``g``, given
the hierarchical structure encoded in graph `t`.
Parameters
----------
g : :class:`~graph_tool.Graph`
Graph to be drawn.
t : :class:`~graph_tool.Graph`
Directed graph containing the hierarchy of ``g``. It must be a directed
tree with a single root. The direction of the edges point from the root
to the leaves, and the vertices in ``t`` with index in the range
:math:`[0, N-1]`, with `:math:`N` being the number of vertices in ``g``,
must correspond to the respective vertex in ``g``.
tpos : :class:`~graph_tool.PropertyMap`
Vector-valued vertex property map containing the x and y coordinates of
the vertices in graph ``t``.
beta : ``float`` (optional, default: ``0.8``)
Edge bundling strength. For ``beta == 0`` the edges are straight lines,
and for ``beta == 1`` they strictly follow the hierarchy.
Returns
-------
ctp : :class:`~graph_tool.PropertyMap`
Vector-valued edge property map containing the Bézier spline control
points for the edges in ``g``.
Notes
-----
This is an implementation of the edge-bundling algorithm described in
[holten-hierarchical-2006]_.
Examples
--------
TODO
References
----------
.. [holten-hierarchical-2006] Holten, D. "Hierarchical Edge Bundles:
Visualization of Adjacency Relations in Hierarchical Data.", IEEE
Transactions on Visualization and Computer Graphics 12, no. 5, 741–748
(2006). :doi:`10.1109/TVCG.2006.147`
"""
cts
=
g
.
new_edge_property
(
"vector<double>"
)
u
=
GraphView
(
g
,
directed
=
True
)
tu
=
GraphView
(
t
,
directed
=
True
)
libgraph_tool_draw
.
get_cts
(
u
.
_Graph__graph
,
tu
.
_Graph__graph
,
_prop
(
"v"
,
tu
,
tpos
),
beta
,
_prop
(
"e"
,
u
,
cts
))
return
cts
#
# The functions and classes below depend on GTK
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment