Commit d864ef87 authored by Tiago Peixoto's avatar Tiago Peixoto
Browse files

Implement edge text labels in graph_draw()

parent e1fa3a90
......@@ -75,6 +75,14 @@ enum edge_attr_t {
EDGE_MARKER_SIZE,
EDGE_CONTROL_POINTS,
EDGE_DASH_STYLE,
EDGE_TEXT,
EDGE_TEXT_COLOR,
EDGE_TEXT_DISTANCE,
EDGE_TEXT_PARALLEL,
EDGE_FONT_FAMILY,
EDGE_FONT_SLANT,
EDGE_FONT_WEIGHT,
EDGE_FONT_SIZE,
EDGE_SLOPPY
};
......@@ -109,7 +117,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::map28<
typedef mpl::map36<
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>,
......@@ -137,6 +145,14 @@ typedef mpl::map28<
mpl::pair<mpl::int_<EDGE_MARKER_SIZE>, double>,
mpl::pair<mpl::int_<EDGE_CONTROL_POINTS>, vector<double> >,
mpl::pair<mpl::int_<EDGE_DASH_STYLE>, vector<double> >,
mpl::pair<mpl::int_<EDGE_TEXT>, string>,
mpl::pair<mpl::int_<EDGE_TEXT_COLOR>, color_t>,
mpl::pair<mpl::int_<EDGE_TEXT_DISTANCE>, double>,
mpl::pair<mpl::int_<EDGE_TEXT_PARALLEL>, uint8_t>,
mpl::pair<mpl::int_<EDGE_FONT_FAMILY>, string>,
mpl::pair<mpl::int_<EDGE_FONT_SLANT>, int32_t>,
mpl::pair<mpl::int_<EDGE_FONT_WEIGHT>, int32_t>,
mpl::pair<mpl::int_<EDGE_FONT_SIZE>, double>,
mpl::pair<mpl::int_<EDGE_SLOPPY>, uint8_t> >
attr_types;
......@@ -898,6 +914,54 @@ public:
cr.stroke();
}
string text = _attrs.template get<string>(EDGE_TEXT);
if (text != "")
{
cr.save();
cr.select_font_face(_attrs.template get<string>(EDGE_FONT_FAMILY),
static_cast<Cairo::FontSlant>(_attrs.template get<int32_t>(EDGE_FONT_SLANT)),
static_cast<Cairo::FontWeight>(_attrs.template get<int32_t>(EDGE_FONT_WEIGHT)));
cr.set_font_size(_attrs.template get<double>(EDGE_FONT_SIZE) *
get_user_dist(cr));
double text_dist = _attrs.template get<double>(EDGE_TEXT_DISTANCE);
text_dist *= get_user_dist(cr);
bool text_parallel = _attrs.template get<uint8_t>(EDGE_TEXT_PARALLEL);
Cairo::TextExtents extents;
cr.get_text_extents(text, extents);
pos_t origin;
origin.first = (pos_begin_c.first + pos_end_c.first) / 2;
origin.second = (pos_begin_c.second + pos_end_c.second) / 2;
cr.translate(origin.first, origin.second);
double angle = atan2(pos_end_c.second - pos_begin_c.second,
pos_end_c.first - pos_begin_c.first);
if (text_parallel)
{
if (angle > M_PI / 2)
angle -= M_PI;
if (angle < -M_PI / 2)
angle += M_PI;
}
cr.rotate(angle);
if (text_parallel)
cr.translate(0, -text_dist);
else
cr.translate(0, text_dist);
if (!text_parallel)
cr.rotate(-angle);
else
cr.translate(-extents.width / 2, 0);
color = _attrs.template get<color_t>(EDGE_TEXT_COLOR);
cr.set_source_rgba(get<0>(color), get<1>(color), get<2>(color),
get<3>(color));
cr.show_text(text);
cr.begin_new_path();
cr.restore();
}
cr.restore();
}
......@@ -1587,6 +1651,14 @@ BOOST_PYTHON_MODULE(libgraph_tool_draw)
.value("marker_size", EDGE_MARKER_SIZE)
.value("control_points", EDGE_CONTROL_POINTS)
.value("dash_style", EDGE_DASH_STYLE)
.value("text", EDGE_TEXT)
.value("text_color", EDGE_TEXT_COLOR)
.value("text_distance", EDGE_TEXT_DISTANCE)
.value("text_parallel", EDGE_TEXT_PARALLEL)
.value("font_family", EDGE_FONT_FAMILY)
.value("font_slant", EDGE_FONT_SLANT)
.value("font_weight", EDGE_FONT_WEIGHT)
.value("font_size", EDGE_FONT_SIZE)
.value("sloppy", EDGE_SLOPPY);
enum_<vertex_shape_t>("vertex_shape")
......
......@@ -101,6 +101,14 @@ _edefaults = {
"marker_size": 4.,
"control_points": [],
"dash_style": [],
"text": "",
"text_color": [0., 0., 0., 1.],
"text_distance": 5,
"text_parallel": True,
"font_family": "serif",
"font_slant": cairo.FONT_SLANT_NORMAL,
"font_weight": cairo.FONT_WEIGHT_NORMAL,
"font_size": 12.,
"sloppy": False
}
......@@ -226,7 +234,7 @@ def _convert(attr, val, cmap):
pass
if attr in [vertex_attrs.color, vertex_attrs.fill_color,
vertex_attrs.text_color, vertex_attrs.halo_color,
edge_attrs.color]:
edge_attrs.color, edge_attrs.text_color]:
if isinstance(val, list):
return val
if isinstance(val, (tuple, np.ndarray)):
......@@ -646,6 +654,24 @@ def graph_draw(g, pos=None, vprops=None, eprops=None, vorder=None, eorder=None,
| | The last value specifies an offset into the | | |
| | pattern at which the stroke begins. | | |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| text | Text to draw next to the edges. | ``str`` | ``""`` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| text_color | Color used to draw the text. | ``str`` or list of | ``[0., 0., 0., 1.]`` |
| | | ``floats`` | |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| text_distance | Distance from the edge and its text. | ``float`` or ``int`` | ``4`` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| text_parallel | If ``True`` the text will be drawn parallel to | ``bool`` | ``True`` |
| | the edges. | | |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| font_family | Font family used to draw the text. | ``str`` | ``"serif"`` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| font_slant | Font slant used to draw the text. | ``cairo.FONT_SLANT_*`` | :data:`cairo.FONT_SLANT_NORMAL` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| font_weight | Font weight used to draw the text. | ``cairo.FONT_WEIGHT_*``| :data:`cairo.FONT_WEIGHT_NORMAL` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
| font_size | Font size used to draw the text. | ``float`` or ``int`` | ``12`` |
+----------------+---------------------------------------------------+------------------------+----------------------------------+
Examples
--------
......@@ -729,6 +755,15 @@ def graph_draw(g, pos=None, vprops=None, eprops=None, vorder=None, eorder=None,
else:
eprops["marker_size"] = pw * 2.75
if "text" in eprops and "text_distance" not in eprops and "pen_width" in eprops:
pw = eprops["pen_width"]
if isinstance(pw, PropertyMap):
pw = pw.copy()
pw.a *= 2
eprops["text_distance"] = pw
else:
eprops["text_distance"] = pw * 2
if "text" in vprops and ("text_color" not in vprops or vprops["text_color"] == "auto"):
vcmap = kwargs.get("vcmap", matplotlib.cm.jet)
bg = _convert(vertex_attrs.fill_color, vprops.get("fill_color", _vdefaults["fill_color"]), vcmap)
......@@ -825,6 +860,10 @@ def scale_ink(scale, vprops, eprops):
eprops["pen_width"] = _edefaults["pen_width"]
if "marker_size" not in eprops:
eprops["marker_size"] = _edefaults["marker_size"]
if "font_size" not in eprops:
eprops["font_size"] = _edefaults["font_size"]
if "text_distance" not in eprops:
eprops["text_distance"] = _edefaults["text_distance"]
for props in [vprops, eprops]:
if isinstance(props["pen_width"], PropertyMap):
......@@ -843,6 +882,14 @@ def scale_ink(scale, vprops, eprops):
eprops["marker_size"].fa *= scale
else:
eprops["marker_size"] *= scale
if isinstance(eprops["font_size"], PropertyMap):
eprops["font_size"].fa *= scale
else:
eprops["font_size"] *= scale
if isinstance(eprops["text_distance"], PropertyMap):
eprops["text_distance"].fa *= scale
else:
eprops["text_distance"] *= scale
def get_bb(g, pos, size, pen_width, size_scale=1, text=None, font_family=None,
font_size=None, cr=None):
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment