Number: 649
Title: Plain format spec does not create a useable spline
Submitter: Norman Papernick
Date: Tue Mar 15 21:06:23 2005
Subsys: Output generation
Version: 2.2
System: *-*-
Severity: minor
Problem:
The function output.c _write_plain() does not emit a parseable edge when multiple splines make up the edge. This happens when concentrate=true and the concentration happens. The program will emit the splines points without indication of where one spline starts and another begines.
Input:
digraph G {
 concentrate="true";
 A -> B;
 B -> C;
 C -> B;
 E -> B;
 A -> B;
 B -> E;
 A -> C;
 B -> C;
 D -> C;
 E -> C;
 A -> D;
 A -> E;
 E -> A;
 B -> A;
 B -> C;
 B -> D;
}
Comments: I've been using the fix that follows in my own project, and it works for me.
Fix:
I suggest changing the spec from edge tail head n x1 y1 .. xn yn [label xl yl] style color to edge tail head ne n1 x11 y11 .. x1n y1n n2 ... [label x1 y1] style color where ne is the total number of segments in the spline set n1 is the number of pairs in the first segment x11 y11 are the first pair and so on. n2 is the number of pairs in the second segment. repeat up to ne segments

There was also a bug where the base color was being repreated for each edge. An IF statement was added to fix that.

Here is the new function call _write_plain() with the fixes noted:


void _write_plain(GVC_t * gvc, FILE * f, boolean extend)
{
	int i, j, splinePoints;
	char *tport, *hport;
	node_t *n;
	edge_t *e;
	bezier bz;
	point pt;
	graph_t *g = gvc->g;
	char *lbl;

setup_graph(gvc, g); setYInvert(g); pt = GD_bb(g).UR; fprintf(f, "graph %.3f %.3f %.3fn", GD_drawing(g)->scale, PS2INCH(pt.x), PS2INCH(pt.y)); for (n = agfstnode(g); n; n = agnxtnode(g, n)) { if (IS_CLUST_NODE(n)) continue; fprintf(f, "node %s ", canonical(n->name)); printptf(f, ND_coord_i(n)); lbl = ND_label(n)->text; if (lbl) lbl = canonical(lbl); else lbl = """"; fprintf(f, " %.3f %.3f %s %s %s %s %sn", ND_width(n), ND_height(n), lbl, late_nnstring(n, N_style, "solid"), ND_shape(n)->name, late_nnstring(n, N_color, DEFAULT_COLOR), late_nnstring(n, N_fillcolor, DEFAULT_FILL)); } for (n = agfstnode(g); n; n = agnxtnode(g, n)) { for (e = agfstout(g, n); e; e = agnxtout(g, e)) { if (extend && e->attr) { tport = e->attr[TAILX]; hport = e->attr[HEADX]; } else tport = hport = ""; if (ED_spl(e)) { splinePoints = 0; for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; splinePoints += bz.size; } fprintf(f, "edge "); writenodeandport(f, e->tail, tport); fprintf(f, " "); writenodeandport(f, e->head, hport); // begin change by visionline // print out the number of segments. fprintf(f, " %d", ED_spl(e)->size); for (i = 0; i < ED_spl(e)->size; i++) { bz = ED_spl(e)->list[i]; // for each segment, print out the number of elements fprintf(f, " %d", bz.size); // print out each element for (j = 0; j < bz.size; j++) printptf(f, bz.list[j]); } // end change by visionline } if (ED_label(e)) { fprintf(f, " %s", canonical(ED_label(e)->text)); printptf(f, ED_label(e)->p); } // begin change by visionline // This insures that the tag will only be printed for actual edges if (ED_spl(e)) // end change by visionline fprintf(f, " %s %sn", late_nnstring(e, E_style, "solid"), late_nnstring(e, E_color, DEFAULT_COLOR)); } } fprintf(f, "stopn"); }

Comments: [erg] A not unreasonable suggestion, but we'll have to give it some thought. There are two problems with further extending the plain format. One is that is really is meant to be plain and simple, and only applicable for the simplest applications. The question is where to stop adding enhancements. If one wants all of the information, it can be found by using the dot format.

The other problem with the plain format is its simplicity. It can't be easily extended without breaking someone's code. People who use the format typically don't build forgiving parses. Their code would break if a new format is introduced. For this latter reason, if we were to add your extension, we would probably have to do it as another output format.
Owner: *
Status: *