From: Yifan Hu Date: Fri, 28 Feb 2014 17:14:01 +0000 (-0500) Subject: changed due to edgepaint X-Git-Tag: 2.38.0~49^2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=3606ab84a116dfeed383b6007f1d0bf5d862b6e0;p=graphviz changed due to edgepaint --- diff --git a/graphviz.spec.in b/graphviz.spec.in index 43c74ffd2..1a210126a 100644 --- a/graphviz.spec.in +++ b/graphviz.spec.in @@ -215,6 +215,7 @@ of graphs (as in nodes and edges, not as in bar-charts). %{_bindir}/gxl2dot %{_bindir}/gxl2gv %{_bindir}/mingle +%{_bindir}/edgepaint %{_bindir}/mm2gv %{_bindir}/neato %{_bindir}/nop @@ -248,6 +249,7 @@ of graphs (as in nodes and edges, not as in bar-charts). %{_mandir}/man1/gvpr.1* %{_mandir}/man1/gxl2gv.1* %{_mandir}/man1/mingle.1* +%{_mandir}/man1/edgepaint.1* %{_mandir}/man1/mm2gv.1* %{_mandir}/man1/neato.1* %{_mandir}/man1/nop.1* diff --git a/lib/sfdpgen/QuadTree.c b/lib/sfdpgen/QuadTree.c index bd6b289d4..aeb14254d 100644 --- a/lib/sfdpgen/QuadTree.c +++ b/lib/sfdpgen/QuadTree.c @@ -373,6 +373,7 @@ QuadTree QuadTree_new_from_point_list(int dim, int n, int max_level, real *coord center[i] = (xmin[i] + xmax[i])*0.5; width = MAX(width, xmax[i] - xmin[i]); } + if (width == 0) width = 0.00001;/* if we only have one point, width = 0! */ width *= 0.52; qt = QuadTree_new(dim, center, width, max_level); @@ -446,7 +447,7 @@ static int QuadTree_get_quadrant(int dim, real *center, real *coord){ return d; } -static QuadTree QuadTree_new_in_quadrant(int dim, real *center, real width, int max_level, int i){ +QuadTree QuadTree_new_in_quadrant(int dim, real *center, real width, int max_level, int i){ /* a new quadtree in quadrant i of the original cell. The original cell is centered at 'center". The new cell have width "width". */ diff --git a/lib/sfdpgen/QuadTree.h b/lib/sfdpgen/QuadTree.h index bbd904859..358cb7885 100644 --- a/lib/sfdpgen/QuadTree.h +++ b/lib/sfdpgen/QuadTree.h @@ -59,5 +59,6 @@ void QuadTree_get_repulsive_force(QuadTree qt, real *force, real *x, real bh, re /* find the nearest point and put in ymin, index in imin and distance in min */ void QuadTree_get_nearest(QuadTree qt, real *x, real *ymin, int *imin, real *min, int *flag); +QuadTree QuadTree_new_in_quadrant(int dim, real *center, real width, int max_level, int i); #endif diff --git a/lib/sparse/DotIO.c b/lib/sparse/DotIO.c index 12e658aec..b2d564275 100644 --- a/lib/sparse/DotIO.c +++ b/lib/sparse/DotIO.c @@ -20,6 +20,11 @@ #include "color_palette.h" #include "colorutil.h" +#define ag_xget(x,a) agxget(x,a) +#define ag_xset(x,a,c) agxset(x,a,c) +#define agedgeattr(g,a,c) (agattr(g,AGEDGE,a,c)) +#define agfindedgeattr(g,a) (agattr(g,AGEDGE,a,NULL)) + typedef struct { Agrec_t h; unsigned int id; @@ -70,6 +75,52 @@ attach_embedding (Agraph_t* g, int dim, double sc, real *x) } #endif + +static void color_string(int slen, char *buf, int dim, real *color){ + if (dim > 3 || dim < 1){ + fprintf(stderr,"can only 1, 2 or 3 dimensional color space. with color value between 0 to 1\n"); + assert(0); + } + assert(slen >= 3); + if (dim == 3){ + sprintf(buf,"#%02x%02x%02x", MIN((unsigned int)(color[0]*255),255), + MIN((unsigned int) (color[1]*255), 255), MIN((unsigned int)(color[2]*255), 255)); + } else if (dim == 1){ + sprintf(buf,"#%02x%02x%02x", MIN((unsigned int)(color[0]*255),255), + MIN((unsigned int) (color[0]*255), 255), MIN((unsigned int)(color[0]*255), 255)); + } else if (dim == 2){ + sprintf(buf,"#%02x%02x%02x", MIN((unsigned int)(color[0]*255),255), + 0, MIN((unsigned int)(color[1]*255), 255)); + } +} + +void attach_edge_colors(Agraph_t* g, int dim, real *colors){ + /* colors is array of dim*nedges, with color for edge i at colors[dim*i, dim(i+1)) + */ + Agsym_t* sym = agfindedgeattr(g, "color"); + Agedge_t* e; + Agnode_t* n; + enum {slen = 1024}; + char buf[slen]; + int row, col; + int ie = 0; + + if (!sym) + sym = agedgeattr (g, "color", ""); + + for (n = agfstnode (g); n; n = agnxtnode (g, n)) { + row = ND_id(n); + for (e = agfstout (g, n); e; e = agnxtout (g, e)) { + col = ND_id(aghead(e)); + if (row == col) continue; + color_string(slen, buf, dim, colors + ie*dim); + ag_xset(e, sym, buf); + ie++; + } + } + +} + /* SparseMatrix_read_dot: * Wrapper for reading dot graph from file */ @@ -106,26 +157,39 @@ SparseMatrix_import_dot (Agraph_t* g, int dim, real **label_sizes, real **x, int real padding = 10; int nedge_nodes = 0; + + if (!g) return NULL; nnodes = agnnodes (g); nedges = agnedges (g); - if (format != FORMAT_CSR) { + if (format != FORMAT_CSR && format != FORMAT_COORD) { fprintf (stderr, "Format %d not supported\n", format); exit (1); } + /* Assign node ids */ i = 0; for (n = agfstnode (g); n; n = agnxtnode (g, n)) ND_id(n) = i++; - I = N_NEW(nedges, int); - J = N_NEW(nedges, int); - val = N_NEW(nedges, real); - sym = agattr(g, AGEDGE, "weight", NULL); + + if (format == FORMAT_COORD){ + A = SparseMatrix_new(i, i, nedges, MATRIX_TYPE_REAL, format); + A->nz = nedges; + I = A->ia; + J = A->ja; + val = (real*) A->a; + } else { + I = N_NEW(nedges, int); + J = N_NEW(nedges, int); + val = N_NEW(nedges, real); + } + + sym = agfindedgeattr(g, "weight"); if (D) { - symD = agattr(g, AGEDGE, "len", NULL); + symD = agfindedgeattr(g, "len"); valD = N_NEW(nedges, real); } i = 0; @@ -165,26 +229,30 @@ SparseMatrix_import_dot (Agraph_t* g, int dim, real **label_sizes, real **x, int nedge_nodes = 0; } - *label_sizes = MALLOC(sizeof(real)*2*nnodes); + + if (label_sizes) *label_sizes = MALLOC(sizeof(real)*2*nnodes); for (n = agfstnode (g); n; n = agnxtnode (g, n)) { real sz; i = ND_id(n); if (edge_label_nodes && strncmp(agnameof(n), "|edgelabel|",11)==0) { (*edge_label_nodes)[nedge_nodes++] = i; } - if (agget(n, "width") && agget(n, "height")){ - sscanf(agget(n, "width"), "%lf", &sz); - /* (*label_sizes)[i*2] = POINTS(sz)*.6;*/ - (*label_sizes)[i*2] = POINTS(sz)*.5 + padding*0.5; - sscanf(agget(n, "height"), "%lf", &sz); - /*(*label_sizes)[i*2+1] = POINTS(sz)*.6;*/ - (*label_sizes)[i*2+1] = POINTS(sz)*.5 + padding*0.5; - } else { - (*label_sizes)[i*2] = 4*POINTS(0.75)*.5; - (*label_sizes)[i*2+1] = 4*POINTS(0.5)*.5; + if (label_sizes){ + if (agget(n, "width") && agget(n, "height")){ + sscanf(agget(n, "width"), "%lf", &sz); + /* (*label_sizes)[i*2] = POINTS(sz)*.6;*/ + (*label_sizes)[i*2] = POINTS(sz)*.5 + padding*0.5; + sscanf(agget(n, "height"), "%lf", &sz); + /*(*label_sizes)[i*2+1] = POINTS(sz)*.6;*/ + (*label_sizes)[i*2+1] = POINTS(sz)*.5 + padding*0.5; + } else { + (*label_sizes)[i*2] = 4*POINTS(0.75)*.5; + (*label_sizes)[i*2+1] = 4*POINTS(0.5)*.5; + } } } + if (x && (psym = agattr(g, AGNODE, "pos", NULL))) { int has_positions = TRUE; char* pval; @@ -244,19 +312,68 @@ SparseMatrix_import_dot (Agraph_t* g, int dim, real **label_sizes, real **x, int else if (x) agerr (AGERR, "Error: graph %s has missing \"pos\" information", agnameof(g)); - A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val, type, sz); + + if (format == FORMAT_CSR) A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val, type, sz); if (edge_label_nodes) *n_edge_label_nodes = nedge_nodes; if (D) *D = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, valD, type, sz); - FREE(I); - FREE(J); - FREE(val); + if (format != FORMAT_COORD){ + FREE(I); + FREE(J); + FREE(val); + } if (valD) FREE(valD); return A; } +/* get spline info */ +int Import_dot_splines(Agraph_t* g, int *ne, char ***xsplines){ + /* get the list of splines for the edges in the order they appear, and store as a list of strings in xspline. + If *xsplines = NULL, it will be allocated. On exit (*xsplines)[i] is the control point string for the i-th edge. This string + is of the form "x1,y1 x2,y2...", the two end points of the edge is not included per Dot format + Return 1 if success. 0 if not. + */ + Agnode_t* n; + Agedge_t* e; + Agsym_t *sym; + int nedges; + int i; + + if (!g){ + return 0; + } + + *ne = nedges = agnedges (g); + + /* Assign node ids */ + i = 0; + for (n = agfstnode (g); n; n = agnxtnode (g, n)) + ND_id(n) = i++; + + sym = agattr(g, AGEDGE, "pos", NULL); + if (!sym) return 0; + + if (!(*xsplines)) *xsplines = malloc(sizeof(char*)*nedges); + + i = 0; + for (n = agfstnode (g); n; n = agnxtnode (g, n)) { + for (e = agfstout (g, n); e; e = agnxtout (g, e)) { + /* edge weight */ + if (sym) { + char *pos = ag_xget (e, sym); + (*xsplines)[i] = malloc(sizeof(char)*(strlen(pos)+1)); + strcpy((*xsplines)[i], pos); + } else { + (*xsplines)[i] = NULL; + } + i++; + } + } + return 1; +} + static real dist(int dim, real *x, real *y){ int k; real d = 0; @@ -646,6 +763,17 @@ Agraph_t* assign_random_edge_color(Agraph_t* g){ return g; } + +static int hex2int(char h){ + if (h >= '0' && h <= '9') return h - '0'; + if (h >= 'a' && h <= 'f') return 10 + h - 'a'; + if (h >= 'A' && h <= 'F') return 10 + h - 'A'; + return 0; +} +static float hexcol2rgb(char *h){ + return (hex2int(h[0])*16 + hex2int(h[1]))/255.; +} + void Dot_SetClusterColor(Agraph_t* g, float *rgb_r, float *rgb_g, float *rgb_b, int *clusters){ Agnode_t* n; @@ -911,6 +1039,13 @@ SparseMatrix Import_coord_clusters_from_dot(Agraph_t* g, int maxcluster, int dim (*rgb_b)[(*clusters)[i]] = color.u.RGBA[2]; } + if (!noclusterinfo && agget(n, "cluster") && agget(n, "clustercolor") && strlen(agget(n, "clustercolor") ) >= 7 && pal){ + char cc[10]; + strcpy(cc, agget(n, "clustercolor")); + (*rgb_r)[(*clusters)[i]] = hexcol2rgb(cc+1); + (*rgb_g)[(*clusters)[i]] = hexcol2rgb(cc+3); + (*rgb_b)[(*clusters)[i]] = hexcol2rgb(cc+5); + } } diff --git a/lib/sparse/DotIO.h b/lib/sparse/DotIO.h index 00258b03b..8057421c1 100644 --- a/lib/sparse/DotIO.h +++ b/lib/sparse/DotIO.h @@ -24,6 +24,10 @@ extern Agraph_t* SparseMatrix_read_dot(FILE*); extern void setDotNodeID (Agnode_t* n, int v); extern int getDotNodeID (Agnode_t* n); +extern void attach_edge_colors(Agraph_t* g, int dim, real *colors); + +extern void attach_embedding(Agraph_t *g, int dim, double sc, real *x); + /* extern void attach_embedding(Agraph_t *g, int dim, double sc, real *x); */ extern SparseMatrix SparseMatrix_import_dot(Agraph_t* g, int dim, real **label_sizes, real **x, int *n_edge_label_nodes, int **edge_label_nodes, int format, SparseMatrix *D); @@ -39,4 +43,5 @@ SparseMatrix Import_coord_clusters_from_dot(Agraph_t* g, int maxcluster, int dim void Dot_SetClusterColor(Agraph_t* g, float *rgb_r, float *rgb_g, float *rgb_b, int *clustering); void attached_clustering(Agraph_t* g, int maxcluster, int clustering_scheme); +int Import_dot_splines(Agraph_t* g, int *ne, char ***xsplines); #endif diff --git a/lib/sparse/general.c b/lib/sparse/general.c index bf2c6333a..7bdc79e4f 100644 --- a/lib/sparse/general.c +++ b/lib/sparse/general.c @@ -207,7 +207,7 @@ int comp_ascend_int(const void *s1, const void *s2){ void vector_ordering(int n, real *v, int **p, int ascending){ - /* give the position of the lagest, second largest etc in vector v if ascending = TRUE + /* give the position of the lagest, second largest etc in vector v if ascending = FALSE or @@ -271,7 +271,6 @@ int excute_system_command(char *s1, char *s2){ return system(c); } - real distance_cropped(real *x, int dim, int i, int j){ int k; real dist = 0.; @@ -298,6 +297,7 @@ real point_distance(real *p1, real *p2, int dim){ char *strip_dir(char *s){ int i, first = TRUE; + if (!s) return s; for (i = strlen(s); i >= 0; i--) { if (first && s[i] == '.') {/* get rid of .mtx */ s[i] = '\0'; @@ -342,3 +342,24 @@ void scale_to_box(real xmin, real ymin, real xmax, real ymax, int n, int dim, re } + +int digitsQ(char *s){ + while (*s && *s - '0' >= 0 && *s - '0' <= 9) { + s++; + } + if (*s) return 0; + return 1; +} +int validQ_int_string(char *to_convert, int *v){ + /* check to see if this is a string is integer */ + char *p = to_convert; + int errno = 0; + long val = strtoul(to_convert, &p, 10); + if (errno != 0 ||// conversion failed (EINVAL, ERANGE) + to_convert == p || // conversion failed (no characters consumed) + *p != 0 + ) return 0; + if (val > INT_MAX || val < INT_MIN) return 0; + *v = (int) val; + return 1; +} diff --git a/lib/sparse/general.h b/lib/sparse/general.h index 9411d86fd..f8996e526 100644 --- a/lib/sparse/general.h +++ b/lib/sparse/general.h @@ -116,6 +116,8 @@ real vector_percentile(int n, real *x, real y);/* find the value such that y% of void vector_print(char *s, int n, real *x); #define MACHINEACC 1.0e-16 +#define SQRT_MACHINEACC 1.0e-8 + int excute_system_command3(char *s1, char *s2, char *s3); int excute_system_command(char *s1, char *s2); @@ -134,6 +136,12 @@ char *strip_dir(char *s); void scale_to_box(real xmin, real ymin, real xmax, real ymax, int n, int dim, real *x); +/* check to see if this is a string is integer (that can be casted into an integer variable hence very long list of digits are not valid, like 123456789012345. Return 1 if true, 0 if false. */ +int validQ_int_string(char *to_convert, int *v); + +/* check to see if this is a string of digits consists of 0-9 */ +int digitsQ(char *to_convert); + #endif