Graphviz 13.0.0~dev.20250511.0440
Loading...
Searching...
No Matches
topfisheyeview.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#include "topfisheyeview.h"
11#include <math.h>
12#include "viewport.h"
13#include "viewportcamera.h"
14#include "draw.h"
15#include "smyrna_utils.h"
16
17#include <assert.h>
18#include "hier.h"
19#include "topfisheyeview.h"
20#include <string.h>
21#include <common/color.h>
22#include <common/colorprocs.h>
23#include <util/alloc.h>
24
25static int get_temp_coords(topview * t, int level, int v, double *coord_x,
26 double *coord_y);
27
28static int color_interpolation(glCompColor srcColor, glCompColor tarColor,
29 glCompColor * color, int levelcount,
30 int level)
31{
32 if (levelcount <= 0)
33 return -1;
34
35
36 color->R =
37 ((float) level * tarColor.R - (float) level * srcColor.R +
38 (float) levelcount * srcColor.R) / (float) levelcount;
39 color->G =
40 ((float) level * tarColor.G - (float) level * srcColor.G +
41 (float) levelcount * srcColor.G) / (float) levelcount;
42 color->B =
43 ((float) level * tarColor.B - (float) level * srcColor.B +
44 (float) levelcount * srcColor.B) / (float) levelcount;
45 return 0;
46}
47
48static v_data *makeGraph(Agraph_t* gg, int *nedges)
49{
50 int i;
51 int ne = agnedges(gg);
52 int nv = agnnodes(gg);
53 v_data *graph = gv_calloc(nv, sizeof(v_data));
54 int *edges = gv_calloc(2 * ne + nv, sizeof(int)); /* reserve space for self loops */
55 float *ewgts = gv_calloc(2 * ne + nv, sizeof(float));
56 Agnode_t *np;
57 Agedge_t *ep;
58 Agraph_t *g = NULL;
59 int i_nedges;
60 ne = 0;
61 i=0;
62 for (np = agfstnode(gg); np; np = agnxtnode(gg, np))
63 {
64 graph[i].edges = edges++; /* reserve space for the self loop */
65 graph[i].ewgts = ewgts++;
66 i_nedges = 1; /* one for the self */
67
68 if (!g)
69 g = agraphof(np);
70 for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np))
71 {
72 Agnode_t *vp;
73 Agnode_t *tp = agtail(ep);
74 Agnode_t *hp = aghead(ep);
75 assert(hp != tp);
76 /* FIX: handle multiedges */
77 vp = tp == np ? hp : tp;
78 ne++;
79 i_nedges++;
80 *edges++ = ND_TVref(vp);
81 *ewgts++ = 1;
82
83 }
84
85 graph[i].nedges = i_nedges;
86 graph[i].edges[0] = i;
87 graph[i].ewgts[0] = 1 - i_nedges;
88 i++;
89 }
90 ne /= 2; /* each edge counted twice */
91 *nedges = ne;
92 return graph;
93}
94
96{
97 int level, v;
98 Hierarchy *hp = t->fisheyeParams.h;
99 for (level = 0; level < hp->nlevels; level++) {
100 for (v = 0; v < hp->nvtxs[level]; v++) {
101 ex_vtx_data *gg = hp->geom_graphs[level];
104 gg[v].old_active_level = gg[v].active_level;
105 }
106 }
107
108}
109
110/* To use:
111 * double* x_coords; // initial x coordinates
112 * double* y_coords; // initial y coordinates
113 * focus_t* fs;
114 * int ne;
115 * v_data* graph = makeGraph (topview*, &ne);
116 * hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
117 * freeGraph (graph);
118 * fs = initFocus (topview->Nodecount); // create focus set
119 */
121{
122 double *x_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial x coordinates
123 double *y_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial y coordinates
124 focus_t *fs;
125 int ne;
126 int i;
127 int closest_fine_node;
128 int cur_level = 0;
129 Hierarchy *hp;
130 gvcolor_t cl;
131 Agnode_t *np;
132
133 v_data *graph = makeGraph(g, &ne);
134
135 i=0;
136 for (np = agfstnode(g); np; np = agnxtnode(g, np))
137 {
138 x_coords[i]=ND_A(np).x;
139 y_coords[i]=ND_A(np).y;
140 i++;
141 }
142 hp = t->fisheyeParams.h =
143 makeHier(agnnodes(g), ne, graph, x_coords, y_coords,
146 free(x_coords);
147 free(y_coords);
148
149 fs = t->fisheyeParams.fs = initFocus(agnnodes(g)); // create focus set
150
151 closest_fine_node = 0; /* first node */
152 fs->num_foci = 1;
153 fs->foci_nodes[0] = closest_fine_node;
154 fs->x_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].x_coord;
155 fs->y_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].y_coord;
156
158 (int) (view->bdxRight - view->bdxLeft);
160 (int) (view->bdyTop - view->bdyBottom);
161
162 //topological fisheye
163
165 ("topologicalfisheyefinestcolor", view,
166 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
167 view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
168 view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
169 view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
171 ("topologicalfisheyecoarsestcolor", view,
172 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
173 view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
174 view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
175 view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
176
177
178 sscanf(agget
180 "topologicalfisheyedistortionfactor"), "%lf",
182 sscanf(agget
183 (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
185 sscanf(agget
187 "topologicalfisheyecoarseningfactor"), "%lf",
189 int dist2_limit = 0;
190 sscanf(agget
191 (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
192 "%d", &dist2_limit);
193 view->Topview->fisheyeParams.dist2_limit = dist2_limit != 0;
194 sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
196
200}
201
202static void drawtopfishnodes(topview * t)
203{
205 int level, v;
206 Hierarchy *hp = t->fisheyeParams.h;
207 static int max_visible_level = 0;
208 const glCompColor srcColor = view->Topview->fisheyeParams.srcColor;
209 const glCompColor tarColor = view->Topview->fisheyeParams.tarColor;
210
211 //drawing nodes
212 glPointSize(7);
213 level = 0;
214 glBegin(GL_POINTS);
215 for (level = 0; level < hp->nlevels; level++) {
216 for (v = 0; v < hp->nvtxs[level]; v++) {
217 double x0, y0;
218 if (get_temp_coords(t, level, v, &x0, &y0)) {
219
220 if (!(-x0 / view->zoom > view->clipX1 && -x0 / view->zoom < view->clipX2 &&
221 -y0 / view->zoom > view->clipY1 && -y0 / view->zoom < view->clipY2))
222 continue;
223
224 if (max_visible_level < level)
225 max_visible_level = level;
226 if (color_interpolation(srcColor, tarColor, &color, max_visible_level, level)
227 != 0) {
228 continue;
229 }
230 glColor4f(color.R, color.G, color.B, view->defaultnodealpha);
231
232 glVertex3f((float)x0, (float)y0, 0.0f);
233 }
234 }
235 }
236 glEnd();
237
238}
239
240static void drawtopfishedges(topview * t)
241{
243
244 int level, v, i, n;
245 Hierarchy *hp = t->fisheyeParams.h;
246 static int max_visible_level = 0;
247 const glCompColor srcColor = view->Topview->fisheyeParams.srcColor;
248 const glCompColor tarColor = view->Topview->fisheyeParams.tarColor;
249
250 //and edges
251 glBegin(GL_LINES);
252 for (level = 0; level < hp->nlevels; level++) {
253 for (v = 0; v < hp->nvtxs[level]; v++) {
254 v_data *g = hp->graphs[level];
255 double x0, y0;
256 if (get_temp_coords(t, level, v, &x0, &y0)) {
257 for (i = 1; i < g[v].nedges; i++) {
258 double x, y;
259 n = g[v].edges[i];
260
261
262 if (max_visible_level < level)
263 max_visible_level = level;
264 if (color_interpolation(srcColor, tarColor, &color, max_visible_level,
265 level) != 0) {
266 continue;
267 }
268 glColor4f(color.R, color.G, color.B, view->defaultnodealpha);
269
270 if (get_temp_coords(t, level, n, &x, &y)) {
271 glVertex3f((float)x0, (float)y0, 0.0f);
272 glVertex3f((float)x, (float)y, 0.0f);
273 } else
274 {
275 int levell, nodee;
276 find_active_ancestor_info(hp, level, n, &levell,
277 &nodee);
278 if (get_temp_coords(t, levell, nodee, &x, &y)) {
279
280 if (!(-x0 / view->zoom > view->clipX1
281 && -x0 / view->zoom < view->clipX2
282 && -y0 / view->zoom > view->clipY1
283 && -y0 / view->zoom < view->clipY2)
284 && !(-x / view->zoom > view->clipX1
285 && -x / view->zoom < view->clipX2
286 && -y / view->zoom > view->clipY1
287 && -y / view->zoom < view->clipY2))
288
289 continue;
290
291
292 glVertex3f((float)x0, (float)y0, 0.0f);
293 glVertex3f((float)x, (float)y, 0.0f);
294 }
295 }
296 }
297 }
298 }
299 }
300 glEnd();
301
302}
303
304static int get_active_frame(void)
305{
306 int fr;
307 gdouble seconds = g_timer_elapsed(view->timer, NULL);
308 fr = (int)(seconds * 1000.0);
309 if (fr < view->total_frames) {
310
311 if (fr == view->active_frame)
312 return 0;
313 else {
314 view->active_frame = fr;
315 return 1;
316 }
317 } else {
318 g_timer_stop(view->timer);
320 return 0;
321 }
322
323}
324
331
332static void get_interpolated_coords(double x0, double y0, double x1, double y1,
333 int fr, int total_fr, double *x, double *y)
334{
335 *x = x0 + (x1 - x0) / (double) total_fr *(double) (fr + 1);
336 *y = y0 + (y1 - y0) / (double) total_fr *(double) (fr + 1);
337}
338
339static int get_temp_coords(topview * t, int level, int v, double *coord_x,
340 double *coord_y)
341{
342 Hierarchy *hp = t->fisheyeParams.h;
343 ex_vtx_data *gg = hp->geom_graphs[level];
344
345 if (!t->fisheyeParams.animate) {
346 if (gg[v].active_level != level)
347 return 0;
348
349 *coord_x = gg[v].physical_x_coord;
350 *coord_y = gg[v].physical_y_coord;
351 } else {
352
353
354 double x0, y0, x1, y1;
355 int OAL, AL;
356
357 x0 = 0;
358 y0 = 0;
359 x1 = 0;
360 y1 = 0;
361 AL = gg[v].active_level;
362 OAL = gg[v].old_active_level;
363
364 if (OAL < level || AL < level) //no draw
365 return 0;
366 if (OAL >= level || AL >= level) //draw the node
367 {
368 if (OAL == level && AL == level) //draw as is from old coords to new)
369 {
370 x0 = gg[v].old_physical_x_coord;
371 y0 = gg[v].old_physical_y_coord;
372 x1 = gg[v].physical_x_coord;
373 y1 = gg[v].physical_y_coord;
374 }
375 if (OAL > level && AL == level) //draw as from ancs to new)
376 {
377 find_old_physical_coords(t->fisheyeParams.h, level, v, &x0, &y0);
378 x1 = gg[v].physical_x_coord;
379 y1 = gg[v].physical_y_coord;
380 }
381 if (OAL == level && AL > level) //draw as from ancs to new)
382 {
383 find_physical_coords(t->fisheyeParams.h, level, v, &x1, &y1);
384 x0 = gg[v].old_physical_x_coord;
385 y0 = gg[v].old_physical_y_coord;
386 }
388 view->total_frames, coord_x, coord_y);
389 if (x0 == 0 || x1 == 0)
390 return 0;
391
392 }
393 }
394 return 1;
395}
396
397void changetopfishfocus(topview * t, float *x, float *y, int num_foci)
398{
399
400 gvcolor_t cl;
401 focus_t *fs = t->fisheyeParams.fs;
402 int i;
403 int closest_fine_node;
404 int cur_level = 0;
405
406 Hierarchy *hp = t->fisheyeParams.h;
408 fs->num_foci = num_foci;
409 for (i = 0; i < num_foci; i++) {
410 find_closest_active_node(hp, x[i], y[i], &closest_fine_node);
411 fs->foci_nodes[i] = closest_fine_node;
412 fs->x_foci[i] =
413 hp->geom_graphs[cur_level][closest_fine_node].x_coord;
414 fs->y_foci[i] =
415 hp->geom_graphs[cur_level][closest_fine_node].y_coord;
416 }
417
418
420 (int) (view->bdxRight - view->bdxLeft);
422 (int) (view->bdyTop - view->bdyBottom);
423
425 ("topologicalfisheyefinestcolor", view,
426 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
427 view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
428 view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
429 view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
431 ("topologicalfisheyecoarsestcolor", view,
432 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
433 view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
434 view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
435 view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
436
437
438
439 sscanf(agget
441 "topologicalfisheyedistortionfactor"), "%lf",
443 sscanf(agget
444 (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
446 sscanf(agget
448 "topologicalfisheyecoarseningfactor"), "%lf",
450 int dist2_limit = 0;
451 sscanf(agget
452 (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
453 "%d", &dist2_limit);
454 view->Topview->fisheyeParams.dist2_limit = dist2_limit != 0;
455 sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
457
459
461
463
464 if (t->fisheyeParams.animate) {
465 view->active_frame = 0;
466 g_timer_start(view->timer);
467 }
468
469}
Memory allocation wrappers that exit on failure.
static void * gv_calloc(size_t nmemb, size_t size)
Definition alloc.h:26
@ RGBA_DOUBLE
Definition color.h:27
void colorxlate(char *str, agxbuf *buf)
Definition colxlate.c:46
void freeGraph(v_data *graph)
Definition delaunay.c:823
void free(void *)
node NULL
Definition grammar.y:163
int agnedges(Agraph_t *g)
Definition graph.c:165
int agnnodes(Agraph_t *g)
Definition graph.c:159
char * agget(void *obj, char *name)
Definition attr.c:472
#define agtail(e)
Definition cgraph.h:986
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:94
#define aghead(e)
Definition cgraph.h:987
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:85
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:47
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:40
Agraph_t * agraphof(void *obj)
Definition obj.c:185
Agraph_t * graph(char *name)
Definition gv.cpp:30
static void color(Agraph_t *g)
Definition gvcolor.c:129
Hierarchy * makeHier(int nn, int ne, v_data *graph, double *x_coords, double *y_coords, bool dist2_limit)
Definition hier.c:100
void positionAllItems(Hierarchy *hp, focus_t *fs, reposition_t *parms)
Definition hier.c:19
focus_t * initFocus(int ncnt)
Definition hier.c:130
void set_active_levels(Hierarchy *hierarchy, int *foci_nodes, int num_foci, levelparms_t *parms)
Definition hierarchy.c:753
double find_closest_active_node(Hierarchy *hierarchy, double x, double y, int *closest_fine_node)
Definition hierarchy.c:929
void find_active_ancestor_info(Hierarchy *hierarchy, int level, int node, int *levell, int *nodee)
Definition hierarchy.c:1078
void find_old_physical_coords(Hierarchy *hierarchy, int level, int node, double *x, double *y)
Definition hierarchy.c:1097
void find_physical_coords(Hierarchy *hierarchy, int level, int node, double *x, double *y)
Definition hierarchy.c:1064
static int nedges
total no. of edges used in routing
Definition routespl.c:31
ViewInfo * view
Definition viewport.c:37
#define ND_TVref(n)
Definition smyrnadefs.h:165
#define ND_A(n)
Definition smyrnadefs.h:163
graph or subgraph
Definition cgraph.h:424
v_data ** graphs
Definition hierarchy.h:41
int * nvtxs
Definition hierarchy.h:43
ex_vtx_data ** geom_graphs
Definition hierarchy.h:42
int nlevels
Definition hierarchy.h:40
float bdxLeft
Definition smyrnadefs.h:289
int active_frame
Definition smyrnadefs.h:319
topview * Topview
Definition smyrnadefs.h:312
Agraph_t ** g
Definition smyrnadefs.h:295
int total_frames
Definition smyrnadefs.h:320
float clipX2
Definition smyrnadefs.h:260
float bdyTop
Definition smyrnadefs.h:289
GTimer * timer
Definition smyrnadefs.h:314
int activeGraph
Definition smyrnadefs.h:299
float bdxRight
Definition smyrnadefs.h:290
float bdyBottom
Definition smyrnadefs.h:290
float zoom
Definition smyrnadefs.h:257
float clipY1
Definition smyrnadefs.h:260
float clipX1
Definition smyrnadefs.h:260
float clipY2
Definition smyrnadefs.h:260
float defaultnodealpha
Definition smyrnadefs.h:275
double RGBA[4]
Definition color.h:32
union color_s::@72 u
float physical_y_coord
Definition hierarchy.h:30
float old_physical_y_coord
Definition hierarchy.h:33
float old_physical_x_coord
Definition hierarchy.h:32
int old_active_level
Definition hierarchy.h:34
float physical_x_coord
Definition hierarchy.h:29
float x_coord
Definition hierarchy.h:25
int active_level
Definition hierarchy.h:21
float y_coord
Definition hierarchy.h:26
Definition hier.h:16
int * foci_nodes
Definition hier.h:18
int num_foci
Definition hier.h:17
double * y_foci
Definition hier.h:20
double * x_foci
Definition hier.h:19
int num_fine_nodes
Definition hierarchy.h:57
double coarsening_rate
Definition hierarchy.h:58
double distortion
Definition hier.h:27
int height
Definition hier.h:26
int width
Definition hier.h:25
struct topview::@56 fisheyeParams
int animate
Definition smyrnadefs.h:228
Hierarchy * h
Definition smyrnadefs.h:227
glCompColor srcColor
Definition smyrnadefs.h:229
reposition_t repos
Definition smyrnadefs.h:222
focus_t * fs
Definition smyrnadefs.h:231
bool dist2_limit
Definition smyrnadefs.h:226
size_t Nodecount
Definition smyrnadefs.h:219
levelparms_t level
Definition smyrnadefs.h:223
glCompColor tarColor
Definition smyrnadefs.h:230
int nedges
Definition sparsegraph.h:22
int * edges
Definition sparsegraph.h:23
static void get_interpolated_coords(double x0, double y0, double x1, double y1, int fr, int total_fr, double *x, double *y)
void changetopfishfocus(topview *t, float *x, float *y, int num_foci)
static void refresh_old_values(topview *t)
static int color_interpolation(glCompColor srcColor, glCompColor tarColor, glCompColor *color, int levelcount, int level)
static void drawtopfishedges(topview *t)
static int get_temp_coords(topview *t, int level, int v, double *coord_x, double *coord_y)
static void drawtopfishnodes(topview *t)
static int get_active_frame(void)
void drawtopologicalfisheye(topview *t)
void prepare_topological_fisheye(Agraph_t *g, topview *t)
static v_data * makeGraph(Agraph_t *gg, int *nedges)
char * get_attribute_value(char *attr, ViewInfo *vi, Agraph_t *g)
Definition viewport.c:77