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
2e0b08d3
Commit
2e0b08d3
authored
Dec 22, 2012
by
Tiago Peixoto
Browse files
Implement "pie" (i.e. pie chart) vertex shape
parent
d284760a
Changes
2
Hide whitespace changes
Inline
Side-by-side
src/graph/draw/graph_cairo_draw.cc
View file @
2e0b08d3
...
...
@@ -63,7 +63,9 @@ enum vertex_attr_t {
VERTEX_FONT_SLANT
,
VERTEX_FONT_WEIGHT
,
VERTEX_FONT_SIZE
,
VERTEX_SURFACE
VERTEX_SURFACE
,
VERTEX_PIE_FRACTIONS
,
VERTEX_PIE_COLORS
};
enum
edge_attr_t
{
...
...
@@ -92,7 +94,8 @@ enum vertex_shape_t {
SHAPE_DOUBLE_PENTAGON
,
SHAPE_DOUBLE_HEXAGON
,
SHAPE_DOUBLE_HEPTAGON
,
SHAPE_DOUBLE_OCTAGON
SHAPE_DOUBLE_OCTAGON
,
SHAPE_PIE
};
enum
edge_marker_t
{
...
...
@@ -108,7 +111,7 @@ typedef pair<double, double> pos_t;
typedef
tuple
<
double
,
double
,
double
,
double
>
color_t
;
typedef
tr1
::
unordered_map
<
int
,
boost
::
any
>
attrs_t
;
typedef
mpl
::
map2
5
<
typedef
mpl
::
map2
7
<
mpl
::
pair
<
mpl
::
int_
<
VERTEX_SHAPE
>
,
vertex_shape_t
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_COLOR
>
,
color_t
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_FILL_COLOR
>
,
color_t
>
,
...
...
@@ -125,6 +128,8 @@ typedef mpl::map25<
mpl
::
pair
<
mpl
::
int_
<
VERTEX_FONT_WEIGHT
>
,
int32_t
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_FONT_SIZE
>
,
double
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_SURFACE
>
,
python
::
object
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_PIE_FRACTIONS
>
,
vector
<
double
>
>
,
mpl
::
pair
<
mpl
::
int_
<
VERTEX_PIE_COLORS
>
,
vector
<
color_t
>
>
,
mpl
::
pair
<
mpl
::
int_
<
EDGE_COLOR
>
,
color_t
>
,
mpl
::
pair
<
mpl
::
int_
<
EDGE_PENWIDTH
>
,
double
>
,
mpl
::
pair
<
mpl
::
int_
<
EDGE_START_MARKER
>
,
edge_marker_t
>
,
...
...
@@ -389,6 +394,37 @@ double get_polygon_anchor(size_t N, double radius, double angle)
return
radius
*
cos
(
M_PI
/
N
)
/
cos
(
theta
);
}
void
draw_pie
(
double
radius
,
const
vector
<
double
>&
f
,
const
vector
<
color_t
>&
colors
,
Cairo
::
Context
&
cr
)
{
if
(
colors
.
empty
())
throw
ValueException
(
"No pie colors!"
);
double
s
=
0
;
for
(
size_t
i
=
0
;
i
<
f
.
size
();
++
i
)
s
+=
f
[
i
];
double
last
=
0
;
double
pos
=
0
;
cr
.
save
();
cr
.
begin_new_path
();
for
(
size_t
i
=
0
;
i
<
f
.
size
();
++
i
)
{
pos
+=
f
[
i
];
double
angle
=
(
2
*
pos
*
M_PI
)
/
s
;
cr
.
move_to
(
0
,
0
);
cr
.
arc
(
0
,
0
,
radius
,
last
,
angle
);
last
=
angle
;
size_t
j
=
i
%
colors
.
size
();
cr
.
set_source_rgba
(
get
<
0
>
(
colors
[
j
]),
get
<
1
>
(
colors
[
j
]),
get
<
2
>
(
colors
[
j
]),
get
<
3
>
(
colors
[
j
]));
cr
.
fill
();
}
cr
.
restore
();
}
void
move_radially
(
pos_t
&
pos
,
const
pos_t
&
origin
,
double
dr
)
{
double
angle
=
atan2
(
pos
.
second
-
origin
.
second
,
...
...
@@ -499,6 +535,7 @@ public:
break
;
case
SHAPE_CIRCLE
:
case
SHAPE_DOUBLE_CIRCLE
:
case
SHAPE_PIE
:
dr
=
r
;
break
;
default:
...
...
@@ -584,6 +621,23 @@ public:
cr
.
restore
();
}
break
;
case
SHAPE_PIE
:
{
if
(
!
outline
)
{
vector
<
double
>
f
=
_attrs
.
template
get
<
vector
<
double
>
>
(
VERTEX_PIE_FRACTIONS
);
vector
<
color_t
>
fcolors
=
_attrs
.
template
get
<
vector
<
color_t
>
>
(
VERTEX_PIE_COLORS
);
draw_pie
(
size
/
2
+
pw
/
2
,
f
,
fcolors
,
cr
);
}
else
{
cr
.
save
();
cr
.
arc
(
0
,
0
,
size
/
2.
,
0
,
2
*
M_PI
);
cr
.
close_path
();
cr
.
restore
();
}
}
break
;
case
SHAPE_TRIANGLE
:
case
SHAPE_SQUARE
:
case
SHAPE_PENTAGON
:
...
...
@@ -621,7 +675,7 @@ public:
python
::
object
osrc
=
_attrs
.
template
get
<
python
::
object
>(
VERTEX_SURFACE
);
if
(
osrc
==
python
::
object
())
{
if
(
!
outline
)
if
(
!
outline
&&
shape
!=
SHAPE_PIE
)
{
fillcolor
=
_attrs
.
template
get
<
color_t
>(
VERTEX_FILL_COLOR
);
cr
.
set_source_rgba
(
get
<
0
>
(
fillcolor
),
get
<
1
>
(
fillcolor
),
...
...
@@ -781,13 +835,13 @@ public:
marker_size
*=
get_user_dist
(
cr
);
if
(
start_marker
==
MARKER_SHAPE_NONE
&&
!
sloppy
)
move_radially
(
pos_begin
_c
,
_s
.
get_pos
()
,
-
_s
.
get_size
(
cr
)
/
2
)
;
pos_begin
=
_s
.
get_pos
();
else
if
((
start_marker
!=
MARKER_SHAPE_NONE
&&
start_marker
!=
MARKER_SHAPE_BAR
))
move_radially
(
pos_begin_c
,
_s
.
get_pos
(),
marker_size
/
2
);
if
(
end_marker
==
MARKER_SHAPE_NONE
&&
!
sloppy
)
move_radially
(
pos_end
_c
,
_t
.
get_pos
()
,
-
marker_size
)
;
pos_end
=
_t
.
get_pos
();
else
if
((
end_marker
!=
MARKER_SHAPE_NONE
&&
end_marker
!=
MARKER_SHAPE_BAR
))
move_radially
(
pos_end_c
,
_t
.
get_pos
(),
-
_t
.
get
_size
(
cr
)
/
2
);
move_radially
(
pos_end_c
,
_t
.
get_pos
(),
marker
_size
/
2
);
color_t
color
=
_attrs
.
template
get
<
color_t
>(
EDGE_COLOR
);
double
pw
;
...
...
@@ -1413,6 +1467,50 @@ struct color_from_list
}
};
struct
color_vector_from_list
{
color_vector_from_list
()
{
converter
::
registry
::
push_back
(
&
convertible
,
&
construct
,
boost
::
python
::
type_id
<
vector
<
color_t
>
>
());
}
static
void
*
convertible
(
PyObject
*
obj_ptr
)
{
handle
<>
x
(
borrowed
(
obj_ptr
));
object
o
(
x
);
size_t
N
=
len
(
o
);
if
(
N
<
4
)
return
0
;
return
obj_ptr
;
}
static
void
construct
(
PyObject
*
obj_ptr
,
converter
::
rvalue_from_python_stage1_data
*
data
)
{
handle
<>
x
(
borrowed
(
obj_ptr
));
object
o
(
x
);
vector
<
color_t
>
c
;
assert
(
len
(
o
)
>=
4
);
for
(
int
i
=
0
;
i
<
len
(
o
)
/
4
;
++
i
)
{
c
.
push_back
(
color_t
());
get
<
0
>
(
c
[
i
])
=
extract
<
double
>
(
o
[
0
+
4
*
i
]);
get
<
1
>
(
c
[
i
])
=
extract
<
double
>
(
o
[
1
+
4
*
i
]);
get
<
2
>
(
c
[
i
])
=
extract
<
double
>
(
o
[
2
+
4
*
i
]);
get
<
3
>
(
c
[
i
])
=
extract
<
double
>
(
o
[
3
+
4
*
i
]);
}
void
*
storage
=
(
(
boost
::
python
::
converter
::
rvalue_from_python_storage
<
color_t
>*
)
data
)
->
storage
.
bytes
;
new
(
storage
)
vector
<
color_t
>
(
c
);
data
->
convertible
=
storage
;
}
};
template
<
class
Enum
>
struct
enum_from_int
{
...
...
@@ -1470,7 +1568,9 @@ BOOST_PYTHON_MODULE(libgraph_tool_draw)
.
value
(
"font_slant"
,
VERTEX_FONT_SLANT
)
.
value
(
"font_weight"
,
VERTEX_FONT_WEIGHT
)
.
value
(
"font_size"
,
VERTEX_FONT_SIZE
)
.
value
(
"surface"
,
VERTEX_SURFACE
);
.
value
(
"surface"
,
VERTEX_SURFACE
)
.
value
(
"pie_fractions"
,
VERTEX_PIE_FRACTIONS
)
.
value
(
"pie_colors"
,
VERTEX_PIE_COLORS
);
enum_
<
edge_attr_t
>
(
"edge_attrs"
)
.
value
(
"color"
,
EDGE_COLOR
)
...
...
@@ -1497,7 +1597,8 @@ BOOST_PYTHON_MODULE(libgraph_tool_draw)
.
value
(
"double_pentagon"
,
SHAPE_DOUBLE_PENTAGON
)
.
value
(
"double_hexagon"
,
SHAPE_DOUBLE_HEXAGON
)
.
value
(
"double_heptagon"
,
SHAPE_DOUBLE_HEPTAGON
)
.
value
(
"double_octagon"
,
SHAPE_DOUBLE_OCTAGON
);
.
value
(
"double_octagon"
,
SHAPE_DOUBLE_OCTAGON
)
.
value
(
"pie"
,
SHAPE_PIE
);
enum_
<
edge_marker_t
>
(
"edge_marker"
)
.
value
(
"none"
,
MARKER_SHAPE_NONE
)
...
...
@@ -1508,6 +1609,7 @@ BOOST_PYTHON_MODULE(libgraph_tool_draw)
.
value
(
"bar"
,
MARKER_SHAPE_BAR
);
color_from_list
();
color_vector_from_list
();
enum_from_int
<
vertex_attr_t
>
();
enum_from_int
<
edge_attr_t
>
();
enum_from_int
<
vertex_shape_t
>
();
...
...
src/graph_tool/draw/cairo_draw.py
View file @
2e0b08d3
...
...
@@ -19,6 +19,9 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from
__future__
import
division
,
absolute_import
,
print_function
import
sys
if
sys
.
version_info
<
(
3
,):
range
=
xrange
import
os
import
warnings
...
...
@@ -34,6 +37,7 @@ except ImportError:
try
:
import
matplotlib.cm
import
matplotlib.colors
from
matplotlib.cbook
import
flatten
except
ImportError
:
msg
=
"Error importing matplotlib module. Graph drawing will not work."
warnings
.
filterwarnings
(
"always"
,
msg
,
ImportWarning
)
...
...
@@ -82,7 +86,9 @@ _vdefaults = {
"font_slant"
:
cairo
.
FONT_SLANT_NORMAL
,
"font_weight"
:
cairo
.
FONT_WEIGHT_NORMAL
,
"font_size"
:
12.
,
"surface"
:
None
"surface"
:
None
,
"pie_fractions"
:
[
0.75
,
0.25
],
"pie_colors"
:
(
'b'
,
'g'
,
'r'
,
'c'
,
'm'
,
'y'
,
'k'
)
}
_edefaults
=
{
...
...
@@ -186,6 +192,37 @@ def _convert(attr, val, cmap):
edge_attrs
.
end_marker
]:
return
shape_from_prop
(
val
,
edge_marker
)
if
attr
in
[
vertex_attrs
.
pie_colors
]:
if
isinstance
(
val
,
PropertyMap
):
if
val
.
value_type
()
in
[
"vector<double>"
,
"vector<long double>"
]:
return
val
if
val
.
value_type
()
==
"vector<string>"
:
g
=
val
.
get_graph
()
new_val
=
g
.
new_vertex_property
(
"vector<double>"
)
for
v
in
g
.
vertices
():
new_val
[
v
]
=
[
matplotlib
.
colors
.
ColorConverter
().
to_rgba
(
x
)
for
x
in
val
[
v
]]
return
new_val
if
val
.
value_type
()
==
"python::object"
:
try
:
g
=
val
.
get_graph
()
new_val
=
g
.
new_vertex_property
(
"vector<double>"
)
for
v
in
g
.
vertices
():
try
:
new_val
[
v
]
=
[
float
(
x
)
for
x
in
flatten
(
val
[
v
])]
except
ValueError
:
new_val
[
v
]
=
flatten
([
matplotlib
.
colors
.
ColorConverter
().
to_rgba
(
x
)
for
x
in
val
[
v
]])
return
new_val
except
ValueError
:
pass
else
:
try
:
return
[
float
(
x
)
for
x
in
flatten
(
val
)]
except
ValueError
:
try
:
new_val
=
flatten
(
matplotlib
.
colors
.
ColorConverter
().
to_rgba
(
x
)
for
x
in
val
)
return
list
(
new_val
)
except
ValueError
:
pass
if
attr
in
[
vertex_attrs
.
color
,
vertex_attrs
.
fill_color
,
vertex_attrs
.
text_color
,
vertex_attrs
.
halo_color
,
edge_attrs
.
color
]:
...
...
@@ -409,7 +446,7 @@ def cairo_draw(g, pos, cr, vprops=None, eprops=None, vorder=None, eorder=None,
def
color_contrast
(
color
):
c
=
np
.
asarray
(
color
)
for
i
in
x
range
(
3
):
for
i
in
range
(
3
):
if
color
[
i
]
>=
0.5
:
c
[
i
]
=
0
else
:
...
...
@@ -676,7 +713,7 @@ def graph_draw(g, pos=None, vprops=None, eprops=None, vorder=None, eorder=None,
return
interactive_window
(
g
,
pos
,
vprops
,
eprops
,
vorder
,
eorder
,
nodesfirst
,
**
kwargs
)
else
:
out
,
auto_fmt
=
open_file
(
output
,
mode
=
"w"
)
out
,
auto_fmt
=
open_file
(
output
,
mode
=
"w
b
"
)
if
fmt
==
"auto"
:
fmt
=
auto_fmt
...
...
Write
Preview
Supports
Markdown
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