|
Graphviz
2.29.20120524.0446
|
00001 /* $Id$ $Revision$ */ 00002 /* vim:set shiftwidth=4 ts=8: */ 00003 00004 /************************************************************************* 00005 * Copyright (c) 2011 AT&T Intellectual Property 00006 * All rights reserved. This program and the accompanying materials 00007 * are made available under the terms of the Eclipse Public License v1.0 00008 * which accompanies this distribution, and is available at 00009 * http://www.eclipse.org/legal/epl-v10.html 00010 * 00011 * Contributors: See CVS logs. Details at http://www.graphviz.org/ 00012 *************************************************************************/ 00013 00014 00015 /* 00016 * Written by Emden R. Gansner 00017 * Derived from Graham Wills' algorithm described in GD'97. 00018 */ 00019 00020 #include "circle.h" 00021 #include "adjust.h" 00022 #include "pack.h" 00023 #include "neatoprocs.h" 00024 00025 static void twopi_init_edge(edge_t * e) 00026 { 00027 #ifdef WITH_CGRAPH 00028 agbindrec(e, "Agedgeinfo_t", sizeof(Agedgeinfo_t), TRUE); //edge custom data 00029 #endif /* WITH_CGRAPH */ 00030 common_init_edge(e); 00031 ED_factor(e) = late_double(e, E_weight, 1.0, 0.0); 00032 } 00033 00034 static void twopi_init_node_edge(graph_t * g) 00035 { 00036 node_t *n; 00037 edge_t *e; 00038 int i = 0; 00039 int n_nodes = agnnodes(g); 00040 rdata* alg; 00041 00042 alg = N_NEW(n_nodes, rdata); 00043 GD_neato_nlist(g) = N_NEW(n_nodes + 1, node_t *); 00044 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00045 neato_init_node(n); 00046 ND_alg(n) = alg + i; 00047 GD_neato_nlist(g)[i++] = n; 00048 } 00049 for (n = agfstnode(g); n; n = agnxtnode(g, n)) { 00050 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00051 twopi_init_edge(e); 00052 } 00053 } 00054 } 00055 00056 static void scaleGraph (graph_t * g, node_t* root, pointf sc) 00057 { 00058 pointf ctr; 00059 node_t* n; 00060 00061 ctr.x = ND_pos(root)[0]; 00062 ctr.y = ND_pos(root)[1]; 00063 00064 for (n = agfstnode(g); n; n = agnxtnode (g, n)) { 00065 if (n == root) continue; 00066 ND_pos(n)[0] = sc.x*(ND_pos(n)[0] - ctr.x) + ctr.x; 00067 ND_pos(n)[1] = sc.y*(ND_pos(n)[1] - ctr.y) + ctr.y; 00068 } 00069 } 00070 00071 void twopi_init_graph(graph_t * g) 00072 { 00073 setEdgeType (g, ET_LINE); 00074 /* GD_ndim(g) = late_int(g,agfindgraphattr(g,"dim"),2,2); */ 00075 Ndim = GD_ndim(g)=2; /* The algorithm only makes sense in 2D */ 00076 twopi_init_node_edge(g); 00077 } 00078 00079 /* twopi_layout: 00080 */ 00081 void twopi_layout(Agraph_t * g) 00082 { 00083 Agnode_t *ctr = 0; 00084 char *s; 00085 int setRoot = 0; 00086 pointf sc; 00087 int doScale = 0; 00088 int r; 00089 00090 if (agnnodes(g) == 0) return; 00091 00092 twopi_init_graph(g); 00093 s = agget(g, "root"); 00094 if ((s = agget(g, "root"))) { 00095 if (*s) { 00096 ctr = agfindnode(g, s); 00097 if (!ctr) { 00098 agerr(AGWARN, "specified root node \"%s\" was not found.", s); 00099 agerr(AGPREV, "Using default calculation for root node\n"); 00100 setRoot = 1; 00101 } 00102 } 00103 else { 00104 setRoot = 1; 00105 } 00106 } 00107 00108 if ((s = agget(g, "scale")) && *s) { 00109 if ((r = sscanf (s, "%lf,%lf",&sc.x,&sc.y))) { 00110 if (r == 1) sc.y = sc.x; 00111 doScale = 1; 00112 if (Verbose) 00113 fprintf (stderr, "scale = (%f,%f)\n", sc.x, sc.y); 00114 } 00115 } 00116 00117 if (agnnodes(g)) { 00118 Agraph_t **ccs; 00119 Agraph_t *sg; 00120 Agnode_t *c = NULL; 00121 Agnode_t *n; 00122 int ncc; 00123 int i; 00124 00125 ccs = ccomps(g, &ncc, 0); 00126 if (ncc == 1) { 00127 c = circleLayout(g, ctr); 00128 if (setRoot && !ctr) 00129 ctr = c; 00130 n = agfstnode(g); 00131 free(ND_alg(n)); 00132 ND_alg(n) = NULL; 00133 if (doScale) 00134 scaleGraph (g, c, sc); 00135 adjustNodes(g); 00136 spline_edges(g); 00137 } else { 00138 pack_info pinfo; 00139 getPackInfo (g, l_node, CL_OFFSET, &pinfo); 00140 pinfo.doSplines = 0; 00141 00142 for (i = 0; i < ncc; i++) { 00143 sg = ccs[i]; 00144 if (ctr && agcontains(sg, ctr)) 00145 c = ctr; 00146 else 00147 c = 0; 00148 nodeInduce(sg); 00149 c = circleLayout(sg, c); 00150 if (setRoot && !ctr) 00151 ctr = c; 00152 if (doScale) 00153 scaleGraph (sg, c, sc); 00154 adjustNodes(sg); 00155 } 00156 n = agfstnode(g); 00157 free(ND_alg(n)); 00158 ND_alg(n) = NULL; 00159 packSubgraphs(ncc, ccs, g, &pinfo); 00160 spline_edges(g); 00161 } 00162 for (i = 0; i < ncc; i++) { 00163 agdelete(g, ccs[i]); 00164 } 00165 free(ccs); 00166 } 00167 if (setRoot) 00168 agset (g, "root", agnameof (ctr)); 00169 dotneato_postprocess(g); 00170 00171 } 00172 00173 static void twopi_cleanup_graph(graph_t * g) 00174 { 00175 free(GD_neato_nlist(g)); 00176 if (g != agroot(g)) 00177 #ifndef WITH_CGRAPH 00178 memset(&(g->u), 0, sizeof(Agraphinfo_t)); 00179 #else /* WITH_CGRAPH */ 00180 agclean(g,AGRAPH,"Agraphinfo_t"); 00181 #endif /* WITH_CGRAPH */ 00182 } 00183 00184 /* twopi_cleanup: 00185 * The ND_alg data used by twopi is freed in twopi_layout 00186 * before edge routing as edge routing may use this field. 00187 */ 00188 void twopi_cleanup(graph_t * g) 00189 { 00190 node_t *n; 00191 edge_t *e; 00192 00193 n = agfstnode (g); 00194 if (!n) return; /* empty graph */ 00195 /* free (ND_alg(n)); */ 00196 for (; n; n = agnxtnode(g, n)) { 00197 for (e = agfstout(g, n); e; e = agnxtout(g, e)) { 00198 gv_cleanup_edge(e); 00199 } 00200 gv_cleanup_node(n); 00201 } 00202 twopi_cleanup_graph(g); 00203 }
1.7.5