#include "gui.h"
#include "viewport.h"
#include "topview.h"
+#include "topfisheyeview.h"
#include "gltemplate.h"
#include "glutils.h"
#include "glexpose.h"
GLfloat lmodel_ambient[] = { 0.2f, 0.2f, 0.2f, 1.0f };
GLfloat local_view[] = { 0.0 };
- char* smyrna_font;
+ char *smyrna_font;
#ifdef WIN32
#define SMYRNA_FONT "c:/arial.tga"
// using -DSMYRNA_FONT from Makefile.am and configure.ac
#endif
- if ((smyrna_font = smyrnaPath ("gui/arial.tga"))) {
+ if ((smyrna_font = smyrnaPath("gui/arial.tga"))) {
g_print("loading font....%i\n", fontLoad(smyrna_font));
- free (smyrna_font);
- }
- else g_print("loading font....%i\n", fontLoad(SMYRNA_FONT));
+ free(smyrna_font);
+ } else
+ g_print("loading font....%i\n", fontLoad(SMYRNA_FONT));
/*** OpenGL BEGIN ***/
if (!gdk_gl_drawable_gl_begin(gldrawable, glcontext))
glLoadIdentity();
if (view->w > view->h) {
aspect = (float) view->w / (float) view->h;
- glOrtho(-aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR, GL_VIEWPORT_FACTOR*-1, GL_VIEWPORT_FACTOR, -1500, 1500);
+ glOrtho(-aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR,
+ GL_VIEWPORT_FACTOR * -1, GL_VIEWPORT_FACTOR, -1500, 1500);
} else {
aspect = (float) view->h / (float) view->w;
- glOrtho(GL_VIEWPORT_FACTOR*-1, GL_VIEWPORT_FACTOR, -aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR, -1500, 1500);
+ glOrtho(GL_VIEWPORT_FACTOR * -1, GL_VIEWPORT_FACTOR,
+ -aspect * GL_VIEWPORT_FACTOR, aspect * GL_VIEWPORT_FACTOR,
+ -1500, 1500);
}
glMatrixMode(GL_MODELVIEW);
begin_y = (float) event->y;
if (event->button == 3) //right click
- view->mouse.button = rightmousebutton;
+ view->mouse.button = rightmousebutton;
if (event->button == 1) //left click
{
- view->prevpanx = view->panx;
- view->prevpany = view->pany;
- view->mouse.mouse_down = 1;
- view->mouse.button = leftmousebutton;
+ view->prevpanx = view->panx;
+ view->prevpany = view->pany;
+ view->mouse.mouse_down = 1;
+ view->mouse.button = leftmousebutton;
if (GetOGLPosRef
((int) begin_x, (int) begin_y, &(view->GLx), &(view->GLy),
&(view->GLz))) {
GdkEventButton * event, gpointer data)
{
if (event->button == 1) //left click release
+ {
+ if (glCompSetRelease
+ (view->Topview->topviewmenu, (int) event->x_root,
+ (int) event->y_root)) {
+ expose_event(view->drawing_area, NULL, NULL);
+ }
+ view->mouse.mouse_down = 0;
+ if ((view->mouse.mouse_mode == MM_RECTANGULAR_SELECT)
+ || (view->mouse.mouse_mode == MM_RECTANGULAR_X_SELECT)) {
+ if (view->GLx <= view->GLx2)
+ view->Selection.X = view->GLx;
+ else
+ view->Selection.X = view->GLx2;
+ if (view->GLy <= view->GLy2)
+ view->Selection.Y = view->GLy;
+ else
+ view->Selection.Y = view->GLy2;
+ view->Selection.W = view->GLx2 - view->GLx;
+ if (view->Selection.W < 0)
+ view->Selection.W = view->Selection.W * -1;
+ view->Selection.H = view->GLy2 - view->GLy;
+ if (view->Selection.H < 0)
+ view->Selection.H = view->Selection.H * -1;
+ if (view->mouse.mouse_mode == 4)
+ view->Selection.Type = 1;
+ else
+ view->Selection.Type = 2;
+ view->Selection.Active = 1;
+ expose_event(view->drawing_area, NULL, NULL);
+ }
+ if (view->mouse.mouse_mode == MM_MOVE) {
+ if (GD_TopView(view->g[view->activeGraph]) == 0)
+ move_nodes(view->g[view->activeGraph]);
+ else
+ move_TVnodes();
+ }
+
+ if ((view->mouse.mouse_mode == MM_FISHEYE_MAGNIFIER) || (view->mouse.mouse_mode == MM_MAGNIFIER)) //fisheye mag mouse release, stop distortion
{
- if (glCompSetRelease
- (view->Topview->topviewmenu, (int) event->x_root,
- (int) event->y_root))
- {
- expose_event(view->drawing_area, NULL, NULL);
- }
- view->mouse.mouse_down = 0;
- if ((view->mouse.mouse_mode == MM_RECTANGULAR_SELECT)
- || (view->mouse.mouse_mode == MM_RECTANGULAR_X_SELECT))
- {
- if (view->GLx <= view->GLx2)
- view->Selection.X = view->GLx;
- else
- view->Selection.X = view->GLx2;
- if (view->GLy <= view->GLy2)
- view->Selection.Y = view->GLy;
- else
- view->Selection.Y = view->GLy2;
- view->Selection.W = view->GLx2 - view->GLx;
- if (view->Selection.W < 0)
- view->Selection.W = view->Selection.W * -1;
- view->Selection.H = view->GLy2 - view->GLy;
- if (view->Selection.H < 0)
- view->Selection.H = view->Selection.H * -1;
- if (view->mouse.mouse_mode == 4)
- view->Selection.Type = 1;
- else
- view->Selection.Type = 2;
- view->Selection.Active = 1;
- expose_event(view->drawing_area, NULL, NULL);
- }
- if (view->mouse.mouse_mode == MM_MOVE)
- {
- if (GD_TopView(view->g[view->activeGraph]) == 0)
- move_nodes(view->g[view->activeGraph]);
- else
- move_TVnodes();
- }
-
- if ((view->mouse.mouse_mode == MM_FISHEYE_MAGNIFIER) || (view->mouse.mouse_mode == MM_MAGNIFIER)) //fisheye mag mouse release, stop distortion
- {
- originate_distorded_coordinates(view->Topview);
- expose_event(view->drawing_area, NULL, NULL);
- }
+ originate_distorded_coordinates(view->Topview);
+ expose_event(view->drawing_area, NULL, NULL);
}
+ }
if (event->button == 3) //right click
- {
- if (view->Topview->is_top_fisheye)
- {
- GetFixedOGLPoslocal((int) event->x, (int) event->y, view->GLDepth, &(view->GLx2),
- &(view->GLy2), &(view->GLz2));
- changetopologicalfisheyefocus(view->Topview,&view->GLx2,&view->GLy2,0,1);
- expose_event(view->drawing_area, NULL, NULL);
- }
+ {
+ if (view->Topview->is_top_fisheye) {
+ GetFixedOGLPoslocal((int) event->x, (int) event->y,
+ view->GLDepth, &(view->GLx2),
+ &(view->GLy2), &(view->GLz2));
+ changetopfishfocus(view->Topview, &view->GLx2, &view->GLy2, 0,
+ 1);
+ expose_event(view->drawing_area, NULL, NULL);
}
+ }
dx = 0.0;
dy = 0.0;
char buf[50];
- float gldx,gldy;
- gboolean redraw = FALSE;
+ float gldx, gldy;
+ gboolean redraw = FALSE;
dx = x - begin_x;
dy = y - begin_y;
- view->mouse.dx=dx;
- view->mouse.dy=dy;
+ view->mouse.dx = dx;
+ view->mouse.dy = dy;
- /*panning */
+ /*panning */
if ((event->state & GDK_BUTTON1_MASK)
- && (view->mouse.mouse_mode == MM_PAN))
- {
- if(glmotion_main(view,event,widget))
- redraw = TRUE;
- }
- /*rotating, only in 3d view */
- if ((view->active_camera >=0)&&(view->mouse.mouse_mode==MM_ROTATE)&& (event->state & GDK_BUTTON1_MASK) )
- {
- if(glmotion_main(view,event,widget))
- redraw = TRUE;
- }
+ && (view->mouse.mouse_mode == MM_PAN)) {
+ if (glmotion_main(view, event, widget))
+ redraw = TRUE;
+ }
+ /*rotating, only in 3d view */
+ if ((view->active_camera >= 0) && (view->mouse.mouse_mode == MM_ROTATE)
+ && (event->state & GDK_BUTTON1_MASK)) {
+ if (glmotion_main(view, event, widget))
+ redraw = TRUE;
+ }
/*zooming */
if ((event->state & GDK_BUTTON1_MASK)
&& (view->mouse.mouse_mode == MM_ZOOM)) {
float x;
- float real_zoom,old_zoom;
- if(view->active_camera==-1)
- {
- old_zoom=view->zoom;
- real_zoom=view->zoom + dx / 10 * (view->zoom * -1 / 20);
- }
- else
- {
- old_zoom=view->cameras[view->active_camera]->r;
- real_zoom=(view->cameras[view->active_camera]->r + dx / 10 * (view->cameras[view->active_camera]->r / 20))*-1;
+ float real_zoom, old_zoom;
+ if (view->active_camera == -1) {
+ old_zoom = view->zoom;
+ real_zoom = view->zoom + dx / 10 * (view->zoom * -1 / 20);
+ } else {
+ old_zoom = view->cameras[view->active_camera]->r;
+ real_zoom =
+ (view->cameras[view->active_camera]->r +
+ dx / 10 * (view->cameras[view->active_camera]->r / 20)) *
+ -1;
}
if (real_zoom > MAX_ZOOM)
- real_zoom = (float) MAX_ZOOM;
+ real_zoom = (float) MAX_ZOOM;
if (real_zoom < MIN_ZOOM)
real_zoom = (float) MIN_ZOOM;
- if(view->active_camera==-1)
- view->zoom = real_zoom;
- else{
- view->cameras[view->active_camera]->r=real_zoom*-1;
+ if (view->active_camera == -1)
+ view->zoom = real_zoom;
+ else {
+ view->cameras[view->active_camera]->r = real_zoom * -1;
- //pan adjsutment
+ //pan adjsutment
}
- view->panx=old_zoom*view->panx/real_zoom;
- view->pany=old_zoom*view->pany/real_zoom;
+ view->panx = old_zoom * view->panx / real_zoom;
+ view->pany = old_zoom * view->pany / real_zoom;
/*set label to new zoom value */
x = ((float) 100.0 - (float) 1.0) * (view->zoom -
glconfig, NULL, TRUE, GDK_GL_RGBA_TYPE);
gtk_widget_add_events(view->drawing_area,
-// GDK_BUTTON_MOTION_MASK = 1 << 4,
- GDK_BUTTON_MOTION_MASK |
- GDK_BUTTON1_MOTION_MASK |
+// GDK_BUTTON_MOTION_MASK = 1 << 4,
+ GDK_BUTTON_MOTION_MASK |
+ GDK_BUTTON1_MOTION_MASK |
GDK_BUTTON2_MOTION_MASK |
- GDK_BUTTON3_MOTION_MASK |
+ GDK_BUTTON3_MOTION_MASK |
GDK_BUTTON_PRESS_MASK |
GDK_BUTTON_RELEASE_MASK |
GDK_VISIBILITY_NOTIFY_MASK);
/* Popup menu. */
- /* menu = create_popup_menu(view->drawing_area);
+#if 0
+ menu = create_popup_menu(view->drawing_area);
/* Signal handler */
- /* g_signal_connect_swapped(G_OBJECT(view->drawing_area),
+ g_signal_connect_swapped(G_OBJECT(view->drawing_area),
"button_press_event",
G_CALLBACK(button_press_event_popup_menu),
- menu);*/
+ menu);
+#endif
}
* AT&T Research, Florham Park NJ *
**********************************************************/
-
-#include <assert.h>
+#include "smyrnadefs.h"
#include "hier.h"
#include "memory.h"
-/* To use:
- double* x_coords; // initial x coordinates
- double* y_coords; // initial y coordinates
- focus_t* fs;
- int ne;
- vtx_data* graph = makeGraph (topview*, &ne);
- hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
- freeGraph (graph);
- fs = initFocus (topview->Nodecount); // create focus set
-
- In loop,
- update fs.
- For example, if user clicks mouse at (p.x,p.y) to pick a single new focus,
- int closest_fine_node;
- find_closest_active_node(hierarchy, p.x, p.y, &closest_fine_node);
- fs->num_foci = 1;
- fs->foci_nodes[0] = closest_fine_node;
- fs->x_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].x_coord;
- fs->y_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].y_coord;
-
- set_active_levels(hierarchy, fs->foci_nodes, fs->num_foci);
- positionAllItems(hierarchy, fs, parms)
-
- When done:
- release (hierarchy);
-*/
-
/* scale_coords:
*/
static void
}
}
-void positionAllItems(Hierarchy * hp, focus_t * fs, hierparms_t * parms)
+void positionAllItems(Hierarchy * hp, focus_t * fs, reposition_t* parms)
{
int i;
int interval = 20;
double width = parms->width;
double height = parms->height;
double margin = parms->margin;
+ double distortion = parms->distortion;
/* get all logical coordinates of active nodes */
for (i = 0; i < hp->nvtxs[max_level]; i++) {
case Polar:
rescale_layout_polar(x_coords, y_coords, fs->x_foci,
fs->y_foci, fs->num_foci, counter,
- interval, width, height, margin);
+ interval, width, height, margin, distortion);
break;
case Rectilinear:
rescale_layout(x_coords, y_coords, counter, interval,
- width, height, margin);
+ width, height, margin, distortion);
break;
case Scale:
scale_coords(x_coords, y_coords, counter, width, height, margin);
free(y_coords);
}
-vtx_data *makeGraph(topview * tv, int *nedges)
-{
- int i;
- int ne = tv->Edgecount; /* upper bound */
- int nv = tv->Nodecount;
- vtx_data *graph = N_NEW(nv, vtx_data);
- int *edges = N_NEW(2 * ne + nv, int); /* reserve space for self loops */
- float *ewgts = N_NEW(2 * ne + nv, float);
- Agnode_t *np;
- Agedge_t *ep;
- Agraph_t *g = NULL;
- int i_nedges;
-
- ne = 0;
- for (i = 0; i < nv; i++) {
- graph[i].edges = edges++; /* reserve space for the self loop */
- graph[i].ewgts = ewgts++;
-#ifdef STYLES
- graph[i].styles = NULL;
-#endif
- i_nedges = 1; /* one for the self */
-
- np = tv->Nodes[i].Node;
- if (!g)
- g = agraphof(np);
- for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) {
- Agnode_t *vp;
- Agnode_t *tp = agtail(ep);
- Agnode_t *hp = aghead(ep);
- assert(hp != tp);
- /* FIX: handle multiedges */
- vp = (tp == np ? hp : tp);
- ne++;
- i_nedges++;
- *edges++ = OD_TVRef(vp);
- *ewgts++ = 1;
- }
-
- graph[i].nedges = i_nedges;
- graph[i].edges[0] = i;
- graph[i].ewgts[0] = 1 - i_nedges;
- }
- ne /= 2; /* each edge counted twice */
- *nedges = ne;
- return graph;
-}
-
#ifdef DEBUG
static void
dumpG (int nn, vtx_data * graph)
#endif
Hierarchy *makeHier(int nn, int ne, vtx_data * graph, double *x_coords,
- double *y_coords)
+ double *y_coords, hierparms_t* parms)
{
vtx_data *delaunay;
ex_vtx_data *geom_graph;
free(delaunay[0].edges);
free(delaunay);
- hp = create_hierarchy(graph, nn, ne, geom_graph, ngeom_edges, 20);
+ hp = create_hierarchy(graph, nn, ne, geom_graph, ngeom_edges, parms);
free(geom_graph[0].edges);
free(geom_graph);
fs->y_foci = N_NEW(ncnt, double);
return fs;
}
+
+void freeFocus(focus_t* fs)
+{
+ free (fs->foci_nodes);
+ free (fs->x_foci);
+ free (fs->y_foci);
+ free (fs);
+}
#define HIER_H
#include "hierarchy.h"
-#include "topview.h"
+
typedef struct {
int num_foci;
int *foci_nodes; /* Nodes in real graph */
typedef enum {NoRescale, Scale, Polar, Rectilinear} RescaleType;
typedef struct {
+/* First 5 must be set i rescale = Polar or Rectilinear */
int width; /* viewport width */
int height; /* viewport height */
int margin; /* viewport margin */
- int graphSize; /* viewport scale : 0 -- 100 */
+ int graphSize; /* 0 -- 100: percent to shrink w x h */
+ double distortion; /* default of 1.0 */
RescaleType rescale;
-} hierparms_t;
+} reposition_t;
-void positionAllItems(Hierarchy * hp, focus_t * fs, hierparms_t * parms);
-vtx_data *makeGraph(topview * tv, int *nedges);
+void positionAllItems(Hierarchy * hp, focus_t * fs, reposition_t* parms);
Hierarchy *makeHier(int nnodes, int nedges, vtx_data *, double *,
- double *);
+ double*, hierparms_t *);
+
focus_t *initFocus(int ncnt);
+void freeFocus(focus_t* fs);
#endif
#include <GL/glu.h>
#include <gtk/gtkgl.h>
#include "glcompset.h"
-#include "hierarchy.h"
+#include "hier.h"
#define IS_TEST_MODE_ON 0
#define DEFAULT_MAGNIFIER_WIDTH 300
typedef enum { leftmousebutton,rightmousebutton,thirdmousebutton} clicked_mouse_button;
typedef enum { MOUSE_ROTATE_X,MOUSE_ROTATE_Y,MOUSE_ROTATE_XY,MOUSE_ROTATE_Z} mouse_rotate_axis;
-
typedef struct {
float R;
float G;
cam_t type; //
} viewport_camera;
-
-
typedef struct {
topview_node *Nodes;
topview_edge *Edges;
topviewdata *TopviewData;
void *customptr;
Hierarchy *h;
- int is_top_fisheye; //1 draw hierarchy 0 draw regular topview
+ int is_top_fisheye; //1 draw hierarchy 0 draw regular topview
+ focus_t* fs;
+ struct {
+ reposition_t repos;
+ levelparms_t level;
+ hierparms_t hier;
+ } parms;
} topview;
enum {
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2004 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
#include "topfisheyeview.h"
#include "glTexFont.h"
#include "viewportcamera.h"
#include "draw.h"
#include "selection.h"
+#include "assert.h"
#include "hier.h"
static double dist(double x1, double y1, double x2, double y2)
{
return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));
}
-static double dist3d(double x1, double y1,double z1, double x2, double y2,double z2)
+static double dist3d(double x1, double y1, double z1, double x2, double y2,
+ double z2)
{
- return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2)+(z1 - z2) * (z1 - z2));
+ return sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2) +
+ (z1 - z2) * (z1 - z2));
}
}
}
}
-void fisheye_spherical(double x_focus, double y_focus,double z_focus, topview * t)
+void fisheye_spherical(double x_focus, double y_focus, double z_focus,
+ topview * t)
{
int i;
double distance, distorted_distance, ratio, range;
range = 0;
for (i = 1; i < t->Nodecount; i++) {
- if ( point_within_sphere_with_coords((float) x_focus, (float) y_focus, (float)z_focus, (float) view->fmg.R
- ,t->Nodes[i].x, t->Nodes[i].y,t->Nodes[i].z))
- {
-
-
+ if (point_within_sphere_with_coords
+ ((float) x_focus, (float) y_focus, (float) z_focus,
+ (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y,
+ t->Nodes[i].z)) {
+
+
range =
MAX(range,
- dist3d(t->Nodes[i].x, t->Nodes[i].y,t->Nodes[i].z, x_focus, y_focus,z_focus));
+ dist3d(t->Nodes[i].x, t->Nodes[i].y, t->Nodes[i].z,
+ x_focus, y_focus, z_focus));
}
}
for (i = 1; i < t->Nodecount; i++) {
- if (
- point_within_sphere_with_coords((float) x_focus, (float) y_focus, (float)z_focus, (float) view->fmg.R
- ,t->Nodes[i].x, t->Nodes[i].y,t->Nodes[i].z))
- {
+ if (point_within_sphere_with_coords
+ ((float) x_focus, (float) y_focus, (float) z_focus,
+ (float) view->fmg.R, t->Nodes[i].x, t->Nodes[i].y,
+ t->Nodes[i].z)) {
distance =
- dist3d(t->Nodes[i].x, t->Nodes[i].y,t->Nodes[i].z, x_focus, y_focus,z_focus);
+ dist3d(t->Nodes[i].x, t->Nodes[i].y, t->Nodes[i].z,
+ x_focus, y_focus, z_focus);
distorted_distance = G(distance / range) * range;
if (distance != 0) {
ratio = distorted_distance / distance;
}
}
+static vtx_data *makeGraph(topview * tv, int *nedges)
+{
+ int i;
+ int ne = tv->Edgecount; /* upper bound */
+ int nv = tv->Nodecount;
+ vtx_data *graph = N_NEW(nv, vtx_data);
+ int *edges = N_NEW(2 * ne + nv, int); /* reserve space for self loops */
+ float *ewgts = N_NEW(2 * ne + nv, float);
+ Agnode_t *np;
+ Agedge_t *ep;
+ Agraph_t *g = NULL;
+ int i_nedges;
+
+ ne = 0;
+ for (i = 0; i < nv; i++) {
+ graph[i].edges = edges++; /* reserve space for the self loop */
+ graph[i].ewgts = ewgts++;
+#ifdef STYLES
+ graph[i].styles = NULL;
+#endif
+ i_nedges = 1; /* one for the self */
+
+ np = tv->Nodes[i].Node;
+ if (!g)
+ g = agraphof(np);
+ for (ep = agfstedge(g, np); ep; ep = agnxtedge(g, ep, np)) {
+ Agnode_t *vp;
+ Agnode_t *tp = agtail(ep);
+ Agnode_t *hp = aghead(ep);
+ assert(hp != tp);
+ /* FIX: handle multiedges */
+ vp = (tp == np ? hp : tp);
+ ne++;
+ i_nedges++;
+ *edges++ = OD_TVRef(vp);
+ *ewgts++ = 1;
+ }
+ graph[i].nedges = i_nedges;
+ graph[i].edges[0] = i;
+ graph[i].ewgts[0] = 1 - i_nedges;
+ }
+ ne /= 2; /* each edge counted twice */
+ *nedges = ne;
+ return graph;
+}
-void prepare_topological_fisheye(topview * t)
-{
/* To use:
- double* x_coords; // initial x coordinates
- double* y_coords; // initial y coordinates
- focus_t* fs;
- int ne;
- vtx_data* graph = makeGraph (topview*, &ne);
- hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
- freeGraph (graph);
- fs = initFocus (topview->Nodecount); // create focus set
-
- In loop,
- update fs.
- For example, if user clicks mouse at (p.x,p.y) to pick a single new focus,
- int closest_fine_node;
- find_closest_active_node(hierarchy, p.x, p.y, &closest_fine_node);
- fs->num_foci = 1;
- fs->foci_nodes[0] = closest_fine_node;
- fs->x_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].x_coord;
- fs->y_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].y_coord;
-
- set_active_levels(hierarchy, fs->foci_nodes, fs->num_foci);
- positionAllItems(hierarchy, fs, parms)
-
- When done:
- release (hierarchy);
-*/
- double *x_coords = N_NEW(t->Nodecount,double); // initial x coordinates
- double *y_coords = N_NEW(t->Nodecount,double); // initial y coordinates
+ * double* x_coords; // initial x coordinates
+ * double* y_coords; // initial y coordinates
+ * focus_t* fs;
+ * int ne;
+ * vtx_data* graph = makeGraph (topview*, &ne);
+ * hierarchy = makeHier(topview->NodeCount, ne, graph, x_coords, y_coords);
+ * freeGraph (graph);
+ * fs = initFocus (topview->Nodecount); // create focus set
+ */
+void prepare_topological_fisheye(topview* t)
+{
+ double *x_coords = N_NEW(t->Nodecount, double); // initial x coordinates
+ double *y_coords = N_NEW(t->Nodecount, double); // initial y coordinates
focus_t *fs;
int ne;
int i;
int closest_fine_node;
- int cur_level = 0;
- hierparms_t parms;
- Hierarchy* hp;
- ex_vtx_data* gg;
+ int cur_level = 0;
+ Hierarchy *hp;
+ ex_vtx_data *gg;
+ topview_node *np;
+ reposition_t parms;
- topview_node* np;
vtx_data *graph = makeGraph(t, &ne);
for (i = 0, np = t->Nodes; i < t->Nodecount; i++, np++) {
- x_coords[i] = np->x;
- y_coords[i] = np->y;
- }
- hp = t->h = makeHier(t->Nodecount, ne, graph, x_coords, y_coords);
+ x_coords[i] = np->x;
+ y_coords[i] = np->y;
+ }
+ hp = t->h =
+ makeHier(t->Nodecount, ne, graph, x_coords, y_coords, &(t->parms.hier));
freeGraph(graph);
- free (x_coords);
- free (y_coords);
- fs = initFocus(t->Nodecount); // create focus set
+ free(x_coords);
+ free(y_coords);
+
+ fs = t->fs = initFocus(t->Nodecount); // create focus set
gg = hp->geom_graphs[0];
-/*
- find_closest_active_node(hp, 465.966318,438.649967, &closest_fine_node);
-*/
- closest_fine_node = 0;
-/* fprintf (stderr, "Closest node [%d] %s\n", closest_fine_node, agnameof(t->Nodes[closest_fine_node].Node)); */
+ closest_fine_node = 0; /* first node */
fs->num_foci = 1;
fs->foci_nodes[0] = closest_fine_node;
- fs->x_foci[0] =
- hp->geom_graphs[cur_level][closest_fine_node].x_coord;
- fs->y_foci[0] =
- hp->geom_graphs[cur_level][closest_fine_node].y_coord;
-
- set_active_levels(hp, fs->foci_nodes, fs->num_foci);
-
- parms.rescale = NoRescale;
-/* parms.width=view->bdxRight-view->bdxLeft;
- parms.height=view->bdyTop-view->bdyBottom;
- parms.margin=0;
- parms.graphSize=100;*/
+ fs->x_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].x_coord;
+ fs->y_foci[0] = hp->geom_graphs[cur_level][closest_fine_node].y_coord;
+
+ set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->parms.level));
+
+ parms.rescale = Polar;
+ parms.width=view->bdxRight-view->bdxLeft;
+ parms.height=view->bdyTop-view->bdyBottom;
+ parms.margin=0;
+ parms.graphSize=100;
+ parms.distortion=1.0;
positionAllItems(hp, fs, &parms);
+ /* positionAllItems(hp, fs, &(t->parms.repos)); */
/* fprintf (stderr, "No. of active nodes = %d\n", count_active_nodes(hp)); */
+
}
-void drawtopologicalfisheye(topview* t)
+void drawtopologicalfisheye(topview * t)
{
int level, v, i, n;
- Hierarchy* hp = t->h;
-
- glPointSize(3);
- glBegin(GL_POINTS);
- for (level=0;level < hp->nlevels;level++) {
- for (v=0;v < hp->nvtxs[level]; v++) {
- ex_vtx_data* gg = hp->geom_graphs[level];
- vtx_data* g = hp->graphs[level];
- if(gg[v].active_level==level) {
+ Hierarchy *hp = t->h;
+
+ glPointSize(3);
+ glBegin(GL_POINTS);
+ for (level = 0; level < hp->nlevels; level++) {
+ for (v = 0; v < hp->nvtxs[level]; v++) {
+ ex_vtx_data *gg = hp->geom_graphs[level];
+ if (gg[v].active_level == level) {
double x0 = gg[v].physical_x_coord;
double y0 = gg[v].physical_y_coord;
- glColor3f((GLfloat)(hp->nlevels-level)/(GLfloat)hp->nlevels,(GLfloat)level/(GLfloat)hp->nlevels,0);
- glVertex3f((GLfloat)x0,(GLfloat)y0,(GLfloat)0);
+ glColor3f((GLfloat) (hp->nlevels - level) /
+ (GLfloat) hp->nlevels,
+ (GLfloat) level / (GLfloat) hp->nlevels, 0);
+ glVertex3f((GLfloat) x0, (GLfloat) y0, (GLfloat) 0);
}
}
}
glEnd();
-
-
-
- glBegin(GL_LINES);
- for (level=0;level < hp->nlevels;level++) {
- for (v=0;v < hp->nvtxs[level]; v++) {
- ex_vtx_data* gg = hp->geom_graphs[level];
- vtx_data* g = hp->graphs[level];
- if(gg[v].active_level==level) {
+ glBegin(GL_LINES);
+ for (level = 0; level < hp->nlevels; level++) {
+ for (v = 0; v < hp->nvtxs[level]; v++) {
+ ex_vtx_data *gg = hp->geom_graphs[level];
+ vtx_data *g = hp->graphs[level];
+ if (gg[v].active_level == level) {
double x0 = gg[v].physical_x_coord;
double y0 = gg[v].physical_y_coord;
- for (i=1;i < g[v].nedges;i++) {
- double x,y;
- n = g[v].edges[i];
- glColor3f((GLfloat)(hp->nlevels-level)/(GLfloat)hp->nlevels,(GLfloat)level/(GLfloat)hp->nlevels,0);
- if (gg[n].active_level == level) {
+ for (i = 1; i < g[v].nedges; i++) {
+ double x, y;
+ n = g[v].edges[i];
+ glColor3f((GLfloat) (hp->nlevels - level) /
+ (GLfloat) hp->nlevels,
+ (GLfloat) level / (GLfloat) hp->nlevels, 0);
+ if (gg[n].active_level == level) {
if (v < n) {
x = gg[n].physical_x_coord;
y = gg[n].physical_y_coord;
- glVertex3f((GLfloat)x0,(GLfloat)y0,(GLfloat)0);
- glVertex3f((GLfloat)x,(GLfloat)y,(GLfloat)0);
+ glVertex3f((GLfloat) x0, (GLfloat) y0,
+ (GLfloat) 0);
+ glVertex3f((GLfloat) x, (GLfloat) y,
+ (GLfloat) 0);
}
- }
- else if (gg[n].active_level > level) {
+ } else if (gg[n].active_level > level) {
find_physical_coords(hp, level, n, &x, &y);
- glVertex3f((GLfloat)x0,(GLfloat)y0,(GLfloat)0);
- glVertex3f((GLfloat)x,(GLfloat)y,(GLfloat)0);
+ glVertex3f((GLfloat) x0, (GLfloat) y0,
+ (GLfloat) 0);
+ glVertex3f((GLfloat) x, (GLfloat) y, (GLfloat) 0);
}
}
}
}
glEnd();
}
-void changetopologicalfisheyefocus(topview* t,float* x,float* y,float* z,int num_foci)
-{
+
/* In loop,
- update fs.
- For example, if user clicks mouse at (p.x,p.y) to pick a single new focus,
- int closest_fine_node;
- find_closest_active_node(hierarchy, p.x, p.y, &closest_fine_node);
- fs->num_foci = 1;
- fs->foci_nodes[0] = closest_fine_node;
- fs->x_foci[0] =
-hierarchy->geom_graphs[cur_level][closest_fine_node].x_coord;
- fs->y_foci[0] =
-hierarchy->geom_graphs[cur_level][closest_fine_node].y_coord;
-
- set_active_levels(hierarchy, fs->foci_nodes, fs->num_foci);
- positionAllItems(hierarchy, fs, parms)*/
-
- focus_t *fs;
- int ne;
+ * update fs.
+ * For example, if user clicks mouse at (p.x,p.y) to pick a single new focus,
+ * int closest_fine_node;
+ * find_closest_active_node(hierarchy, p.x, p.y, &closest_fine_node);
+ * fs->num_foci = 1;
+ * fs->foci_nodes[0] = closest_fine_node;
+ * fs->x_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].x_coord;
+ * fs->y_foci[0] = hierarchy->geom_graphs[cur_level][closest_fine_node].y_coord;
+ * set_active_levels(hierarchy, fs->foci_nodes, fs->num_foci);
+ * positionAllItems(hierarchy, fs, parms)
+ */
+void changetopfishfocus(topview * t, float *x, float *y,
+ float *z, int num_foci)
+{
+ focus_t *fs = t->fs;
int i;
int closest_fine_node;
- int cur_level = 0;
- hierparms_t parms;
- Hierarchy* hp;
-
-// ex_vtx_data* gg;
-
- topview_node* np;
- printf ("c(%f,%f) z:%f\n",x[0],y[0],view->zoom);
-
- hp = t->h;
- fs = initFocus(t->Nodecount); // create focus set
-// gg = hp->geom_graphs[0];
-
-
- fs->num_foci = num_foci;
- for (i=0;i < num_foci;i++)
- {
- find_closest_active_node(hp, x[i],y[i], &closest_fine_node);
- fs->foci_nodes[i] = closest_fine_node;
- fs->x_foci[i] =
- hp->geom_graphs[cur_level][closest_fine_node].x_coord;
- fs->y_foci[i] =
- hp->geom_graphs[cur_level][closest_fine_node].y_coord;
- }
-
+ int cur_level = 0;
+ Hierarchy *hp = t->h;
+
+ fs->num_foci = num_foci;
+ for (i = 0; i < num_foci; i++) {
+ find_closest_active_node(hp, x[i], y[i], &closest_fine_node);
+ fs->foci_nodes[i] = closest_fine_node;
+ fs->x_foci[i] =
+ hp->geom_graphs[cur_level][closest_fine_node].x_coord;
+ fs->y_foci[i] =
+ hp->geom_graphs[cur_level][closest_fine_node].y_coord;
+ }
-
- set_active_levels(hp, fs->foci_nodes, fs->num_foci);
- parms.rescale = NoRescale;
- positionAllItems(hp, fs, &parms);
+ set_active_levels(hp, fs->foci_nodes, fs->num_foci, &(t->parms.level));
+ positionAllItems(hp, fs, &(t->parms.repos));
}
+
+/* vim:set shiftwidth=4 ts=8: */
+
+/**********************************************************
+* This software is part of the graphviz package *
+* http://www.graphviz.org/ *
+* *
+* Copyright (c) 1994-2004 AT&T Corp. *
+* and is licensed under the *
+* Common Public License, Version 1.0 *
+* by AT&T Corp. *
+* *
+* Information and Software Systems Research *
+* AT&T Research, Florham Park NJ *
+**********************************************************/
#ifndef TOPFISHEYEVIEW_H
#define TOPFISHEYEVIEW_H
+
#include "smyrnadefs.h"
+#include "hier.h"
void fisheye_polar(double x_focus, double y_focus, topview * t);
-void fisheye_spherical(double x_focus, double y_focus,double z_focus, topview * t);
-void prepare_topological_fisheye(topview * t);
+void fisheye_spherical(double x_focus, double y_focus, double z_focus,
+ topview * t);
+void prepare_topological_fisheye(topview*);
void drawtopologicalfisheye(topview * t);
-void changetopologicalfisheyefocus(topview* t,float* x,float* y,float* z,int num_foci);
-#endif
+void changetopfishfocus(topview * t, float *x, float *y,
+ float *z, int num_foci);
+#endif
#ifndef TOPVIEW_H
#define TOPVIEW_H
-
#include "smyrnadefs.h"
#ifdef WIN32 //this is needed on WIN32 to get libglade see the callback
#define _BB __declspec(dllexport)
view->Selection.SelectionColor.A = 1;
view->Selection.Anti = 0;
view->Topview = GNEW(topview);
+ view->Topview->fs = 0;
+
+ /* init topfish parameters */
+ view->Topview->parms.level.num_fine_nodes = 50;
+ view->Topview->parms.level.coarsening_rate = 2.5;
+ view->Topview->parms.hier.dist2_limit = 1;
+ view->Topview->parms.hier.min_nvtxs = 20;
+ view->Topview->parms.repos.rescale = NoRescale;
+
view->Topview->topviewmenu = '\0';
view->cameras='\0';;
view->camera_count=0;
#include "hierarchy.h"
static int cur_level = 0;
-static int num_fine_nodes = 50;
-static double coarsening_rate = 2.5;
-static int dist2_limit = 1; // don't contract nodes of distance larger than 2
- // if 'false' then also distance 3 is possible
/////////////////////////
// Some utilities for //
maxmatch(vtx_data * graph, /* array of vtx data for graph */
ex_vtx_data * geom_graph, /* array of vtx data for graph */
int nvtxs, /* number of vertices in graph */
- int *mflag /* flag indicating vtx selected or not */
+ int *mflag, /* flag indicating vtx selected or not */
+ int dist2_limit
)
/*
Compute a matching of the nodes set.
int *cnedges, /* number of edges in coarsened graph */
int *cgeom_nedges, /* number of edges in coarsened geom_graph */
int **v2cvp, /* reference from vertices to coarse vertices */
- int **cv2vp /* reference from vertices to coarse vertices */
+ int **cv2vp, /* reference from vertices to coarse vertices */
+ int dist2_limit
)
/*
mflag = N_NEW(nvtxs, int);
/* Find a maximal matching in the graphs */
- nmerged = maxmatch(graph, geom_graph, nvtxs, mflag);
+ nmerged = maxmatch(graph, geom_graph, nvtxs, mflag, dist2_limit);
/* Now construct coarser graph by contracting along matching edges. */
/* Pairs of values in mflag array indicate matched vertices. */
Hierarchy *create_hierarchy(vtx_data * graph, int nvtxs, int nedges,
ex_vtx_data * geom_graph, int ngeom_edges,
- int min_nvtxs)
+ hierparms_t* parms)
{
int cur_level;
Hierarchy *hierarchy = NEW(Hierarchy);
ex_vtx_data *geom_graph_level;
int nodeIndex = 0;
int i, j;
+ int min_nvtxs = parms->min_nvtxs;
int nlevels = MAX(5, 10 * (int) log((float) (nvtxs / min_nvtxs))); // just an estimate
hierarchy->graphs = N_NEW(nlevels, vtx_data *);
&hierarchy->geom_graphs[cur_level + 1],
&hierarchy->nvtxs[cur_level + 1],
&hierarchy->nedges[cur_level + 1], &cngeom_edges,
- &hierarchy->v2cv[cur_level], &hierarchy->cv2v[cur_level + 1]);
+ &hierarchy->v2cv[cur_level], &hierarchy->cv2v[cur_level + 1],
+ parms->dist2_limit);
}
hierarchy->nlevels = cur_level + 1;
* If the active level equals the node's level then the node is currently shown
*/
void
-set_active_levels(Hierarchy * hierarchy, int *foci_nodes, int num_foci)
+set_active_levels(Hierarchy * hierarchy, int *foci_nodes, int num_foci,
+ levelparms_t* parms)
{
int n, i;
int *nodes;
* factor: 'coarsening_rate'
*/
level = min_level;
- group_size = num_fine_nodes * num_foci;
+ group_size = parms->num_fine_nodes * num_foci;
thresh = group_size;
for (i = 0; i < n; i++) {
vtx = nodes[i];
if (i > thresh && level < hierarchy->nlevels - 1) {
level++;
- group_size = (int) (group_size * coarsening_rate);
+ group_size = (int) (group_size * parms->coarsening_rate);
thresh += group_size;
}
graph[vtx].active_level = level;
float physical_y_coord;
} ex_vtx_data;
-
typedef struct {
int nlevels;
vtx_data ** graphs;
int maxNodeIndex;
} Hierarchy;
+typedef struct {
+ int num_fine_nodes; /* 50 */
+ double coarsening_rate; /* 2.5 */
+} levelparms_t;
+
+typedef struct {
+ // if dist2_limit true, don't contract nodes of distance larger than 2
+ // if false then also distance 3 is possible
+ int dist2_limit; /* TRUE */
+ int min_nvtxs; /* 20 */
+} hierparms_t;
+
void release(Hierarchy*);
+
Hierarchy* create_hierarchy(vtx_data * graph, int nvtxs, int nedges,
- ex_vtx_data* geom_graph, int ngeom_edges, int min_nvtxs);
+ ex_vtx_data* geom_graph, int ngeom_edges, hierparms_t*);
-void set_active_levels(Hierarchy*, int*, int);
+void set_active_levels(Hierarchy*, int*, int, levelparms_t*);
double find_closest_active_node(Hierarchy*, double x, double y, int*);
int extract_active_logical_coords(Hierarchy * hierarchy, int node, int level,
// layout distortion:
void rescale_layout(double *x_coords, double *y_coords,
int n, int interval, double width, double height,
- double margin);
+ double margin, double distortion);
void rescale_layout_polar(double * x_coords, double * y_coords,
- double * x_foci, double * y_foci, int num_foci,
- int n, int interval, double width, double height, double margin);
+ double * x_foci, double * y_foci, int num_foci, int n, int interval,
+ double width, double height, double margin, double distortion);
void find_physical_coords(Hierarchy*, int, int, double *x, double *y);
int find_active_ancestor(Hierarchy*, int, int);
#include "memory.h"
#include "arith.h"
-static double distortion_factor = 1.0;
-
static double *compute_densities(vtx_data * graph, int n, double *x,
double *y)
{
static void
rescaleLayout(vtx_data * graph, int n, double *x_coords, double *y_coords,
- int interval)
+ int interval, double distortion)
{
// Rectlinear distortion - auxilliary function
int i;
}
// just to make milder behavior:
- if (distortion_factor >= 0) {
- factor = sqrt(distortion_factor);
+ if (distortion >= 0) {
+ factor = sqrt(distortion);
} else {
- factor = -sqrt(-distortion_factor);
+ factor = -sqrt(-distortion);
}
quicksort_place(x_coords, ordering, 0, n - 1);
densities = recompute_densities(graph, n, x_coords, densities);
- smooth_vec(densities, ordering, n, interval, smoothed_densities);
+ smoothed_densities = smooth_vec(densities, ordering, n, interval, smoothed_densities);
cpvec(copy_coords, 0, n - 1, x_coords);
for (i = 1; i < n; i++) {
x_coords[ordering[i]] =
quicksort_place(y_coords, ordering, 0, n - 1);
densities = recompute_densities(graph, n, y_coords, densities);
- smooth_vec(densities, ordering, n, interval, smoothed_densities);
+ smoothed_densities = smooth_vec(densities, ordering, n, interval, smoothed_densities);
cpvec(copy_coords, 0, n - 1, y_coords);
for (i = 1; i < n; i++) {
y_coords[ordering[i]] =
void
rescale_layout(double *x_coords, double *y_coords,
int n, int interval, double width, double height,
- double margin)
+ double margin, double distortion)
{
// Rectlinear distortion - main function
int i;
// construct mutual neighborhood graph
graph = UG_graph(x_coords, y_coords, n, 0);
- rescaleLayout(graph, n, x_coords, y_coords, interval);
+ rescaleLayout(graph, n, x_coords, y_coords, interval, distortion);
free(graph[0].edges);
free(graph);
static void
rescale_layout_polarFocus(vtx_data * graph, int n,
- double *x_coords, double *y_coords,
- double x_focus, double y_focus, int interval)
+ double *x_coords, double *y_coords,
+ double x_focus, double y_focus, int interval, double distortion)
{
// Polar distortion - auxilliary function
int i;
quicksort_place(distances, ordering, 0, n - 1);
densities = compute_densities(graph, n, x_coords, y_coords);
- smooth_vec(densities, ordering, n, interval, smoothed_densities);
+ smoothed_densities = smooth_vec(densities, ordering, n, interval, smoothed_densities);
// rescale distances
- if (distortion_factor < 1.01 && distortion_factor > 0.99) {
+ if (distortion < 1.01 && distortion > 0.99) {
for (i = 1; i < n; i++) {
distances[ordering[i]] =
distances[ordering[i - 1]] + (orig_distances[ordering[i]] -
orig_distances[ordering
[i -
- 1]]) /
- smoothed_densities[ordering[i]];
+ 1]]) / smoothed_densities[ordering[i]];
}
} else {
double factor;
// just to make milder behavior:
- if (distortion_factor >= 0) {
- factor = sqrt(distortion_factor);
+ if (distortion >= 0) {
+ factor = sqrt(distortion);
} else {
- factor = -sqrt(-distortion_factor);
+ factor = -sqrt(-distortion);
}
for (i = 1; i < n; i++) {
distances[ordering[i]] =
rescale_layout_polar(double *x_coords, double *y_coords,
double *x_foci, double *y_foci, int num_foci,
int n, int interval, double width,
- double height, double margin)
+ double height, double margin, double distortion)
{
// Polar distortion - main function
int i;
if (num_foci == 1) { // accelerate execution of most common case
rescale_layout_polarFocus(graph, n, x_coords, y_coords, x_foci[0],
- y_foci[0], interval);
+ y_foci[0], interval, distortion);
} else {
// average-based rescale
double *final_x_coords = N_NEW(n, double);
cpvec(cp_x_coords, 0, n - 1, x_coords);
cpvec(cp_y_coords, 0, n - 1, y_coords);
rescale_layout_polarFocus(graph, n, cp_x_coords, cp_y_coords,
- x_foci[i], y_foci[i], interval);
+ x_foci[i], y_foci[i], interval, distortion);
scadd(final_x_coords, 0, n - 1, 1.0 / num_foci, cp_x_coords);
scadd(final_y_coords, 0, n - 1, 1.0 / num_foci, cp_y_coords);
}