1 | /* $Id$ $Revision$ */ |
2 | /* vim:set shiftwidth=4 ts=8: */ |
3 | |
4 | /************************************************************************* |
5 | * Copyright (c) 2011 AT&T Intellectual Property |
6 | * All rights reserved. This program and the accompanying materials |
7 | * are made available under the terms of the Eclipse Public License v1.0 |
8 | * which accompanies this distribution, and is available at |
9 | * http://www.eclipse.org/legal/epl-v10.html |
10 | * |
11 | * Contributors: See CVS logs. Details at http://www.graphviz.org/ |
12 | *************************************************************************/ |
13 | |
14 | |
15 | /* fdpinit.c: |
16 | * Written by Emden R. Gansner |
17 | * |
18 | * Mostly boilerplate initialization and cleanup code. |
19 | */ |
20 | |
21 | /* uses PRIVATE interface */ |
22 | #define FDP_PRIVATE 1 |
23 | |
24 | #include "tlayout.h" |
25 | #include "neatoprocs.h" |
26 | #include "agxbuf.h" |
27 | |
28 | static void initialPositions(graph_t * g) |
29 | { |
30 | int i; |
31 | node_t *np; |
32 | attrsym_t *possym; |
33 | attrsym_t *pinsym; |
34 | double *pvec; |
35 | char *p; |
36 | char c; |
37 | |
38 | possym = agattr(g,AGNODE, "pos" , NULL); |
39 | if (!possym) |
40 | return; |
41 | pinsym = agattr(g,AGNODE, "pin" , NULL); |
42 | for (i = 0; (np = GD_neato_nlist(g)[i]); i++) { |
43 | p = agxget(np, possym); |
44 | if (p[0]) { |
45 | pvec = ND_pos(np); |
46 | c = '\0'; |
47 | if (sscanf(p, "%lf,%lf%c" , pvec, pvec + 1, &c) >= 2) { |
48 | if (PSinputscale > 0.0) { |
49 | int j; |
50 | for (j = 0; j < NDIM; j++) |
51 | pvec[j] = pvec[j] / PSinputscale; |
52 | } |
53 | ND_pinned(np) = P_SET; |
54 | if ((c == '!') |
55 | || (pinsym && mapbool(agxget(np, pinsym)))) |
56 | ND_pinned(np) = P_PIN; |
57 | } else |
58 | fprintf(stderr, |
59 | "Warning: node %s, position %s, expected two floats\n" , |
60 | agnameof(np), p); |
61 | } |
62 | } |
63 | } |
64 | |
65 | /* init_edge: |
66 | */ |
67 | static void init_edge(edge_t * e, attrsym_t * E_len) |
68 | { |
69 | agbindrec(e, "Agedgeinfo_t" , sizeof(Agedgeinfo_t), TRUE); //node custom data |
70 | ED_factor(e) = late_double(e, E_weight, 1.0, 0.0); |
71 | ED_dist(e) = late_double(e, E_len, fdp_parms->K, 0.0); |
72 | |
73 | common_init_edge(e); |
74 | } |
75 | |
76 | static void init_node(node_t * n) |
77 | { |
78 | common_init_node(n); |
79 | ND_pos(n) = N_NEW(GD_ndim(agraphof(n)), double); |
80 | gv_nodesize(n, GD_flip(agraphof(n))); |
81 | } |
82 | |
83 | void fdp_init_node_edge(graph_t * g) |
84 | { |
85 | attrsym_t *E_len; |
86 | node_t *n; |
87 | edge_t *e; |
88 | int nn; |
89 | int i; |
90 | /* ndata* alg; */ |
91 | |
92 | aginit(g, AGNODE, "Agnodeinfo_t" , sizeof(Agnodeinfo_t), TRUE); |
93 | processClusterEdges(g); |
94 | |
95 | /* Get node count after processClusterEdges(), as this function may |
96 | * add new nodes. |
97 | */ |
98 | nn = agnnodes(g); |
99 | /* alg = N_NEW(nn, ndata); */ |
100 | GD_neato_nlist(g) = N_NEW(nn + 1, node_t *); |
101 | |
102 | for (i = 0, n = agfstnode(g); n; n = agnxtnode(g, n)) { |
103 | init_node (n); |
104 | /* ND_alg(n) = alg + i; */ |
105 | GD_neato_nlist(g)[i] = n; |
106 | ND_id(n) = i++; |
107 | } |
108 | |
109 | E_len = agattr(g,AGEDGE, "len" , NULL); |
110 | for (n = agfstnode(g); n; n = agnxtnode(g, n)) { |
111 | for (e = agfstout(g, n); e; e = agnxtout(g, e)) { |
112 | init_edge(e, E_len); |
113 | } |
114 | } |
115 | initialPositions(g); |
116 | |
117 | } |
118 | |
119 | static void cleanup_subgs(graph_t * g) |
120 | { |
121 | graph_t *subg; |
122 | int i; |
123 | |
124 | for (i = 1; i <= GD_n_cluster(g); i++) { |
125 | subg = GD_clust(g)[i]; |
126 | free_label(GD_label(subg)); |
127 | if (GD_alg(subg)) { |
128 | free(PORTS(subg)); |
129 | free(GD_alg(subg)); |
130 | } |
131 | cleanup_subgs(subg); |
132 | } |
133 | free (GD_clust(g)); |
134 | if (g != agroot(g)) |
135 | agdelrec(g, "Agraphinfo_t" ); |
136 | } |
137 | |
138 | static void fdp_cleanup_graph(graph_t * g) |
139 | { |
140 | cleanup_subgs(g); |
141 | free(GD_neato_nlist(g)); |
142 | free(GD_alg(g)); |
143 | } |
144 | |
145 | void fdp_cleanup(graph_t * g) |
146 | { |
147 | node_t *n; |
148 | edge_t *e; |
149 | |
150 | for (n = agfstnode(g); n; n = agnxtnode(g, n)) { |
151 | for (e = agfstout(g, n); e; e = agnxtout(g, e)) { |
152 | gv_cleanup_edge(e); |
153 | } |
154 | gv_cleanup_node(n); |
155 | } |
156 | fdp_cleanup_graph(g); |
157 | } |
158 | |