Reputation: 1708
I have Mrecord nodes, each with a number of fields specified using an HTML label. I have TDs in my table each with a port="..." attribute. When I specify headport and tailport of an edge to use those port names though, I'm always getting a warning that the port is unrecognized:
ex: Warning: node departments, port dept_no unrecognized
and yet I'm 100% certain such a port does exist. Here's a trivial example of html:
<table><tr><td>departments</td></tr><tr><td port="dept_no">dept_no</td></tr></table>
Having set that as the node's label, I'd assume the node would have a dept_no
port, but it doesn't.
--
Now a bit more info: I'm using the C API to construct this graph and do the layout etc. After layout the nodes each have a label, with the html
boolean as true, but the label itself has no html data, and no ports, etc.
It's puzzling. I can't figure out why the nodes have no ports.
#include <stdio.h>
#include <gvc.h>
#include <gvplugin.h>
extern gvplugin_library_t gvplugin_dot_layout_LTX_library;
extern gvplugin_library_t gvplugin_core_LTX_library;
lt_symlist_t lt_preloaded_symbols[] =
{
{ "gvplugin_dot_layout_LTX_library", &gvplugin_dot_layout_LTX_library},
{ "gvplugin_core_LTX_library", &gvplugin_core_LTX_library},
{ 0, 0}
};
int main(int argc, const char * argv[])
{
GVC_t * gvc = gvContextPlugins(lt_preloaded_symbols, 0);
Agraph_t * gvg = agopen("Graph", Agdirected, NULL);
agattr(gvg, AGRAPH, "dpi", "72");
agattr(gvg, AGRAPH, "resolution", "72");
agattr(gvg, AGRAPH, "sep", "0.27777");
agattr(gvg, AGRAPH, "rankdir", "TB");
agattr(gvg, AGRAPH, "ranksep", "0.5");
agattr(gvg, AGRAPH, "nodesep", "0.4");
agattr(gvg, AGRAPH, "pad", "0.5,0.5");
agattr(gvg, AGRAPH, "margin", "0,0");
agattr(gvg, AGRAPH, "splines", "spline");
agattr(gvg, AGNODE, "shape", "Mrecord");
agattr(gvg, AGNODE, "width", "0");
agattr(gvg, AGNODE, "height", "0");
agattr(gvg, AGNODE, "fixedsize", "false");
agattr(gvg, AGNODE, "margin", "0.0,0.0");
agattr(gvg, AGNODE, "penwidth", "0.0");
agattr(gvg, AGNODE, "fontsize", "13");
agattr(gvg, AGEDGE, "arrowsize", "0.5");
agattr(gvg, AGEDGE, "penwidth", "1.0");
agattr(gvg, AGEDGE, "labelangle", "32");
agattr(gvg, AGEDGE, "labeldistance", "1.8");
agattr(gvg, AGEDGE, "dir", "none");
agattr(gvg, AGEDGE, "headport", "_");
agattr(gvg, AGEDGE, "tailport", "_");
const char * nodeALabel = "<table id=\"dept_emp\" width=\"140\" height=\"26\"><tr><td height=\"26\">dept_emp</td></tr><tr><td height=\"20\" port=\"emp_no\">emp_no</td></tr><tr><td height=\"20\" port=\"dept_no\">dept_no</td></tr></table>";
const char * nodeBLabel = "<table id=\"departments\" width=\"140\" height=\"26\"><tr><td height=\"26\">departments</td></tr><tr><td height=\"20\" port=\"dept_no\">dept_no</td></tr><tr><td height=\"20\" port=\"dept_name\">dept_name</td></tr></table>";
Agnode_t * nodeA = agnode(gvg, "dept_emp", 1);
Agnode_t * nodeB = agnode(gvg, "departments", 1);
char * la = agstrdup_html(gvg, (char *)nodeALabel);
char * lb = agstrdup_html(gvg, (char *)nodeBLabel);
agsafeset(nodeA, "label", la, "");
agsafeset(nodeB, "label", lb, "");
agstrfree(gvg, la);
agstrfree(gvg, lb);
// An edge pointing from dept_emp.dept_no ---> departments.dept_no
Agedge_t * edge = agedge(gvg, nodeA, nodeB, NULL, 1);
agsafeset(edge, "dir", "forward", "none");
agsafeset(edge, "tailport", "dept_no", "_");
agsafeset(edge, "headport", "dept_no", "_");
gvLayout(gvc, gvg, "dot");
// Warning: node dept_emp, port dept_no unrecognized
// Warning: node departments, port dept_no unrecognized
return 0;
}
Upvotes: 1
Views: 1105
Reputation: 233
Although it is confusing that the HTML is rendered, but the ports are not recognized, Record-based nodes and HTML-like labels should just not be mixed. They have conflicting label schemas and overlapping functionality. As confirmed by one of the Graphviz authors, they are incompatible by design and it was simply not expected that people would try to combine the two. So, the solution is to replace Mrecord
by none
. For details, see https://gitlab.com/graphviz/graphviz/issues/1491.
Upvotes: 2