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 #include "topfisheyeview.h"
14 
15 //#include "glcomptext.h"
16 //#include "glcomptextpng.h"
17 #include "math.h"
18 #include "memory.h"
19 #include "viewport.h"
20 #include "viewportcamera.h"
21 #include "draw.h"
22 #include "smyrna_utils.h"
23 
24 #include "assert.h"
25 #include "hier.h"
26 #include "topfisheyeview.h"
27 #include <string.h>
28 #include "color.h"
29 #include "colorprocs.h"
30 
31 #ifdef _WIN32
32 #include <wincrypt.h>
33 #endif
34 
35 static int get_temp_coords(topview * t, int level, int v, double *coord_x,
36 			   double *coord_y);
37 #ifdef UNUSED
38 static int get_temp_coords2(topview * t, int level, int v, double *coord_x,
39 			    double *coord_y, float *R, float *G, float *B);
40 #endif
41 
color_interpolation(glCompColor srcColor,glCompColor tarColor,glCompColor * color,int levelcount,int level)42 static void color_interpolation(glCompColor srcColor, glCompColor tarColor,
43 				glCompColor * color, int levelcount,
44 				int level)
45 {
46     if (levelcount <= 0)
47 	return;
48 
49 
50     color->R =
51 	((float) level * tarColor.R - (float) level * srcColor.R +
52 	 (float) levelcount * srcColor.R) / (float) levelcount;
53     color->G =
54 	((float) level * tarColor.G - (float) level * srcColor.G +
55 	 (float) levelcount * srcColor.G) / (float) levelcount;
56     color->B =
57 	((float) level * tarColor.B - (float) level * srcColor.B +
58 	 (float) levelcount * srcColor.B) / (float) levelcount;
59 }
60 
61 #ifdef UNUSED
dist(double x1,double y1,double x2,double y2)62 static double dist(double x1, double y1, double x2, double y2)
63 {
64     return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
65 }
dist3d(double x1,double y1,double z1,double x2,double y2,double z2)66 static double dist3d(double x1, double y1, double z1, double x2, double y2,
67 		     double z2)
68 {
69     return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) +
70 		(z1 - z2) * (z1 - z2));
71 }
72 #endif
73 
74 #ifdef UNUSED
75 static void drawtopologicalfisheyestatic(topview * t);
76 #endif
77 
78 #ifdef UNUSED
79 
80 The code below now longer works. First, t->Nodes == NULL, since
81 we now rely on the libgraph graph for data. Second, the code that
82 drew the distorted view was left out of the move from topview.c
83 to topviewfuncs.c. The magnifiers were cute but not particularly
84 useful, so we leave the feature out for now.
85 
86 static double G(double x)
87 {
88     // distortion function for fisheye display
89     return (view->fmg.fisheye_distortion_fac +
90 	    1) * x / (view->fmg.fisheye_distortion_fac * x + 1);
91 }
92 
93 
fisheye_polar(double x_focus,double y_focus,topview * t)94 void fisheye_polar(double x_focus, double y_focus, topview * t)
95 {
96     int i;
97     double distance, distorted_distance, ratio, range;
98 
99     range = 0;
100     for (i = 1; i < t->Nodecount; i++) {
101 	if (point_within_ellips_with_coords
102 	    ((float) x_focus, (float) y_focus, (float) view->fmg.R,
103 	     (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y)) {
104 	    range = MAX(range,
105 			dist(t->Nodes[i].x, t->Nodes[i].y, x_focus,
106 			     y_focus));
107 	}
108     }
109 
110     for (i = 1; i < t->Nodecount; i++) {
111 
112 	if (point_within_ellips_with_coords
113 	    ((float) x_focus, (float) y_focus, (float) view->fmg.R,
114 	     (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y)) {
115 	    distance =
116 		dist(t->Nodes[i].x, t->Nodes[i].y, x_focus, y_focus);
117 	    distorted_distance = G(distance / range) * range;
118 	    if (distance != 0) {
119 		ratio = distorted_distance / distance;
120 	    } else {
121 		ratio = 0;
122 	    }
123 	    t->Nodes[i].distorted_x =
124 		(float) x_focus + (t->Nodes[i].x -
125 				   (float) x_focus) * (float) ratio;
126 	    t->Nodes[i].distorted_y =
127 		(float) y_focus + (t->Nodes[i].y -
128 				   (float) y_focus) * (float) ratio;
129 	    t->Nodes[i].zoom_factor =
130 		(float) 1 *(float) distorted_distance / (float) distance;
131 	} else {
132 	    t->Nodes[i].distorted_x = t->Nodes[i].x;
133 	    t->Nodes[i].distorted_y = t->Nodes[i].y;
134 	    t->Nodes[i].zoom_factor = 1;
135 	}
136     }
137 }
fisheye_spherical(double x_focus,double y_focus,double z_focus,topview * t)138 void fisheye_spherical(double x_focus, double y_focus, double z_focus,
139 		       topview * t)
140 {
141     int i;
142     double distance, distorted_distance, ratio, range;
143 
144     range = 0;
145     for (i = 1; i < t->Nodecount; i++) {
146 	if (point_within_sphere_with_coords
147 	    ((float) x_focus, (float) y_focus, (float) z_focus,
148 	     (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y,
149 	     t->Nodes[i].z)) {
150 
151 
152 	    range =
153 		MAX(range,
154 		    dist3d(t->Nodes[i].x, t->Nodes[i].y, t->Nodes[i].z,
155 			   x_focus, y_focus, z_focus));
156 	}
157     }
158 
159     for (i = 1; i < t->Nodecount; i++) {
160 
161 
162 	if (point_within_sphere_with_coords
163 	    ((float) x_focus, (float) y_focus, (float) z_focus,
164 	     (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y,
165 	     t->Nodes[i].z)) {
166 	    distance =
167 		dist3d(t->Nodes[i].x, t->Nodes[i].y, t->Nodes[i].z,
168 		       x_focus, y_focus, z_focus);
169 	    distorted_distance = G(distance / range) * range;
170 	    if (distance != 0) {
171 		ratio = distorted_distance / distance;
172 	    } else {
173 		ratio = 0;
174 	    }
175 	    t->Nodes[i].distorted_x =
176 		(float) x_focus + (t->Nodes[i].x -
177 				   (float) x_focus) * (float) ratio;
178 	    t->Nodes[i].distorted_y =
179 		(float) y_focus + (t->Nodes[i].y -
180 				   (float) y_focus) * (float) ratio;
181 	    t->Nodes[i].distorted_z =
182 		(float) z_focus + (t->Nodes[i].z -
183 				   (float) z_focus) * (float) ratio;
184 	    t->Nodes[i].zoom_factor =
185 		(float) 1 *(float) distorted_distance / (float) distance;
186 	} else {
187 	    t->Nodes[i].distorted_x = t->Nodes[i].x;
188 	    t->Nodes[i].distorted_y = t->Nodes[i].y;
189 	    t->Nodes[i].distorted_z = t->Nodes[i].z;
190 	    t->Nodes[i].zoom_factor = 1;
191 	}
192     }
193 }
194 #endif
195 
makeGraph(Agraph_t * gg,int * nedges)196 static v_data *makeGraph(Agraph_t* gg, int *nedges)
197 {
198     int i;
199     int ne = agnedges(gg);
200     int nv = agnnodes(gg);
201     v_data *graph = N_NEW(nv, v_data);
202     int *edges = N_NEW(2 * ne + nv, int);	/* reserve space for self loops */
203     float *ewgts = N_NEW(2 * ne + nv, float);
204     Agnode_t *np;
205     Agedge_t *ep;
206     Agraph_t *g = NULL;
207     int i_nedges;
208     ne = 0;
209     i=0;
210 //    for (i = 0; i < nv; i++) {
211     for (np = agfstnode(gg); np; np = agnxtnode(gg, np))
212     {
213 	graph[i].edges = edges++;	/* reserve space for the self loop */
214 	graph[i].ewgts = ewgts++;
215 #ifdef STYLES
216 	graph[i].styles = NULL;
217 #endif
218 	i_nedges = 1;		/* one for the self */
219 
220 	if (!g)
221 	    g = agraphof(np);
222 	for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np))
223 	{
224 	    Agnode_t *vp;
225 	    Agnode_t *tp = agtail(ep);
226 	    Agnode_t *hp = aghead(ep);
227 	    assert(hp != tp);
228 	    /* FIX: handle multiedges */
229 	    vp = (tp == np ? hp : tp);
230 	    ne++;
231 	    i_nedges++;
232 //	    *edges++ = ((temp_node_record *) AGDATA(vp))->TVref;
233 	    *edges++ = ND_TVref(vp);
234 	    *ewgts++ = 1;
235 
236 	}
237 
238 	graph[i].nedges = i_nedges;
239 	graph[i].edges[0] = i;
240 	graph[i].ewgts[0] = 1 - i_nedges;
241 	i++;
242     }
243     ne /= 2;			/* each edge counted twice */
244     *nedges = ne;
245     return graph;
246 }
247 
248 
249 
250 
251 #if 0
252 static v_data *makeGraph_old(topview * tv, int *nedges)
253 {
254     int i;
255     int ne = tv->Edgecount;	/* upper bound */
256     int nv = tv->Nodecount;
257     v_data *graph = N_NEW(nv, v_data);
258     int *edges = N_NEW(2 * ne + nv, int);	/* reserve space for self loops */
259     float *ewgts = N_NEW(2 * ne + nv, float);
260     Agnode_t *np;
261     Agedge_t *ep;
262     Agraph_t *g = NULL;
263     int i_nedges;
264 
265     ne = 0;
266     for (i = 0; i < nv; i++) {
267 	graph[i].edges = edges++;	/* reserve space for the self loop */
268 	graph[i].ewgts = ewgts++;
269 #ifdef STYLES
270 	graph[i].styles = NULL;
271 #endif
272 	i_nedges = 1;		/* one for the self */
273 
274 	np = tv->Nodes[i].Node;
275 	if (!g)
276 	    g = agraphof(np);
277 	for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np))
278 	{
279 	    Agnode_t *vp;
280 	    Agnode_t *tp = agtail(ep);
281 	    Agnode_t *hp = aghead(ep);
282 	    assert(hp != tp);
283 	    /* FIX: handle multiedges */
284 	    vp = (tp == np ? hp : tp);
285 	    ne++;
286 	    i_nedges++;
287 	    *edges++ = ((temp_node_record *) AGDATA(vp))->TVref;
288 	    *ewgts++ = 1;
289 	}
290 
291 	graph[i].nedges = i_nedges;
292 	graph[i].edges[0] = i;
293 	graph[i].ewgts[0] = 1 - i_nedges;
294     }
295     ne /= 2;			/* each edge counted twice */
296     *nedges = ne;
297     return graph;
298 }
299 #endif
300 
refresh_old_values(topview * t)301 static void refresh_old_values(topview * t)
302 {
303     int level, v;
304     Hierarchy *hp = t->fisheyeParams.h;
305     for (level = 0; level < hp->nlevels; level++) {
306 	for (v = 0; v < hp->nvtxs[level]; v++) {
307 	    ex_vtx_data *gg = hp->geom_graphs[level];
308 	    /* v_data *g = hp->graphs[level]; */
309 	    /* double x0,y0; */
310 	    gg[v].old_physical_x_coord = gg[v].physical_x_coord;
311 	    gg[v].old_physical_y_coord = gg[v].physical_y_coord;
312 	    gg[v].old_active_level = gg[v].active_level;
313 	}
314     }
315 
316 }
317 
318 /* To use:
319  * double* x_coords; // initial x coordinates
320  * double* y_coords; // initial y coordinates
321  * focus_t* fs;
322  * int ne;
323  * v_data* graph = makeGraph (topview*, &ne);
324  * hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
325  * freeGraph (graph);
326  * fs = initFocus (topview->Nodecount); // create focus set
327  */
prepare_topological_fisheye(Agraph_t * g,topview * t)328 void prepare_topological_fisheye(Agraph_t* g,topview * t)
329 {
330     double *x_coords = N_NEW(t->Nodecount, double);	// initial x coordinates
331     double *y_coords = N_NEW(t->Nodecount, double);	// initial y coordinates
332     focus_t *fs;
333     int ne;
334     int i;
335     int closest_fine_node;
336     int cur_level = 0;
337     Hierarchy *hp;
338     ex_vtx_data *gg;
339     gvcolor_t cl;
340     Agnode_t *np;
341 
342     v_data *graph = makeGraph(g, &ne);
343 
344 //      t->fisheyeParams.animate=1;   //turn the animation on
345     i=0;
346     for (np = agfstnode(g); np; np = agnxtnode(g, np))
347     {
348 	x_coords[i]=ND_A(np).x;
349 	y_coords[i]=ND_A(np).y;
350 	i++;
351     }
352     hp = t->fisheyeParams.h =
353 	makeHier(agnnodes(g), ne, graph, x_coords, y_coords,
354 		 &(t->fisheyeParams.hier));
355     freeGraph(graph);
356     free(x_coords);
357     free(y_coords);
358 
359     fs = t->fisheyeParams.fs = initFocus(agnnodes(g));	// create focus set
360     gg = hp->geom_graphs[0];
361 
362     closest_fine_node = 0;	/* first node */
363     fs->num_foci = 1;
364     fs->foci_nodes[0] = closest_fine_node;
365     fs->x_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].x_coord;
366     fs->y_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].y_coord;
367 
368     view->Topview->fisheyeParams.repos.width =
369 	(int) (view->bdxRight - view->bdxLeft);
370     view->Topview->fisheyeParams.repos.height =
371 	(int) (view->bdyTop - view->bdyBottom);
372     view->Topview->fisheyeParams.repos.rescale = Polar;
373 
374     //topological fisheye
375 
376     colorxlate(get_attribute_value
377 	       ("topologicalfisheyefinestcolor", view,
378 		view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
379     view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
380     view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
381     view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
382     colorxlate(get_attribute_value
383 	       ("topologicalfisheyecoarsestcolor", view,
384 		view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
385     view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
386     view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
387     view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
388 
389 
390     sscanf(agget
391 	   (view->g[view->activeGraph],
392 	    "topologicalfisheyedistortionfactor"), "%lf",
393 	   &view->Topview->fisheyeParams.repos.distortion);
394     sscanf(agget
395 	   (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
396 	   "%d", &view->Topview->fisheyeParams.level.num_fine_nodes);
397     sscanf(agget
398 	   (view->g[view->activeGraph],
399 	    "topologicalfisheyecoarseningfactor"), "%lf",
400 	   &view->Topview->fisheyeParams.level.coarsening_rate);
401     sscanf(agget
402 	   (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
403 	   "%d", &view->Topview->fisheyeParams.hier.dist2_limit);
404     sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
405 	   "%d", &view->Topview->fisheyeParams.animate);
406 
407     set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->fisheyeParams.level));
408     positionAllItems(hp, fs, &(t->fisheyeParams.repos));
409     refresh_old_values(t);
410 
411 /* fprintf (stderr, "No. of active nodes = %d\n", count_active_nodes(hp)); */
412 
413 }
414 
415 #if 0
416 /*
417 	draws all level 0 nodes and edges, during animation
418 */
419 void printalllevels(topview * t)
420 {
421     int level, v;
422     Hierarchy *hp = t->fisheyeParams.h;
423     glPointSize(5);
424     glBegin(GL_POINTS);
425     for (level = 0; level < hp->nlevels; level++) {
426 	for (v = 0; v < hp->nvtxs[level]; v++) {
427 	    ex_vtx_data *gg = hp->geom_graphs[level];
428 	    if (gg[v].active_level == level) {
429 		double x0, y0;
430 		get_temp_coords(t, level, v, &x0, &y0);
431 		glColor3f((GLfloat) (hp->nlevels - level) /
432 			  (GLfloat) hp->nlevels,
433 			  (GLfloat) level / (GLfloat) hp->nlevels, 0);
434 		glVertex3f((GLfloat) x0, (GLfloat) y0, (GLfloat) 0);
435 	    }
436 	}
437     }
438     glEnd();
439 }
440 #endif
441 
drawtopfishnodes(topview * t)442 static void drawtopfishnodes(topview * t)
443 {
444     glCompColor srcColor;
445     glCompColor tarColor;
446     glCompColor color;
447     int level, v;
448     Hierarchy *hp = t->fisheyeParams.h;
449     static int max_visible_level = 0;
450     srcColor.R = view->Topview->fisheyeParams.srcColor.R;
451     srcColor.G = view->Topview->fisheyeParams.srcColor.G;
452     srcColor.B = view->Topview->fisheyeParams.srcColor.B;
453     tarColor.R = view->Topview->fisheyeParams.tarColor.R;
454     tarColor.G = view->Topview->fisheyeParams.tarColor.G;
455     tarColor.B = view->Topview->fisheyeParams.tarColor.B;
456 
457 
458     //draw focused node little bigger than others
459 /*		ex_vtx_data *gg = hp->geom_graphs[0];
460 		if ((gg[v].active_level == 0) &&(v==t->fisheyeParams.fs->foci_nodes[0]))*/
461 
462 
463     //drawing nodes
464     glPointSize(7);
465     level = 0;
466     glBegin(GL_POINTS);
467     for (level = 0; level < hp->nlevels; level++) {
468 	for (v = 0; v < hp->nvtxs[level]; v++) {
469 	    double x0, y0;
470 	    if (get_temp_coords(t, level, v, &x0, &y0)) {
471 
472 		if (!(((-x0 / view->zoom > view->clipX1)
473 		       && (-x0 / view->zoom < view->clipX2)
474 		       && (-y0 / view->zoom > view->clipY1)
475 		       && (-y0 / view->zoom < view->clipY2))))
476 		    continue;
477 
478 //                              if (level !=0)
479 //                                      glColor4f((GLfloat) (hp->nlevels - level)*(GLfloat)0.5 /  (GLfloat) hp->nlevels,
480 //                                (GLfloat) level / (GLfloat) hp->nlevels, (GLfloat)0,(GLfloat)view->defaultnodealpha);
481 		//                      else
482 //                              glColor4f((GLfloat) 1,
483 //                                (GLfloat) level / (GLfloat) hp->nlevels*2, 0,view->defaultnodealpha);
484 
485 		if (max_visible_level < level)
486 		    max_visible_level = level;
487 		color_interpolation(srcColor, tarColor, &color,
488 				    max_visible_level, level);
489 		glColor4f(color.R, color.G, color.B,
490 			  (GLfloat) view->defaultnodealpha);
491 
492 /*								glColor3f((GLfloat) (hp->nlevels - level)*0.5 /  (GLfloat) hp->nlevels,
493 				  (GLfloat) level / (GLfloat) hp->nlevels, 0);*/
494 
495 		glVertex3f((GLfloat) x0, (GLfloat) y0, (GLfloat) 0);
496 	    }
497 	}
498     }
499     glEnd();
500 
501 }
502 
503 #if 0
504 static void drawtopfishnodelabels(topview * t)
505 {
506     int v, finenodes, focusnodes;
507     char buf[512];
508     char *str;
509     Hierarchy *hp = t->fisheyeParams.h;
510     finenodes = focusnodes = 0;
511     str =
512 	agget(view->g[view->activeGraph],
513 	      "topologicalfisheyelabelfinenodes");
514     if (strcmp(str, "1") == 0) {
515 	finenodes = 1;
516     }
517     str =
518 	agget(view->g[view->activeGraph], "topologicalfisheyelabelfocus");
519     if (strcmp(str, "1") == 0) {
520 	focusnodes = 1;
521     }
522     if ((finenodes) || (focusnodes)) {
523 	for (v = 0; v < hp->nvtxs[0]; v++) {
524 	    ex_vtx_data *gg = hp->geom_graphs[0];
525 	    if (gg[v].active_level == 0) {
526 		if (view->Topview->Nodes[v].Label)
527 		    strcpy(buf, view->Topview->Nodes[v].Label);
528 		else
529 		    sprintf(buf, "%d", v);
530 
531 		if ((v == t->fisheyeParams.fs->foci_nodes[0]) && (focusnodes)) {
532 		    glColor4f((float) 0, (float) 0, (float) 1, (float) 1);
533 		    glprintfglut(GLUT_BITMAP_HELVETICA_18,
534 				 gg[v].physical_x_coord,
535 				 gg[v].physical_y_coord, 0, buf);
536 		} else if (finenodes) {
537 		    glColor4f(0, 0, 0, 1);
538 		    glprintfglut(GLUT_BITMAP_HELVETICA_10,
539 				 gg[v].physical_x_coord,
540 				 gg[v].physical_y_coord, 0, buf);
541 		}
542 	    }
543 
544 	}
545     }
546 
547 }
548 #endif
drawtopfishedges(topview * t)549 static void drawtopfishedges(topview * t)
550 {
551     glCompColor srcColor;
552     glCompColor tarColor;
553     glCompColor color;
554 
555     int level, v, i, n;
556     Hierarchy *hp = t->fisheyeParams.h;
557     static int max_visible_level = 0;
558     srcColor.R = view->Topview->fisheyeParams.srcColor.R;
559     srcColor.G = view->Topview->fisheyeParams.srcColor.G;
560     srcColor.B = view->Topview->fisheyeParams.srcColor.B;
561     tarColor.R = view->Topview->fisheyeParams.tarColor.R;
562     tarColor.G = view->Topview->fisheyeParams.tarColor.G;
563     tarColor.B = view->Topview->fisheyeParams.tarColor.B;
564 
565     //and edges
566     glBegin(GL_LINES);
567     for (level = 0; level < hp->nlevels; level++) {
568 	for (v = 0; v < hp->nvtxs[level]; v++) {
569 	    v_data *g = hp->graphs[level];
570 	    double x0, y0;
571 	    if (get_temp_coords(t, level, v, &x0, &y0)) {
572 		for (i = 1; i < g[v].nedges; i++) {
573 		    double x, y;
574 		    n = g[v].edges[i];
575 
576 
577 		    if (max_visible_level < level)
578 			max_visible_level = level;
579 		    color_interpolation(srcColor, tarColor, &color,
580 					max_visible_level, level);
581 		    glColor4f(color.R, color.G, color.B,
582 			      (GLfloat) view->defaultnodealpha);
583 
584 
585 		    if (get_temp_coords(t, level, n, &x, &y)) {
586 			glVertex3f((GLfloat) x0, (GLfloat) y0,
587 				   (GLfloat) 0);
588 			glVertex3f((GLfloat) x, (GLfloat) y, (GLfloat) 0);
589 		    } else	// if (gg[n].active_level > level)
590 		    {
591 			int levell, nodee;
592 			find_active_ancestor_info(hp, level, n, &levell,
593 						  &nodee);
594 //                                              find_physical_coords(hp, level, n, &x, &y);
595 			if (get_temp_coords(t, levell, nodee, &x, &y)) {
596 
597 			    if ((!(((-x0 / view->zoom > view->clipX1)
598 				    && (-x0 / view->zoom < view->clipX2)
599 				    && (-y0 / view->zoom > view->clipY1)
600 				    && (-y0 / view->zoom < view->clipY2))))
601 				&& (!(((-x / view->zoom > view->clipX1)
602 				       && (-x / view->zoom < view->clipX2)
603 				       && (-y / view->zoom > view->clipY1)
604 				       && (-y / view->zoom <
605 					   view->clipY2)))))
606 
607 				continue;
608 
609 
610 			    glVertex3f((GLfloat) x0, (GLfloat) y0,
611 				       (GLfloat) 0);
612 			    glVertex3f((GLfloat) x, (GLfloat) y,
613 				       (GLfloat) 0);
614 			}
615 		    }
616 		}
617 	    }
618 	}
619     }
620     glEnd();
621 
622 }
623 
get_active_frame(topview * t)624 static int get_active_frame(topview * t)
625 {
626     gulong microseconds;
627     gdouble seconds;
628     int fr;
629     seconds = g_timer_elapsed(view->timer, &microseconds);
630     fr = (int) (seconds / ((double) view->frame_length / (double) 1000));
631     if (fr < view->total_frames) {
632 
633 	if (fr == view->active_frame)
634 	    return 0;
635 	else {
636 	    view->active_frame = fr;
637 	    return 1;
638 	}
639     } else {
640 	g_timer_stop(view->timer);
641 	view->Topview->fisheyeParams.animate = 0;
642 	return 0;
643     }
644 
645 }
646 
drawtopologicalfisheye(topview * t)647 void drawtopologicalfisheye(topview * t)
648 {
649     get_active_frame(t);
650     drawtopfishnodes(t);
651     drawtopfishedges(t);
652 /*    if (!t->fisheyeParams.animate)
653 	drawtopfishnodelabels(t);*/
654 
655 }
656 
get_interpolated_coords(double x0,double y0,double x1,double y1,int fr,int total_fr,double * x,double * y)657 static void get_interpolated_coords(double x0, double y0, double x1, double y1,
658 			     int fr, int total_fr, double *x, double *y)
659 {
660     *x = x0 + (x1 - x0) / (double) total_fr *(double) (fr + 1);
661     *y = y0 + (y1 - y0) / (double) total_fr *(double) (fr + 1);
662 }
663 
get_temp_coords(topview * t,int level,int v,double * coord_x,double * coord_y)664 int get_temp_coords(topview * t, int level, int v, double *coord_x,
665 		    double *coord_y)
666 {
667     Hierarchy *hp = t->fisheyeParams.h;
668     ex_vtx_data *gg = hp->geom_graphs[level];
669     /* v_data *g = hp->graphs[level]; */
670 
671     if (!t->fisheyeParams.animate) {
672 	if (gg[v].active_level != level)
673 	    return 0;
674 
675 	*coord_x = (double) gg[v].physical_x_coord;
676 	*coord_y = (double) gg[v].physical_y_coord;
677     } else {
678 
679 
680 	double x0, y0, x1, y1;
681 	int OAL, AL;
682 
683 	x0 = 0;
684 	y0 = 0;
685 	x1 = 0;
686 	y1 = 0;
687 	AL = gg[v].active_level;
688 	OAL = gg[v].old_active_level;
689 
690 	if ((OAL < level) || (AL < level))	//no draw
691 	    return 0;
692 	if ((OAL >= level) || (AL >= level))	//draw the node
693 	{
694 	    if ((OAL == level) && (AL == level))	//draw as is from old coords to new)
695 	    {
696 		x0 = (double) gg[v].old_physical_x_coord;
697 		y0 = (double) gg[v].old_physical_y_coord;
698 		x1 = (double) gg[v].physical_x_coord;
699 		y1 = (double) gg[v].physical_y_coord;
700 	    }
701 	    if ((OAL > level) && (AL == level))	//draw as  from ancs  to new)
702 	    {
703 		find_old_physical_coords(t->fisheyeParams.h, level, v, &x0, &y0);
704 		x1 = (double) gg[v].physical_x_coord;
705 		y1 = (double) gg[v].physical_y_coord;
706 	    }
707 	    if ((OAL == level) && (AL > level))	//draw as  from ancs  to new)
708 	    {
709 		find_physical_coords(t->fisheyeParams.h, level, v, &x1, &y1);
710 		x0 = (double) gg[v].old_physical_x_coord;
711 		y0 = (double) gg[v].old_physical_y_coord;
712 	    }
713 	    get_interpolated_coords(x0, y0, x1, y1, view->active_frame,
714 				    view->total_frames, coord_x, coord_y);
715 	    if ((x0 == 0) || (x1 == 0))
716 		return 0;
717 
718 	}
719     }
720     return 1;
721 }
722 
723 
724 
725 /*  In loop,
726  *  update fs.
727  *    For example, if user clicks mouse at (p.x,p.y) to pick a single new focus,
728  *      int closest_fine_node;
729  *      find_closest_active_node(hierarchy, p.x, p.y, &closest_fine_node);
730  *      fs->num_foci = 1;
731  *      fs->foci_nodes[0] = closest_fine_node;
732  *      fs->x_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].x_coord;
733  *      fs->y_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].y_coord;
734  *  set_active_levels(hierarchy, fs->foci_nodes, fs->num_foci);
735  *  positionAllItems(hierarchy, fs, parms)
736  */
737 
738 #if 0
739 void infotopfisheye(topview * t, float *x, float *y, float *z)
740 {
741 
742     Hierarchy *hp = t->fisheyeParams.h;
743     int closest_fine_node;
744     find_closest_active_node(hp, *x, *y, &closest_fine_node);
745 
746 
747 
748 
749 /*		hp->geom_graphs[0][closest_fine_node].x_coord;
750 	    hp->geom_graphs[0][closest_fine_node].y_coord;*/
751 }
752 #endif
753 
754 
755 
changetopfishfocus(topview * t,float * x,float * y,float * z,int num_foci)756 void changetopfishfocus(topview * t, float *x, float *y,
757 			float *z, int num_foci)
758 {
759 
760     gvcolor_t cl;
761     focus_t *fs = t->fisheyeParams.fs;
762     int i;
763     int closest_fine_node;
764     int cur_level = 0;
765 
766     Hierarchy *hp = t->fisheyeParams.h;
767     refresh_old_values(t);
768     fs->num_foci = num_foci;
769     for (i = 0; i < num_foci; i++) {
770 	find_closest_active_node(hp, x[i], y[i], &closest_fine_node);
771 	fs->foci_nodes[i] = closest_fine_node;
772 	fs->x_foci[i] =
773 	    hp->geom_graphs[cur_level][closest_fine_node].x_coord;
774 	fs->y_foci[i] =
775 	    hp->geom_graphs[cur_level][closest_fine_node].y_coord;
776     }
777 
778 
779     view->Topview->fisheyeParams.repos.width =
780 	(int) (view->bdxRight - view->bdxLeft);
781     view->Topview->fisheyeParams.repos.height =
782 	(int) (view->bdyTop - view->bdyBottom);
783 
784     colorxlate(get_attribute_value
785 	       ("topologicalfisheyefinestcolor", view,
786 		view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
787     view->Topview->fisheyeParams.srcColor.R = (float) cl.u.RGBA[0];
788     view->Topview->fisheyeParams.srcColor.G = (float) cl.u.RGBA[1];
789     view->Topview->fisheyeParams.srcColor.B = (float) cl.u.RGBA[2];
790     colorxlate(get_attribute_value
791 	       ("topologicalfisheyecoarsestcolor", view,
792 		view->g[view->activeGraph]), &cl, RGBA_DOUBLE);
793     view->Topview->fisheyeParams.tarColor.R = (float) cl.u.RGBA[0];
794     view->Topview->fisheyeParams.tarColor.G = (float) cl.u.RGBA[1];
795     view->Topview->fisheyeParams.tarColor.B = (float) cl.u.RGBA[2];
796 
797 
798 
799     sscanf(agget
800 	   (view->g[view->activeGraph],
801 	    "topologicalfisheyedistortionfactor"), "%lf",
802 	   &view->Topview->fisheyeParams.repos.distortion);
803     sscanf(agget
804 	   (view->g[view->activeGraph], "topologicalfisheyefinenodes"),
805 	   "%d", &view->Topview->fisheyeParams.level.num_fine_nodes);
806     sscanf(agget
807 	   (view->g[view->activeGraph],
808 	    "topologicalfisheyecoarseningfactor"), "%lf",
809 	   &view->Topview->fisheyeParams.level.coarsening_rate);
810     sscanf(agget
811 	   (view->g[view->activeGraph], "topologicalfisheyedist2limit"),
812 	   "%d", &view->Topview->fisheyeParams.hier.dist2_limit);
813     sscanf(agget(view->g[view->activeGraph], "topologicalfisheyeanimate"),
814 	   "%d", &view->Topview->fisheyeParams.animate);
815 
816 
817 
818 
819     set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->fisheyeParams.level));
820 
821 
822     positionAllItems(hp, fs, &(t->fisheyeParams.repos));
823 
824     view->Topview->fisheyeParams.animate = 1;
825 
826     if (t->fisheyeParams.animate) {
827 	view->active_frame = 0;
828 	g_timer_start(view->timer);
829     }
830 
831 }
832 
833 
834 
835 #ifdef UNUSED
drawtopologicalfisheyestatic(topview * t)836 void drawtopologicalfisheyestatic(topview * t)
837 {
838     int level, v;
839     Hierarchy *hp = t->fisheyeParams.h;
840 
841     glPointSize(15);
842     glBegin(GL_POINTS);
843     for (level = 0; level < hp->nlevels; level++) {
844 	for (v = 0; v < hp->nvtxs[level]; v++) {
845 	    ex_vtx_data *gg = hp->geom_graphs[level];
846 	    if (gg[v].active_level == level) {
847 		double x0 = gg[v].physical_x_coord;
848 		double y0 = gg[v].physical_y_coord;
849 //              glColor3f((GLfloat)(hp->nlevels-level)/(GLfloat)hp->nlevels,(GLfloat)level/(GLfloat)hp->nlevels,0);
850 		glColor4f((GLfloat) 0, (GLfloat) 1, (GLfloat) 0,
851 			  (GLfloat) 0.2);
852 		glVertex3f((GLfloat) x0, (GLfloat) y0, (GLfloat) 0);
853 	    }
854 	}
855     }
856     glEnd();
857 
858 
859 
860 
861 /*	glBegin(GL_LINES);
862     for (level=0;level < hp->nlevels;level++) {
863 	for (v=0;v < hp->nvtxs[level]; v++) {
864 	    ex_vtx_data* gg = hp->geom_graphs[level];
865 	    vtx_data* g = hp->graphs[level];
866 	    if(gg[v].active_level==level) {
867 		double x0 = gg[v].physical_x_coord;
868 		double y0 = gg[v].physical_y_coord;
869 
870 		for (i=1;i < g[v].nedges;i++) {
871 		    double x,y;
872 			n = g[v].edges[i];
873 			glColor3f((GLfloat)(hp->nlevels-level)/(GLfloat)hp->nlevels,(GLfloat)level/(GLfloat)hp->nlevels,0);
874 			if (gg[n].active_level == level) {
875 			if (v < n) {
876 			    x = gg[n].physical_x_coord;
877 			    y = gg[n].physical_y_coord;
878 			    glVertex3f((GLfloat)x0,(GLfloat)y0,(GLfloat)0);
879 			    glVertex3f((GLfloat)x,(GLfloat)y,(GLfloat)0);
880 			}
881 			}
882 		    else if (gg[n].active_level > level) {
883 			find_physical_coords(hp, level, n, &x, &y);
884 			glVertex3f((GLfloat)x0,(GLfloat)y0,(GLfloat)0);
885 			glVertex3f((GLfloat)x,(GLfloat)y,(GLfloat)0);
886 		    }
887 		}
888 	    }
889 	}
890     }
891     glEnd();*/
892 }
893 #endif
894