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
28static 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 */
67static 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
76static 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
83void 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
119static 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
138static 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
145void 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