Graphviz 13.1.2~dev.20250807.2324
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, float *coord_x,
26 float *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 color->R = (level * tarColor.R - level * srcColor.R +
36 levelcount * srcColor.R) / levelcount;
37 color->G = (level * tarColor.G - level * srcColor.G +
38 levelcount * srcColor.G) / levelcount;
39 color->B = (level * tarColor.B - level * srcColor.B +
40 levelcount * srcColor.B) / levelcount;
41 return 0;
42}
43
44static v_data *makeGraph(Agraph_t* gg, int *nedges)
45{
46 int ne = agnedges(gg);
47 int nv = agnnodes(gg);
48 v_data *graph = gv_calloc(nv, sizeof(v_data));
49 int *edges = gv_calloc(2 * ne + nv, sizeof(int)); /* reserve space for self loops */
50 float *ewgts = gv_calloc(2 * ne + nv, sizeof(float));
51 Agraph_t *g = NULL;
52 ne = 0;
53 int i = 0;
54 for (Agnode_t *np = agfstnode(gg); np; np = agnxtnode(gg, np)) {
55 graph[i].edges = edges++; /* reserve space for the self loop */
56 graph[i].ewgts = ewgts++;
57 int i_nedges = 1; // one for the self
58
59 if (!g)
60 g = agraphof(np);
61 for (Agedge_t *ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) {
62 Agnode_t *tp = agtail(ep);
63 Agnode_t *hp = aghead(ep);
64 assert(hp != tp);
65 /* FIX: handle multiedges */
66 Agnode_t *const vp = tp == np ? hp : tp;
67 ne++;
68 i_nedges++;
69 *edges++ = ND_TVref(vp);
70 *ewgts++ = 1;
71
72 }
73
74 graph[i].nedges = i_nedges;
75 graph[i].edges[0] = i;
76 graph[i].ewgts[0] = 1 - i_nedges;
77 i++;
78 }
79 ne /= 2; /* each edge counted twice */
80 *nedges = ne;
81 return graph;
82}
83
85{
86 int level, v;
87 Hierarchy *hp = t->fisheyeParams.h;
88 for (level = 0; level < hp->nlevels; level++) {
89 for (v = 0; v < hp->nvtxs[level]; v++) {
90 ex_vtx_data *gg = hp->geom_graphs[level];
93 gg[v].old_active_level = gg[v].active_level;
94 }
95 }
96
97}
98
99/* To use:
100 * double* x_coords; // initial x coordinates
101 * double* y_coords; // initial y coordinates
102 * focus_t* fs;
103 * int ne;
104 * v_data* graph = makeGraph (topview*, &ne);
105 * hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
106 * freeGraph (graph);
107 * fs = initFocus (topview->Nodecount); // create focus set
108 */
110{
111 double *x_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial x coordinates
112 double *y_coords = gv_calloc(t->Nodecount, sizeof(double)); // initial y coordinates
113 focus_t *fs;
114 int ne;
115 int i;
116 int closest_fine_node;
117 int cur_level = 0;
118 Hierarchy *hp;
119 gvcolor_t cl;
120 Agnode_t *np;
121
122 v_data *graph = makeGraph(g, &ne);
123
124 i=0;
125 for (np = agfstnode(g); np; np = agnxtnode(g, np))
126 {
127 x_coords[i]=ND_A(np).x;
128 y_coords[i]=ND_A(np).y;
129 i++;
130 }
131 hp = t->fisheyeParams.h =
132 makeHier(agnnodes(g), ne, graph, x_coords, y_coords,
135 free(x_coords);
136 free(y_coords);
137
138 fs = t->fisheyeParams.fs = initFocus(agnnodes(g)); // create focus set
139
140 closest_fine_node = 0; /* first node */
141 fs->num_foci = 1;
142 fs->foci_nodes[0] = closest_fine_node;
143 fs->x_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].x_coord;
144 fs->y_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].y_coord;
145
147 round(view->bdxRight - view->bdxLeft);
149 round(view->bdyTop - view->bdyBottom);
150
151 //topological fisheye
152
154 ("topologicalfisheyefinestcolor", view,
155 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
160 ("topologicalfisheyecoarsestcolor", view,
161 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
165
166 sscanf(agget
168 "topologicalfisheyedistortionfactor"), "%lf",
170 sscanf(agget
171 (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
173 sscanf(agget
175 "topologicalfisheyecoarseningfactor"), "%lf",
177 int dist2_limit = 0;
178 sscanf(agget
179 (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
180 "%d", &dist2_limit);
181 view->Topview->fisheyeParams.dist2_limit = dist2_limit != 0;
182 sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
184
188}
189
190static void drawtopfishnodes(topview * t)
191{
193 int level, v;
194 Hierarchy *hp = t->fisheyeParams.h;
195 static int max_visible_level = 0;
196 const glCompColor srcColor = view->Topview->fisheyeParams.srcColor;
197 const glCompColor tarColor = view->Topview->fisheyeParams.tarColor;
198
199 //drawing nodes
200 glPointSize(7);
201 level = 0;
202 glBegin(GL_POINTS);
203 for (level = 0; level < hp->nlevels; level++) {
204 for (v = 0; v < hp->nvtxs[level]; v++) {
205 float x0, y0;
206 if (get_temp_coords(t, level, v, &x0, &y0)) {
207
208 if (!(-x0 / view->zoom > view->clipX1 && -x0 / view->zoom < view->clipX2 &&
209 -y0 / view->zoom > view->clipY1 && -y0 / view->zoom < view->clipY2))
210 continue;
211
212 if (max_visible_level < level)
213 max_visible_level = level;
214 if (color_interpolation(srcColor, tarColor, &color, max_visible_level, level)
215 != 0) {
216 continue;
217 }
218 glColor4d(color.R, color.G, color.B, view->defaultnodealpha);
219
220 glVertex3f(x0, y0, 0.0f);
221 }
222 }
223 }
224 glEnd();
225
226}
227
228static void drawtopfishedges(topview * t)
229{
231
232 int level, v, i, n;
233 Hierarchy *hp = t->fisheyeParams.h;
234 static int max_visible_level = 0;
235 const glCompColor srcColor = view->Topview->fisheyeParams.srcColor;
236 const glCompColor tarColor = view->Topview->fisheyeParams.tarColor;
237
238 //and edges
239 glBegin(GL_LINES);
240 for (level = 0; level < hp->nlevels; level++) {
241 for (v = 0; v < hp->nvtxs[level]; v++) {
242 v_data *g = hp->graphs[level];
243 float x0, y0;
244 if (get_temp_coords(t, level, v, &x0, &y0)) {
245 for (i = 1; i < g[v].nedges; i++) {
246 float x, y;
247 n = g[v].edges[i];
248
249
250 if (max_visible_level < level)
251 max_visible_level = level;
252 if (color_interpolation(srcColor, tarColor, &color, max_visible_level,
253 level) != 0) {
254 continue;
255 }
256 glColor4d(color.R, color.G, color.B, view->defaultnodealpha);
257
258 if (get_temp_coords(t, level, n, &x, &y)) {
259 glVertex3f(x0, y0, 0.0f);
260 glVertex3f(x, y, 0.0f);
261 } else
262 {
263 int levell, nodee;
264 find_active_ancestor_info(hp, level, n, &levell,
265 &nodee);
266 if (get_temp_coords(t, levell, nodee, &x, &y)) {
267
268 if (!(-x0 / view->zoom > view->clipX1
269 && -x0 / view->zoom < view->clipX2
270 && -y0 / view->zoom > view->clipY1
271 && -y0 / view->zoom < view->clipY2)
272 && !(-x / view->zoom > view->clipX1
273 && -x / view->zoom < view->clipX2
274 && -y / view->zoom > view->clipY1
275 && -y / view->zoom < view->clipY2))
276
277 continue;
278
279 glVertex3f(x0, y0, 0.0f);
280 glVertex3f(x, y, 0.0f);
281 }
282 }
283 }
284 }
285 }
286 }
287 glEnd();
288
289}
290
291static void get_active_frame(void) {
292 gdouble seconds = g_timer_elapsed(view->timer, NULL);
293 const int fr = (int)(seconds * 1000.0);
294 if (fr < view->total_frames) {
295 view->active_frame = fr;
296 return;
297 }
298 g_timer_stop(view->timer);
300}
301
308
309static void get_interpolated_coords(float x0, float y0, float x1, float y1,
310 int fr, int total_fr, float *x, float *y) {
311 *x = x0 + (x1 - x0) / (float)total_fr * (float)(fr + 1);
312 *y = y0 + (y1 - y0) / (float)total_fr * (float)(fr + 1);
313}
314
315static int get_temp_coords(topview *t, int level, int v, float *coord_x,
316 float *coord_y) {
317 Hierarchy *hp = t->fisheyeParams.h;
318 ex_vtx_data *gg = hp->geom_graphs[level];
319
320 if (!t->fisheyeParams.animate) {
321 if (gg[v].active_level != level)
322 return 0;
323
324 *coord_x = gg[v].physical_x_coord;
325 *coord_y = gg[v].physical_y_coord;
326 } else {
327
328
329 int OAL, AL;
330
331 float x0 = 0;
332 float y0 = 0;
333 float x1 = 0;
334 float y1 = 0;
335 AL = gg[v].active_level;
336 OAL = gg[v].old_active_level;
337
338 if (OAL < level || AL < level) //no draw
339 return 0;
340 if (OAL >= level || AL >= level) //draw the node
341 {
342 if (OAL == level && AL == level) //draw as is from old coords to new)
343 {
344 x0 = gg[v].old_physical_x_coord;
345 y0 = gg[v].old_physical_y_coord;
346 x1 = gg[v].physical_x_coord;
347 y1 = gg[v].physical_y_coord;
348 }
349 if (OAL > level && AL == level) //draw as from ancs to new)
350 {
351 find_old_physical_coords(t->fisheyeParams.h, level, v, &x0, &y0);
352 x1 = gg[v].physical_x_coord;
353 y1 = gg[v].physical_y_coord;
354 }
355 if (OAL == level && AL > level) //draw as from ancs to new)
356 {
357 find_physical_coords(t->fisheyeParams.h, level, v, &x1, &y1);
358 x0 = gg[v].old_physical_x_coord;
359 y0 = gg[v].old_physical_y_coord;
360 }
362 view->total_frames, coord_x, coord_y);
363 if (x0 == 0 || x1 == 0)
364 return 0;
365
366 }
367 }
368 return 1;
369}
370
371void changetopfishfocus(topview * t, float *x, float *y, int num_foci)
372{
373
374 gvcolor_t cl;
375 focus_t *fs = t->fisheyeParams.fs;
376 int i;
377 int closest_fine_node;
378 int cur_level = 0;
379
380 Hierarchy *hp = t->fisheyeParams.h;
382 fs->num_foci = num_foci;
383 for (i = 0; i < num_foci; i++) {
384 find_closest_active_node(hp, x[i], y[i], &closest_fine_node);
385 fs->foci_nodes[i] = closest_fine_node;
386 fs->x_foci[i] =
387 hp->geom_graphs[cur_level][closest_fine_node].x_coord;
388 fs->y_foci[i] =
389 hp->geom_graphs[cur_level][closest_fine_node].y_coord;
390 }
391
392
394 (int) (view->bdxRight - view->bdxLeft);
396 (int) (view->bdyTop - view->bdyBottom);
397
399 ("topologicalfisheyefinestcolor", view,
400 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
405 ("topologicalfisheyecoarsestcolor", view,
406 view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
410
411 sscanf(agget
413 "topologicalfisheyedistortionfactor"), "%lf",
415 sscanf(agget
416 (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
418 sscanf(agget
420 "topologicalfisheyecoarseningfactor"), "%lf",
422 int dist2_limit = 0;
423 sscanf(agget
424 (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
425 "%d", &dist2_limit);
426 view->Topview->fisheyeParams.dist2_limit = dist2_limit != 0;
427 sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
429
431
433
435
436 if (t->fisheyeParams.animate) {
437 view->active_frame = 0;
438 g_timer_start(view->timer);
439 }
440
441}
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:662
void free(void *)
node NULL
Definition grammar.y:180
int agnedges(Agraph_t *g)
Definition graph.c:161
int agnnodes(Agraph_t *g)
Definition graph.c:155
char * agget(void *obj, char *name)
Definition attr.c:448
#define agtail(e)
Definition cgraph.h:988
Agedge_t * agnxtedge(Agraph_t *g, Agedge_t *e, Agnode_t *n)
Definition edge.c:96
#define aghead(e)
Definition cgraph.h:989
Agedge_t * agfstedge(Agraph_t *g, Agnode_t *n)
Definition edge.c:87
Agnode_t * agnxtnode(Agraph_t *g, Agnode_t *n)
Definition node.c:48
Agnode_t * agfstnode(Agraph_t *g)
Definition node.c:41
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
void find_old_physical_coords(Hierarchy *hierarchy, int level, int node, float *x, float *y)
Definition hierarchy.c:1083
double find_closest_active_node(Hierarchy *hierarchy, double x, double y, int *closest_fine_node)
Definition hierarchy.c:918
void find_active_ancestor_info(Hierarchy *hierarchy, int level, int node, int *levell, int *nodee)
Definition hierarchy.c:1065
void find_physical_coords(Hierarchy *hierarchy, int level, int node, float *x, float *y)
Definition hierarchy.c:1052
static int nedges
total no. of edges used in routing
Definition routespl.c:32
ViewInfo * view
Definition viewport.c:37
#define ND_TVref(n)
Definition smyrnadefs.h:160
#define ND_A(n)
Definition smyrnadefs.h:158
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:314
topview * Topview
Definition smyrnadefs.h:307
Agraph_t ** g
Definition smyrnadefs.h:290
double bdxRight
Definition smyrnadefs.h:285
int total_frames
Definition smyrnadefs.h:315
float clipX2
Definition smyrnadefs.h:255
double bdyBottom
Definition smyrnadefs.h:285
double zoom
Definition smyrnadefs.h:252
double bdyTop
Definition smyrnadefs.h:284
GTimer * timer
Definition smyrnadefs.h:309
double defaultnodealpha
Definition smyrnadefs.h:270
int activeGraph
Definition smyrnadefs.h:294
double bdxLeft
Definition smyrnadefs.h:284
float clipY1
Definition smyrnadefs.h:255
float clipX1
Definition smyrnadefs.h:255
float clipY2
Definition smyrnadefs.h:255
double RGBA[4]
Definition color.h:32
union color_s::@74 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
double height
viewport height
Definition hier.h:26
double width
viewport width
Definition hier.h:25
struct topview::@56 fisheyeParams
int animate
Definition smyrnadefs.h:223
Hierarchy * h
Definition smyrnadefs.h:222
glCompColor srcColor
Definition smyrnadefs.h:224
reposition_t repos
Definition smyrnadefs.h:217
focus_t * fs
Definition smyrnadefs.h:226
bool dist2_limit
Definition smyrnadefs.h:221
size_t Nodecount
Definition smyrnadefs.h:214
levelparms_t level
Definition smyrnadefs.h:218
glCompColor tarColor
Definition smyrnadefs.h:225
int nedges
Definition sparsegraph.h:28
int * edges
Definition sparsegraph.h:29
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:77