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