Graphviz 12.0.1~dev.20240715.2254
Loading...
Searching...
No Matches
DotIO.c
Go to the documentation of this file.
1/*************************************************************************
2 * Copyright (c) 2011 AT&T Intellectual Property
3 * All rights reserved. This program and the accompanying materials
4 * are made available under the terms of the Eclipse Public License v1.0
5 * which accompanies this distribution, and is available at
6 * https://www.eclipse.org/legal/epl-v10.html
7 *
8 * Contributors: Details at https://graphviz.org
9 *************************************************************************/
10
11#define STANDALONE
12#include <cgraph/agxbuf.h>
13#include <cgraph/alloc.h>
14#include <cgraph/startswith.h>
15#include <cgraph/unreachable.h>
16#include <sparse/general.h>
17#include <sparse/DotIO.h>
18#include <sparse/clustering.h>
19#include <math.h>
20#include <sparse/mq.h>
22#include <sparse/colorutil.h>
23#include <stdbool.h>
24#include <string.h>
25
26typedef struct {
27 Agrec_t h;
28 unsigned int id;
30
31#define ND_id(n) (((Agnodeinfo_t*)((n)->base.data))->id)
32
33static void color_string(agxbuf *buf, int dim, double *color){
34 if (dim > 3 || dim < 1){
35 fprintf(stderr,"can only 1, 2 or 3 dimensional color space. with color value between 0 to 1\n");
36 assert(0);
37 }
38 if (dim == 3){
39 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] *255), 255),
40 MIN((unsigned int) (color[1]*255), 255), MIN((unsigned int)(color[2]*255), 255));
41 } else if (dim == 1){
42 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] * 255), 255),
43 MIN((unsigned int) (color[0]*255), 255), MIN((unsigned int)(color[0]*255), 255));
44 } else if (dim == 2){
45 agxbprint(buf, "#%02x%02x%02x", MIN((unsigned int)(color[0] * 255), 255),
46 0, MIN((unsigned int)(color[1]*255), 255));
47 }
48}
49
50void attach_edge_colors(Agraph_t* g, int dim, double *colors){
51 /* colors is array of dim*nedges, with color for edge i at colors[dim*i, dim(i+1))
52 */
53 Agsym_t* sym = agattr(g, AGEDGE, "color", 0);
54 Agedge_t* e;
55 Agnode_t* n;
56 agxbuf buf = {0};
57 unsigned row, col;
58 int ie = 0;
59
60 if (!sym)
61 sym = agattr (g, AGEDGE, "color", "");
62
63 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
64 row = ND_id(n);
65 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
66 col = ND_id(aghead(e));
67 if (row == col) continue;
68 color_string(&buf, dim, colors + ie*dim);
69 agxset(e, sym, agxbuse(&buf));
70 ie++;
71 }
72 }
73 agxbfree(&buf);
74}
75
76/* SparseMatrix_import_dot:
77 * Assumes g is connected and simple, i.e., we can have a->b and b->a
78 * but not a->b and a->b
79 */
81 double **x, int format) {
82 SparseMatrix A = 0;
83 Agnode_t* n;
84 Agedge_t* e;
85 Agsym_t *sym;
86 Agsym_t *psym;
87 int nnodes;
88 int nedges;
89 int i, row;
90 int* I;
91 int* J;
92 double *val;
93 double v;
95
96 if (!g) return NULL;
97 nnodes = agnnodes (g);
98 nedges = agnedges (g);
99 if (format != FORMAT_CSR && format != FORMAT_COORD) {
100 fprintf (stderr, "Format %d not supported\n", format);
101 graphviz_exit(1);
102 }
103
104 /* Assign node ids */
105 i = 0;
106 for (n = agfstnode (g); n; n = agnxtnode (g, n))
107 ND_id(n) = i++;
108
109 if (format == FORMAT_COORD){
111 A->nz = nedges;
112 I = A->ia;
113 J = A->ja;
114 val = A->a;
115 } else {
116 I = gv_calloc(nedges, sizeof(int));
117 J = gv_calloc(nedges, sizeof(int));
118 val = gv_calloc(nedges, sizeof(double));
119 }
120
121 sym = agattr(g, AGEDGE, "weight", NULL);
122 i = 0;
123 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
124 row = ND_id(n);
125 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
126 I[i] = row;
127 J[i] = ND_id(aghead(e));
128
129 /* edge weight */
130 if (sym) {
131 if (sscanf (agxget(e,sym), "%lf", &v) != 1) v = 1;
132 } else {
133 v = 1;
134 }
135 val[i] = v;
136
137 i++;
138 }
139 }
140
141 if (x && (psym = agattr(g, AGNODE, "pos", NULL))) {
142 bool has_positions = true;
143 char* pval;
144 if (!(*x)) {
145 *x = gv_calloc(dim * nnodes, sizeof(double));
146 }
147 for (n = agfstnode (g); n && has_positions; n = agnxtnode (g, n)) {
148 double xx,yy, zz,ww;
149 int nitems;
150 i = ND_id(n);
151 if ((pval = agxget(n, psym)) && *pval) {
152 if (dim == 2){
153 nitems = sscanf(pval, "%lf,%lf", &xx, &yy);
154 if (nitems != 2) {
155 has_positions = false;
156 agerrorf("Node \"%s\" pos has %d < 2 values", agnameof(n), nitems);
157 }
158 (*x)[i*dim] = xx;
159 (*x)[i*dim+1] = yy;
160 } else if (dim == 3){
161 nitems = sscanf(pval, "%lf,%lf,%lf", &xx, &yy, &zz);
162 if (nitems != 3) {
163 has_positions = false;
164 agerrorf("Node \"%s\" pos has %d < 3 values", agnameof(n), nitems);
165 }
166 (*x)[i*dim] = xx;
167 (*x)[i*dim+1] = yy;
168 (*x)[i*dim+2] = zz;
169 } else if (dim == 4){
170 nitems = sscanf(pval, "%lf,%lf,%lf,%lf", &xx, &yy, &zz,&ww);
171 if (nitems != 4) {
172 has_positions = false;
173 agerrorf("Node \"%s\" pos has %d < 4 values", agnameof(n), nitems);
174 }
175 (*x)[i*dim] = xx;
176 (*x)[i*dim+1] = yy;
177 (*x)[i*dim+2] = zz;
178 (*x)[i*dim+3] = ww;
179 } else if (dim == 1){
180 nitems = sscanf(pval, "%lf", &xx);
181 if (nitems != 1){
183 A = NULL;
184 goto done;
185 }
186 (*x)[i*dim] = xx;
187 } else {
188 assert(0);
189 }
190 } else {
191 has_positions = false;
192 agerrorf("Node \"%s\" lacks position info", agnameof(n));
193 }
194 }
195 if (!has_positions) {
196 free(*x);
197 *x = NULL;
198 }
199 }
200 else if (x)
201 agerrorf("Error: graph %s has missing \"pos\" information", agnameof(g));
202
203 size_t sz = sizeof(double);
204 if (format == FORMAT_CSR) A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val, type, sz);
205
206done:
207 if (format != FORMAT_COORD){
208 free(I);
209 free(J);
210 free(val);
211 }
212
213 return A;
214}
215
216/* get spline info */
217int Import_dot_splines(Agraph_t* g, int *ne, char ***xsplines){
218 /* get the list of splines for the edges in the order they appear, and store as a list of strings in xspline.
219 If *xsplines = NULL, it will be allocated. On exit (*xsplines)[i] is the control point string for the i-th edge. This string
220 is of the form "x1,y1 x2,y2...", the two end points of the edge is not included per Dot format
221 Return 1 if success. 0 if not.
222 */
223 Agnode_t* n;
224 Agedge_t* e;
225 Agsym_t *sym;
226 int nedges;
227 unsigned i;
228
229 if (!g){
230 return 0;
231 }
232
233 *ne = nedges = agnedges (g);
234
235 /* Assign node ids */
236 i = 0;
237 for (n = agfstnode (g); n; n = agnxtnode (g, n))
238 ND_id(n) = i++;
239
240 sym = agattr(g, AGEDGE, "pos", 0);
241 if (!sym) return 0;
242
243 *xsplines = gv_calloc(nedges, sizeof(char*));
244
245 i = 0;
246 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
247 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
248 /* edge weight */
249 char *pos = agxget (e, sym);
250 (*xsplines)[i] = strdup(pos);
251 i++;
252 }
253 }
254 return 1;
255}
256
257static int hex2int(char h){
258 if (h >= '0' && h <= '9') return h - '0';
259 if (h >= 'a' && h <= 'f') return 10 + h - 'a';
260 if (h >= 'A' && h <= 'F') return 10 + h - 'A';
261 return 0;
262}
263
264static float hexcol2rgb(const char *h) {
265 return (hex2int(h[0])*16 + hex2int(h[1]))/255.;
266}
267
268void Dot_SetClusterColor(Agraph_t* g, float *rgb_r, float *rgb_g, float *rgb_b, int *clusters){
269
270 Agnode_t* n;
271 agxbuf scluster = {0};
272 unsigned i;
273 Agsym_t* clust_clr_sym = agattr(g, AGNODE, "clustercolor", NULL);
274
275 if (!clust_clr_sym) clust_clr_sym = agattr(g, AGNODE, "clustercolor", "-1");
276 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
277 i = ND_id(n);
278 if (rgb_r && rgb_g && rgb_b) {
279 rgb2hex(rgb_r[clusters[i]], rgb_g[clusters[i]], rgb_b[clusters[i]],
280 &scluster, NULL);
281 }
282 agxset(n, clust_clr_sym, agxbuse(&scluster));
283 }
284 agxbfree(&scluster);
285}
286
287SparseMatrix Import_coord_clusters_from_dot(Agraph_t* g, int maxcluster, int dim, int *nn, double **label_sizes, double **x, int **clusters, float **rgb_r, float **rgb_g, float **rgb_b, float **fsz, char ***labels, int default_color_scheme, int clustering_scheme, int useClusters){
288 SparseMatrix A = 0;
289 Agnode_t* n;
290 Agedge_t* e;
291 Agsym_t* sym;
292 Agsym_t* clust_sym;
293 Agsym_t* clust_clr_sym;
294 int nnodes;
295 int nedges;
296 int i, row, ic,nc, j;
297 double v;
299 char scluster[100];
300 float ff;
301
302 int MAX_GRPS, MIN_GRPS;
303 bool noclusterinfo = false;
304 bool first = true;
305 float *pal;
306 int max_color = MAX_COLOR;
307
308 switch (default_color_scheme){
310 pal = &(palette_blue_to_yellow[0][0]);
311 break;
313 pal = &(palette_white_to_red[0][0]);
314 break;
316 pal = &(palette_grey_to_red[0][0]);
317 break;
319 pal = &(palette_grey[0][0]);
320 break;
322 pal = &(palette_pastel[0][0]);
323 break;
325 fprintf(stderr," HERE!\n");
327 break;
329 fprintf(stderr," HERE!\n");
331 break;
333 pal = &(palette_primary[0][0]);
334 break;
336 pal = &(palette_adam_blend[0][0]);
337 break;
339 pal = &(palette_adam[0][0]);
340 max_color = 11;
341 break;
343 pal = NULL;
344 break;
345 default:
346 pal = &(palette_pastel[0][0]);
347 break;
348 }
349
350 if (!g) return NULL;
351 nnodes = agnnodes (g);
352 nedges = agnedges (g);
353 *nn = nnodes;
354
355 /* Assign node ids */
356 i = 0;
357 for (n = agfstnode (g); n; n = agnxtnode (g, n))
358 ND_id(n) = i++;
359
360 /* form matrix */
361 int* I = gv_calloc(nedges, sizeof(int));
362 int* J = gv_calloc(nedges, sizeof(int));
363 double* val = gv_calloc(nedges, sizeof(double));
364
365 sym = agattr(g, AGEDGE, "weight", NULL);
366 clust_sym = agattr(g, AGNODE, "cluster", NULL);
367 clust_clr_sym = agattr(g, AGNODE, "clustercolor", NULL);
368 i = 0;
369 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
370 row = ND_id(n);
371 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
372 I[i] = row;
373 J[i] = ND_id(aghead(e));
374 if (sym) {
375 if (sscanf (agxget(e,sym), "%lf", &v) != 1)
376 v = 1;
377 }
378 else
379 v = 1;
380 val[i] = v;
381 i++;
382 }
383 }
384 A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val,
385 type, sizeof(double));
386
387 /* get clustering info */
388 *clusters = gv_calloc(nnodes, sizeof(int));
389 nc = 1;
390 MIN_GRPS = 0;
391 /* if useClusters, the nodes in each top-level cluster subgraph are assigned to
392 * clusters 2, 3, .... Any nodes not in a cluster subgraph are tossed into cluster 1.
393 */
394 if (useClusters) {
395 Agraph_t* sg;
396 int gid = 1;
397 memset (*clusters, 0, sizeof(int)*nnodes);
398 for (sg = agfstsubg(g); sg; sg = agnxtsubg(sg)) {
399 if (!startswith(agnameof(sg), "cluster")) continue;
400 gid++;
401 for (n = agfstnode(sg); n; n = agnxtnode (sg, n)) {
402 i = ND_id(n);
403 if ((*clusters)[i])
404 fprintf (stderr, "Warning: node %s appears in multiple clusters.\n", agnameof(n));
405 else
406 (*clusters)[i] = gid;
407 }
408 }
409 for (n = agfstnode(g); n; n = agnxtnode (g, n)) {
410 i = ND_id(n);
411 if ((*clusters)[i] == 0)
412 (*clusters)[i] = 1;
413 }
414 MIN_GRPS = 1;
415 nc = gid;
416 }
417 else if (clust_sym) {
418 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
419 i = ND_id(n);
420 if ((sscanf(agxget(n,clust_sym), "%d", &ic)>0)) {
421 (*clusters)[i] = ic;
422 nc = MAX(nc, ic);
423 if (first){
424 MIN_GRPS = ic;
425 first = false;
426 } else {
427 MIN_GRPS = MIN(MIN_GRPS, ic);
428 }
429 } else {
430 noclusterinfo = true;
431 break;
432 }
433 }
434 }
435 else
436 noclusterinfo = true;
437 MAX_GRPS = nc;
438
439 if (noclusterinfo) {
440 double modularity;
441 if (!clust_sym) clust_sym = agattr(g,AGNODE,"cluster","-1");
442
443 if (clustering_scheme == CLUSTERING_MQ){
444 mq_clustering(A, maxcluster,
445 &nc, clusters, &modularity);
446 } else if (clustering_scheme == CLUSTERING_MODULARITY){
447 modularity_clustering(A, false, maxcluster,
448 &nc, clusters, &modularity);
449 } else {
450 UNREACHABLE();
451 }
452 for (i = 0; i < nnodes; i++) (*clusters)[i]++;/* make into 1 based */
453 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
454 i = ND_id(n);
455 snprintf(scluster, sizeof(scluster), "%d", (*clusters)[i]);
456 agxset(n,clust_sym,scluster);
457 }
458 MIN_GRPS = 1;
459 MAX_GRPS = nc;
460 if (Verbose){
461 fprintf(stderr," no complement clustering info in dot file, using modularity clustering. Modularity = %f, ncluster=%d\n",modularity, nc);
462 }
463 }
464
465 *label_sizes = gv_calloc(dim * nnodes, sizeof(double));
466 if (pal || (!noclusterinfo && clust_clr_sym)){
467 *rgb_r = gv_calloc(1 + MAX_GRPS, sizeof(float));
468 *rgb_g = gv_calloc(1 + MAX_GRPS, sizeof(float));
469 *rgb_b = gv_calloc(1 + MAX_GRPS, sizeof(float));
470 } else {
471 *rgb_r = NULL;
472 *rgb_g = NULL;
473 *rgb_b = NULL;
474 }
475 *fsz = gv_calloc(nnodes, sizeof(float));
476 *labels = gv_calloc(nnodes, sizeof(char*));
477
478 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
480 double sz;
481 i = ND_id(n);
482 if (agget(n, "width") && agget(n, "height")){
483 sscanf(agget(n, "width"), "%lf", &sz);
484 (*label_sizes)[i*2] = POINTS(sz*0.5);
485 sscanf(agget(n, "height"), "%lf", &sz);
486 (*label_sizes)[i*2+1] = POINTS(sz*0.5);
487 } else {
488 (*label_sizes)[i*2] = POINTS(0.75/2);
489 (*label_sizes)[i*2+1] = POINTS(0.5*2);
490 }
491
492 if (agget(n, "fontsize")){
493 sscanf(agget(n, "fontsize"), "%f", &ff);
494 (*fsz)[i] = ff;
495 } else {
496 (*fsz)[i] = 14;
497 }
498
499 if (agget(n, "label") && strcmp(agget(n, "label"), "") != 0 && strcmp(agget(n, "label"), "\\N") != 0){
500 char *lbs = agget(n, "label");
501 (*labels)[i] = strdup(lbs);
502 } else {
503 (*labels)[i] = strdup(agnameof(n));
504 }
505
506
507
508 j = (*clusters)[i];
509 if (MAX_GRPS-MIN_GRPS < max_color) {
510 j = (j-MIN_GRPS)*((int)((max_color-1)/MAX((MAX_GRPS-MIN_GRPS),1)));
511 } else {
512 j = (j-MIN_GRPS)%max_color;
513 }
514
515 if (pal){
516 (*rgb_r)[(*clusters)[i]] = pal[3*j+0];
517 (*rgb_g)[(*clusters)[i]] = pal[3*j+1];
518 (*rgb_b)[(*clusters)[i]] = pal[3*j+2];
519 }
520
521 if (!noclusterinfo && clust_clr_sym && (colorxlate(agxget(n,clust_clr_sym),&color,RGBA_DOUBLE) == COLOR_OK)) {
522 (*rgb_r)[(*clusters)[i]] = color.u.RGBA[0];
523 (*rgb_g)[(*clusters)[i]] = color.u.RGBA[1];
524 (*rgb_b)[(*clusters)[i]] = color.u.RGBA[2];
525 }
526
527 const char *cc = agget(n, "clustercolor");
528 if (!noclusterinfo && agget(n, "cluster") && cc && strlen(cc) >= 7 && pal) {
529 (*rgb_r)[(*clusters)[i]] = hexcol2rgb(cc+1);
530 (*rgb_g)[(*clusters)[i]] = hexcol2rgb(cc+3);
531 (*rgb_b)[(*clusters)[i]] = hexcol2rgb(cc+5);
532 }
533
534 }
535
536
537 if (x){
538 bool has_position = false;
539 *x = gv_calloc(dim * nnodes, sizeof(double));
540 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
541 double xx,yy;
542 i = ND_id(n);
543 if (agget(n, "pos")){
544 has_position = true;
545 sscanf(agget(n, "pos"), "%lf,%lf", &xx, &yy);
546 (*x)[i*dim] = xx;
547 (*x)[i*dim+1] = yy;
548 } else {
549 fprintf(stderr,"WARNING: pos field missing for node %d, set to origin\n",i);
550 (*x)[i*dim] = 0;
551 (*x)[i*dim+1] = 0;
552 }
553 }
554 if (!has_position){
555 free(*x);
556 *x = NULL;
557 }
558 }
559
560
561 free(I);
562 free(J);
563 free(val);
564
565 return A;
566}
567
568void attached_clustering(Agraph_t* g, int maxcluster, int clustering_scheme){
569 SparseMatrix A = 0;
570 Agnode_t* n;
571 Agedge_t* e;
572 Agsym_t *sym, *clust_sym;
573 int nnodes;
574 int nedges;
575 int i, row,nc;
576 double v;
578 size_t sz = sizeof(double);
579
580 if (!g) return;
581 nnodes = agnnodes (g);
582 nedges = agnedges (g);
583
584 /* Assign node ids */
585 i = 0;
586 for (n = agfstnode (g); n; n = agnxtnode (g, n))
587 ND_id(n) = i++;
588
589 /* form matrix */
590 int* I = gv_calloc(nedges, sizeof(int));
591 int* J = gv_calloc(nedges, sizeof(int));
592 double* val = gv_calloc(nedges, sizeof(double));
593
594 sym = agattr(g, AGEDGE, "weight", NULL);
595 clust_sym = agattr(g, AGNODE, "cluster", NULL);
596
597 i = 0;
598 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
599 row = ND_id(n);
600 for (e = agfstout (g, n); e; e = agnxtout (g, e)) {
601 I[i] = row;
602 J[i] = ND_id(aghead(e));
603 if (sym) {
604 if (sscanf (agxget(e,sym), "%lf", &v) != 1)
605 v = 1;
606 }
607 else
608 v = 1;
609 val[i] = v;
610 i++;
611 }
612 }
613 A = SparseMatrix_from_coordinate_arrays(nedges, nnodes, nnodes, I, J, val, type, sz);
614
615 int *clusters = gv_calloc(nnodes, sizeof(int));
616
617 {
618 double modularity;
619 if (!clust_sym) clust_sym = agattr(g,AGNODE,"cluster","-1");
620
621 if (clustering_scheme == CLUSTERING_MQ){
622 mq_clustering(A, maxcluster,
623 &nc, &clusters, &modularity);
624 } else if (clustering_scheme == CLUSTERING_MODULARITY){
625 modularity_clustering(A, false, maxcluster,
626 &nc, &clusters, &modularity);
627 } else {
628 UNREACHABLE();
629 }
630 for (i = 0; i < nnodes; i++) (clusters)[i]++;/* make into 1 based */
631 for (n = agfstnode (g); n; n = agnxtnode (g, n)) {
632 i = ND_id(n);
633 agxbuf value_buffer = {0};
634 agxbprint(&value_buffer, "%d", clusters[i]);
635 agxset(n, clust_sym, agxbuse(&value_buffer));
636 agxbfree(&value_buffer);
637 }
638 if (Verbose){
639 fprintf(stderr," no complement clustering info in dot file, using modularity clustering. Modularity = %f, ncluster=%d\n",modularity, nc);
640 }
641 }
642
643 free(I);
644 free(J);
645 free(val);
646 free(clusters);
647
649
650}
651
652
653
655{
656 aginit(g, AGNODE, "info", sizeof(Agnodeinfo_t), true);
657}
658
659void setDotNodeID (Agnode_t* n, int v)
660{
661 ND_id(n) = v;
662}
663
665{
666 return ND_id(n);
667}
668
#define ND_id(n)
Definition DotIO.c:31
void Dot_SetClusterColor(Agraph_t *g, float *rgb_r, float *rgb_g, float *rgb_b, int *clusters)
Definition DotIO.c:268
SparseMatrix SparseMatrix_import_dot(Agraph_t *g, int dim, double **x, int format)
Definition DotIO.c:80
int getDotNodeID(Agnode_t *n)
Definition DotIO.c:664
void initDotIO(Agraph_t *g)
Definition DotIO.c:654
SparseMatrix Import_coord_clusters_from_dot(Agraph_t *g, int maxcluster, int dim, int *nn, double **label_sizes, double **x, int **clusters, float **rgb_r, float **rgb_g, float **rgb_b, float **fsz, char ***labels, int default_color_scheme, int clustering_scheme, int useClusters)
Definition DotIO.c:287
static float hexcol2rgb(const char *h)
Definition DotIO.c:264
void attach_edge_colors(Agraph_t *g, int dim, double *colors)
Definition DotIO.c:50
static void color_string(agxbuf *buf, int dim, double *color)
Definition DotIO.c:33
void setDotNodeID(Agnode_t *n, int v)
Definition DotIO.c:659
static int hex2int(char h)
Definition DotIO.c:257
void attached_clustering(Agraph_t *g, int maxcluster, int clustering_scheme)
Definition DotIO.c:568
int Import_dot_splines(Agraph_t *g, int *ne, char ***xsplines)
Definition DotIO.c:217
@ COLOR_SCHEME_ADAM_BLEND
Definition DotIO.h:20
@ COLOR_SCHEME_PASTEL
Definition DotIO.h:20
@ COLOR_SCHEME_ADAM
Definition DotIO.h:20
@ COLOR_SCHEME_GREY_RED
Definition DotIO.h:20
@ COLOR_SCHEME_SEQUENTIAL_SINGLEHUE_RED
Definition DotIO.h:20
@ COLOR_SCHEME_NONE
Definition DotIO.h:20
@ COLOR_SCHEME_SEQUENTIAL_SINGLEHUE_RED_LIGHTER
Definition DotIO.h:20
@ COLOR_SCHEME_GREY
Definition DotIO.h:20
@ COLOR_SCHEME_WHITE_RED
Definition DotIO.h:20
@ COLOR_SCHEME_PRIMARY
Definition DotIO.h:20
@ COLOR_SCHEME_BLUE_YELLOW
Definition DotIO.h:20
SparseMatrix SparseMatrix_from_coordinate_arrays(int nz, int m, int n, int *irn, int *jcn, void *val0, int type, size_t sz)
void SparseMatrix_delete(SparseMatrix A)
SparseMatrix SparseMatrix_new(int m, int n, int nz, int type, int format)
@ FORMAT_COORD
@ FORMAT_CSR
@ MATRIX_TYPE_REAL
static void agxbfree(agxbuf *xb)
free any malloced resources
Definition agxbuf.h:77
static int agxbprint(agxbuf *xb, const char *fmt,...)
Printf-style output to an agxbuf.
Definition agxbuf.h:213
static char * agxbuse(agxbuf *xb)
Definition agxbuf.h:286
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
#define MIN(a, b)
Definition arith.h:28
void modularity_clustering(SparseMatrix A, bool inplace, int ncluster_target, int *nclusters, int **assignment, double *modularity)
Definition clustering.c:342
@ CLUSTERING_MODULARITY
Definition clustering.h:39
@ CLUSTERING_MQ
Definition clustering.h:39
static int useClusters
Definition ccomps.c:73
@ RGBA_DOUBLE
Definition color.h:27
#define COLOR_OK
Definition color.h:44
float palette_pastel[1001][3]
float palette_blue_to_yellow[1001][3]
float palette_adam_blend[1001][3]
float palette_grey[1001][3]
float palette_sequential_singlehue_red_lighter[1001][3]
float palette_sequential_singlehue_red[1001][3]
float palette_primary[1001][3]
float palette_white_to_red[1001][3]
float palette_grey_to_red[1001][3]
float palette_adam[11][3]
@ MAX_COLOR
void rgb2hex(float r, float g, float b, agxbuf *cstring, const char *opacity)
Definition colorutil.c:21
void colorxlate(char *str, agxbuf *buf)
Definition colxlate.c:48
static NORETURN void graphviz_exit(int status)
Definition exit.h:23
expr procedure type
Definition exparse.y:211
#define A(n, t)
Definition expr.h:76
#define I
Definition expr.h:71
#define POINTS(a_inches)
Definition geom.h:68
static int Verbose
Definition gml2gv.c:22
void free(void *)
node NULL
Definition grammar.y:149
int agnedges(Agraph_t *g)
Definition graph.c:164
int agnnodes(Agraph_t *g)
Definition graph.c:158
Agsym_t * agattr(Agraph_t *g, int kind, char *name, const char *value)
creates or looks up attributes of a graph
Definition attr.c:341
int agxset(void *obj, Agsym_t *sym, const char *value)
Definition attr.c:481
char * agget(void *obj, char *name)
Definition attr.c:442
char * agxget(void *obj, Agsym_t *sym)
Definition attr.c:458
Agedge_t * agfstout(Agraph_t *g, Agnode_t *n)
Definition edge.c:23
#define aghead(e)
Definition cgraph.h:890
Agedge_t * agnxtout(Agraph_t *g, Agedge_t *e)
Definition edge.c:38
void agerrorf(const char *fmt,...)
Definition agerror.c:165
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
char * agnameof(void *)
returns a string descriptor for the object.
Definition id.c:158
@ AGEDGE
Definition cgraph.h:207
@ AGNODE
Definition cgraph.h:207
void aginit(Agraph_t *g, int kind, const char *rec_name, int rec_size, int move_to_front)
attach new records to objects of specified kind
Definition rec.c:169
Agraph_t * agfstsubg(Agraph_t *g)
Definition subg.c:77
Agraph_t * agnxtsubg(Agraph_t *subg)
Definition subg.c:82
static void color(Agraph_t *g)
Definition gvcolor.c:128
GVIO_API const char * format
Definition gvio.h:51
rows row
Definition htmlparse.y:524
void mq_clustering(SparseMatrix A, int maxcluster, int *nclusters, int **assignment, double *mq)
Definition mq.c:583
static int nedges
total no. of edges used in routing
Definition routespl.c:31
static bool startswith(const char *s, const char *prefix)
does the string s begin with the string prefix?
Definition startswith.h:11
unsigned int id
Definition DotIO.c:28
graph or subgraph
Definition cgraph.h:425
implementation of Agrec_t
Definition cgraph.h:172
string attribute descriptor symbol in Agattr_s.dict
Definition cgraph.h:639
#define UNREACHABLE()
Definition unreachable.h:30
#define MAX(a, b)
Definition write.c:31