[xiph-commits] r12777 - trunk/sushivision

xiphmont at svn.xiph.org xiphmont at svn.xiph.org
Mon Mar 19 01:33:09 PDT 2007


Author: xiphmont
Date: 2007-03-19 01:33:06 -0700 (Mon, 19 Mar 2007)
New Revision: 12777

Modified:
   trunk/sushivision/Makefile
   trunk/sushivision/internal.h
   trunk/sushivision/panel-1d.c
   trunk/sushivision/panel-xy.c
   trunk/sushivision/panel-xy.h
Log:
XY panels build, don't run yet



Modified: trunk/sushivision/Makefile
===================================================================
--- trunk/sushivision/Makefile	2007-03-18 14:46:07 UTC (rev 12776)
+++ trunk/sushivision/Makefile	2007-03-19 08:33:06 UTC (rev 12777)
@@ -25,14 +25,14 @@
 SOLDFLAGS = -shared -nostdlib -Wl,-soname="lib$(NAME).so.$(MAJOR)"
 
 SRC       = main.c scale.c plot.c slider.c slice.c spinner.c panel.c panel-1d.c panel-2d.c \
-	mapping.c dimension.c function.c objective.c undo.c gtksucks.c xml.c \
+	panel-xy.c mapping.c dimension.c function.c objective.c undo.c gtksucks.c xml.c \
 	example_fractal.c example_discrete.c example_chirp.c
 INC       = sushivision.h
 MAN	  =
 EXAMPLES  = sushivision_fractal sushivision_discrete sushivision_chirp
 EX_OBJ    = example_fractal.o example_discrete.o example_chirp.o
 OBJ       = main.o scale.o plot.o slider.o slice.o spinner.c panel.o panel-1d.o panel-2d.o \
-	mapping.o dimension.o function.o objective.o undo.o gtksucks.o xml.o
+	panel-xy.o mapping.o dimension.o function.o objective.o undo.o gtksucks.o xml.o
 LIBS      = -lpthread -ldl
 CAIROVER  =  >= 1.4.1
 GTKVER    =  >= 2.10.0

Modified: trunk/sushivision/internal.h
===================================================================
--- trunk/sushivision/internal.h	2007-03-18 14:46:07 UTC (rev 12776)
+++ trunk/sushivision/internal.h	2007-03-19 08:33:06 UTC (rev 12777)
@@ -53,7 +53,7 @@
 #include "gtksucks.h"
 
 union sushiv_panel_subtype {
-  sushiv_panelxy_t *pxy;
+  sushiv_panelxy_t *xy;
   sushiv_panel1d_t *p1;
   sushiv_panel2d_t *p2;
 };
@@ -84,6 +84,7 @@
 
 typedef union {
   _sushiv_bythread_cache_1d p1;
+  _sushiv_bythread_cache_xy xy;
   _sushiv_bythread_cache_2d p2;
 } _sushiv_bythread_cache;
 

Modified: trunk/sushivision/panel-1d.c
===================================================================
--- trunk/sushivision/panel-1d.c	2007-03-18 14:46:07 UTC (rev 12776)
+++ trunk/sushivision/panel-1d.c	2007-03-19 08:33:06 UTC (rev 12777)
@@ -501,7 +501,7 @@
 
   // update colormap
   int pos = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
-  p1->linetype[onum] = line_name[pos].value;
+  p1->linetype[onum] = line_name[pos]->value;
 
   _sushiv_panel_dirty_map(p);
   _sushiv_undo_resume(p->sushi);
@@ -518,7 +518,7 @@
 
   // update colormap
   int pos = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
-  p1->pointtype[onum] = point_name[pos].value;
+  p1->pointtype[onum] = point_name[pos]->value;
 
   _sushiv_panel_dirty_map(p);
   _sushiv_undo_resume(p->sushi);

Modified: trunk/sushivision/panel-xy.c
===================================================================
--- trunk/sushivision/panel-xy.c	2007-03-18 14:46:07 UTC (rev 12776)
+++ trunk/sushivision/panel-xy.c	2007-03-19 08:33:06 UTC (rev 12777)
@@ -54,6 +54,29 @@
   NULL
 };
 
+static void clear_xy_data(sushiv_panel_t *p){
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  int i;
+  
+  if(xy->x_vec){
+    for(i=0;i<p->objectives;i++){
+      if(xy->x_vec[i]){
+	free(xy->x_vec[i]);
+	xy->x_vec[i]=0;
+      }
+    }
+  }
+
+  if(xy->y_vec){
+    for(i=0;i<p->objectives;i++){
+      if(xy->y_vec[i]){
+	free(xy->y_vec[i]);
+	xy->y_vec[i]=0;
+      }
+    }
+  }
+}
+
 static void render_checks(cairo_t *c, int w, int h){
   /* default checked background */
   /* 16x16 'mid-checks' */ 
@@ -78,7 +101,7 @@
 // called internally, assumes we hold lock
 // redraws the data, does not compute the data
 static int _sushiv_panelxy_remap(sushiv_panel_t *p, cairo_t *c){
-  sushiv_panelxy_t *xy = p->subtype->pxy;
+  sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot = PLOT(p->private->graph);
 
   int plot_serialno = p->private->plot_serialno;
@@ -87,9 +110,9 @@
   int pw = plot->x.pixels;
   int ph = plot->y.pixels;
 
-  scalespace sx = p1->x;
-  scalespace sy = p1->y;
-  scalespace data_v = p1->data_v;
+  scalespace sx = xy->x;
+  scalespace sy = xy->y;
+  scalespace data_v = xy->data_v;
   scalespace px = plot->x;
   scalespace py = plot->y;
     
@@ -126,13 +149,13 @@
   if(plot_serialno != p->private->plot_serialno ||
      map_serialno != p->private->map_serialno) return -1;
 
-  if(xy->data_head){
+  if(xy->x_vec && xy->y_vec){
     
     /* by objective */
     for(j=0;j<p->objectives;j++){
       if(xy->x_vec[j] && xy->y_vec[j] && !mapping_inactive_p(xy->mappings+j)){
 	
-	int dw = xy->data_v.pixels;
+	int dw = data_v.pixels;
 	double alpha = slider_get_value(xy->alpha_scale[j],0);
 	int linetype = xy->linetype[j];
 	int pointtype = xy->pointtype[j];
@@ -261,8 +284,6 @@
 	gdk_threads_enter();
 	if(plot_serialno != p->private->plot_serialno ||
 	   map_serialno != p->private->map_serialno) return -1;
-	
-	
       }
     }
   }
@@ -307,14 +328,14 @@
     // if crosshairs are active, add them to the fun
     if( plot->cross_active){
       snprintf(buffer,320,"%s = %+.*f",
-	       xy->x_scale.name,
+	       xy->x_scale->legend,
 	       depth,
-	       xy->x_val);
+	       plot->selx);
       plot_legend_add(plot,buffer);
       snprintf(buffer,320,"%s = %+.*f",
-	       xy->y_scale.name,
+	       xy->y_scale->legend,
 	       depth,
-	       xy->y_val);
+	       plot->sely);
       plot_legend_add(plot,buffer);
 
       if(p->dimensions)
@@ -341,33 +362,33 @@
 }
 
 // call with lock
-static double _determine_rerender_metric(sushiv_panel_t *p, int half){
+static double _determine_rerender_metric(sushiv_panel_t *p, int off){
   sushiv_panelxy_t *xy = p->subtype->xy;
   int on = p->objectives;
   double pw = p->private->graph->allocation.width;
   double ph = p->private->graph->allocation.height;
   int dw = xy->data_v.pixels;
-  int off = (half?2;1);
 
   // if this is a discrete data set, size/view changes cannot affect
   // the data spacing; that's set by the discrete scale
-  if(p->x_d->type != SUSHIV_DIM_CONTINUOUS) return -1;
+  if(xy->x_d->type != SUSHIV_DIM_CONTINUOUS) return -1;
 
   double xscale = scalespace_pixel(&xy->x,1.) - scalespace_pixel(&xy->x,0.);
   double yscale = scalespace_pixel(&xy->y,1.) - scalespace_pixel(&xy->y,0.);
 
   // by plane, look at the spacing between visible x/y points
   double max = -1;
+  int i,j;
   for(i=0;i<on;i++){
 
     if(xy->x_vec[j] && xy->y_vec[j] && !mapping_inactive_p(xy->mappings+i)){
       double xacc = 0;
       double yacc = 0;
       double count = 0;
-      double *x = p->x_vec[i];
-      double *y = p->y_vec[i];
+      double *x = xy->x_vec[i];
+      double *y = xy->y_vec[i];
       
-      for(j = off; j+off<=dw, j+=off){
+      for(j = off; j<dw; j++){
 	if(!isnan(x[i-off]) &&
 	   !isnan(y[i-off]) &&
 	   !isnan(x[i]) &&
@@ -383,7 +404,7 @@
 	}
       }
 
-      acc = sqrt(xacc*xscale*xscale + yacc*yscale*yscale);
+      double acc = sqrt(xacc*xscale*xscale + yacc*yscale*yscale);
 
       if(count>0)
 	if(acc/count > max) max = acc/count;
@@ -395,38 +416,48 @@
 }
 
 // call while locked
-static int _mark_recompute_by_metric_change(sushiv_panel_t *p, int recursing){
+static int _mark_recompute_by_metric(sushiv_panel_t *p, int recursing){
+  sushiv_panelxy_t *xy = p->subtype->xy;
+
   // discrete val dimensions are immune to rerender by metric changes
-  if(p->x_d->type != SUSHIV_DIM_CONTINUOUS) return 0; 
+  if(xy->x_d->type != SUSHIV_DIM_CONTINUOUS) return 0; 
 
-  sushiv_panelxy_t *xy = p->subtype->xy;
   double target = (double) p->private->oversample_n / p->private->oversample_d;
-  double full =  _determine_rerender_metric(p, 0);
-  
-  if(!recursing) xy->request_scaling = 0;
+  double full =  _determine_rerender_metric(p, 1);
 
   if(full > target){
     // we want to halve the sample spacing.  But first make sure we're
     // not looping due to uncertainties in the metric.
-    if(xy->request_scaling != -1){
-      xy->request_scaling = 1; // double pixels, halve spacing
-      _sushiv_panel_dirty_plot(p); // trigger recompute
-      return 1;
-    }
+    if(recursing && xy->prev_zoom > xy->curr_zoom) return 0;
+
+    // also make sure our zoom level doesn't underflow
+    if(xy->data_v.massaged) return 0; 
+
+    xy->prev_zoom = xy->curr_zoom;
+    xy->curr_zoom++;
+
+    _sushiv_panel_dirty_plot(p); // trigger recompute
+    return 1;
   } else {
-    double half =  _determine_rerender_metric(p, 1);
+    double half =  _determine_rerender_metric(p, 2);
     if(half < target){
       // we want to double the sample spacing.  But first make sure we're
       // not looping due to uncertainties in the metric.
-      if(xy->request_scaling != 1){
-	xy->request_scaling = -1; // halve pixels, double spacing
-	_sushiv_panel_dirty_plot(p); // trigger recompute
-	return 1;
-      }
+      if(recursing && xy->prev_zoom < xy->curr_zoom) return 0;
+
+      // also make sure our zoom level doesn't overrflow
+      if(xy->curr_zoom == 0) return 0;
+
+      xy->prev_zoom = xy->curr_zoom;
+      xy->curr_zoom--;
+      
+      _sushiv_panel_dirty_plot(p); // trigger recompute
+      return 1;
+      
     }
   }
 
-  xy->request_scaling = 0;
+  xy->prev_zoom = xy->curr_zoom;
   return 0;
 }
 
@@ -435,7 +466,8 @@
   sushiv_panel_t *p = optr->p;
   sushiv_panelxy_t *xy = p->subtype->xy;
   int onum = optr - p->objective_list;
-  
+  Plot *plot = PLOT(p->private->graph);
+
   _sushiv_undo_push(p->sushi);
   _sushiv_undo_suspend(p->sushi);
 
@@ -445,14 +477,21 @@
   solid_set_func(&xy->mappings[onum],pos);
   slider_set_gradient(xy->alpha_scale[onum], &xy->mappings[onum]);
   
+  // if the mapping has become inactive and the crosshairs point to
+  // this objective, inactivate the crosshairs.
+  if(xy->cross_objnum == onum)
+    plot->cross_active = 0;
+
   // a map view size change may trigger a progressive up/down render,
   // but will at least cause a remap
-  if(!_mark_recompute_by_metric_change(p,0))
-    _sushiv_panel_dirty_map(p);
+  _mark_recompute_by_metric(p,0);
+
+  _sushiv_panel_dirty_map(p);
   _sushiv_panel_dirty_legend(p);
+
   _sushiv_undo_resume(p->sushi);
 }
-XXX
+
 static void alpha_callback_xy(void * in, int buttonstate){
   sushiv_objective_list_t *optr = (sushiv_objective_list_t *)in;
   sushiv_panel_t *p = optr->p;
@@ -480,7 +519,7 @@
 
   // update colormap
   int pos = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
-  xy->linetype[onum] = line_name[pos].value;
+  xy->linetype[onum] = line_name[pos]->value;
 
   _sushiv_panel_dirty_map(p);
   _sushiv_undo_resume(p->sushi);
@@ -497,7 +536,7 @@
 
   // update colormap
   int pos = gtk_combo_box_get_active(GTK_COMBO_BOX(w));
-  xy->pointtype[onum] = point_name[pos].value;
+  xy->pointtype[onum] = point_name[pos]->value;
 
   _sushiv_panel_dirty_map(p);
   _sushiv_undo_resume(p->sushi);
@@ -505,7 +544,7 @@
 
 static void map_callback_xy(void *in,int buttonstate){
   sushiv_panel_t *p = (sushiv_panel_t *)in;
-  sushiv_panel1d_t *xy = p->subtype->xy;
+  sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot = PLOT(p->private->graph);
   
   if(buttonstate == 0){
@@ -527,25 +566,25 @@
     xy->y_bracket[0] = slider_get_value(xy->y_slider,0);
     xy->y_bracket[1] = slider_get_value(xy->y_slider,1);
     
-    xy->x = scalespace_linear(xy->x_bracket[1],
-			      xy->x_bracket[0],
-			      w,
-			      plot->scalespacing,
-			      xy->x_scale->legend);
-    xy->y = scalespace_linear(xy->y_bracket[1],
-			      xy->y_bracket[0],
-			      h,
-			      plot->scalespacing,
-			      xy->y_scale->legend);
+  
+    plot->x = xy->x = scalespace_linear(xy->x_bracket[1],
+					xy->x_bracket[0],
+					w,
+					plot->scalespacing,
+					xy->x_scale->legend);
+    plot->y = xy->y = scalespace_linear(xy->y_bracket[1],
+					xy->y_bracket[0],
+					h,
+					plot->scalespacing,
+					xy->y_scale->legend);
 
+    // a map view size change may trigger a progressive up/down render,
+    // but will at least cause a remap
+    _mark_recompute_by_metric(p,0);
+    
+    _sushiv_panel_dirty_map(p);
+    
   }
-XXX
-  // a map view size change may trigger a progressive up/down render,
-  // but will at least cause a remap
-  if(_determine_rerender_by_metric(p))
-    _mark_recompute_xy(p);
-  else
-    _sushiv_panel_dirty_map(p);
 
   if(buttonstate == 2)
     _sushiv_undo_resume(p->sushi);
@@ -580,232 +619,147 @@
 }
 
 static void compute_xy(sushiv_panel_t *p, 
+		       int serialno,
 		       int x_d, 
 		       scalespace sxi,
 		       double *dim_vals,
+		       char *prefilled,
 		       double **x_vec,
 		       double **y_vec,
-		       _sushiv_bythread_cache_1d *c){
-  sushiv_panelxy_t *xy = p->subtype->xy;
+		       _sushiv_bythread_cache_xy *c){
+
   int i,j,fn=p->sushi->functions;
   int w = sxi.pixels;
 
   /* by x */
   for(j=0;j<w;j++){
-    dim_vals[x_d] = scalespace_value(&sxi,j);
-
-    /* by function */
-    for(i=0;i<fn;i++){
-      if(c->call[i]){
-	sushiv_function_t *f = p->sushi->function_list[i];
-	double *fout = c->fout[i];
-      	c->call[i](dim_vals,fout);
+    if(!prefilled[j]){
+      dim_vals[x_d] = scalespace_value(&sxi,j);
+      
+      /* by function */
+      for(i=0;i<fn;i++){
+	if(c->call[i]){
+	  double *fout = c->fout[i];
+	  c->call[i](dim_vals,fout);
+	}
       }
+      
+      /* process function output by objective */
+      /* xy panels currently only care about the XY output values; in the
+	 future, Z and others may also be relevant */
+      for(i=0;i<p->objectives;i++){
+	sushiv_objective_t *o = p->objective_list[i].o;
+	int xoff = o->private->x_fout;
+	int yoff = o->private->y_fout;
+	sushiv_function_t *xf = o->private->x_func;
+	sushiv_function_t *yf = o->private->y_func;
+	x_vec[i][j] = c->fout[xf->number][xoff];
+	y_vec[i][j] = c->fout[yf->number][yoff];
+      }
     }
 
-    /* process function output by objective */
-    /* xy panels currently only care about the XY output values; in the
-       future, Z may also be relevant */
-    for(i=0;i<p->objectives;i++){
-      sushiv_objective_t *o = p->objective_list[i].o;
-      int xoff = o->private->x_fout;
-      int yoff = o->private->y_fout;
-      sushiv_function_t *xf = o->private->x_func;
-      sushiv_function_t *yf = o->private->y_func;
-      x_vec[j] = c->fout[xf->number][xoff];
-      y_vec[j] = c->fout[yf->number][yoff];
+    if(!(j&0x3f)){
+      gdk_threads_enter();
+      
+      if(serialno != p->private->plot_serialno){
+	gdk_threads_leave();
+	return;
+      }
+
+      spinner_set_busy(p->private->spinner);
+      gdk_threads_leave();
     }
   }
 }
 
-// call only from main gtk thread
+// call with lock
 void _mark_recompute_xy(sushiv_panel_t *p){
   if(!p->private->realized) return;
+
+  _sushiv_panel_dirty_plot(p);
+}
+
+static void recompute_callback_xy(void *ptr){
+  sushiv_panel_t *p = (sushiv_panel_t *)ptr;
   sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot = PLOT(p->private->graph);
   int w = plot->w.allocation.width;
   int h = plot->w.allocation.height;
-  int dw = w;
-  int i,j;
 
-XXXX
-  if(plot && GTK_WIDGET_REALIZED(GTK_WIDGET(plot))){
-      dw = _sushiv_dimension_scales(p1->x_d, 
-				    p1->x_d->bracket[0],
-				    p1->x_d->bracket[1],
-				    w,dw * p->private->oversample_n / p->private->oversample_d,
-				    plot->scalespacing,
-				    p1->x_d->name,
-				    &p1->x,
-				    &p1->x_v,
-				    &p1->x_i);
+  plot->x = xy->x = scalespace_linear(xy->x_bracket[0],
+				      xy->x_bracket[1],
+				      w,
+				      plot->scalespacing,
+				      xy->x_scale->legend);
+  plot->y =  xy->y = scalespace_linear(xy->y_bracket[1],
+				       xy->y_bracket[0],
+				       h,
+				       plot->scalespacing,
+				       xy->y_scale->legend);
 
-      p1->y = scalespace_linear(p1->range_bracket[1],
-				p1->range_bracket[0],
-				h,
-				plot->scalespacing,
-				p1->range_scale->legend);
-    }
+  // always recompute, but also update zoom
+  if(!_mark_recompute_by_metric(p,0))
+    _mark_recompute_xy(p);
+}
 
-    if(p1->data_size != dw){
-      if(p1->data_vec){
+static void update_crosshair(sushiv_panel_t *p){
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  Plot *plot = PLOT(p->private->graph);
 
-	// make new vec
-	int i;
-	for(i=0;i<p->objectives;i++){
-	  double *new_vec = malloc(dw * sizeof(**p1->data_vec));
 
-	  free(p1->data_vec[i]);
-	  p1->data_vec[i] = new_vec;
-	}
-      }
-    }
-    
-    p1->data_size = dw;
-    p1->panel_w = w;
-    p1->panel_h = h;
-    
-    if(!p1->data_vec){
-      // allocate it
+  if(!p->private->realized)return;
 
-      p1->data_vec = calloc(p->objectives,sizeof(*p1->data_vec));
-      for(i=0;i<p->objectives;i++)
-	p1->data_vec[i] = malloc(dw*sizeof(**p1->data_vec));
-      
-    }
+  // crosshairs snap to the x/y location of a point; however, with
+  // multiple objectives, there are probably multiple possible points.
+  // So, if we're currently pointing to a point for a given objective,
+  // update to a point on the same objective.  Otherwise if crosshairs
+  // are inactive, do nothing.
 
-    // blank it 
-    for(i=0;i<p->objectives;i++)
-      for(j=0;j<dw;j++)
-	p1->data_vec[i][j]=NAN;
+  if(!plot->cross_active)return;
+  if(xy->cross_objnum<0 || xy->cross_objnum >= p->objectives)return;
+  if(!xy->x_vec || !xy->y_vec)return;
+  if(!xy->x_vec[xy->cross_objnum] || !xy->y_vec[xy->cross_objnum])return;
 
-    _sushiv_panel_dirty_plot(p);
-  }
-}
+  // get bin number of dim value
+  int x_bin = scalespace_pixel(&xy->data_v, xy->x_d->val);
+  double x = xy->x_vec[xy->cross_objnum][x_bin];
+  double y = xy->y_vec[xy->cross_objnum][x_bin];
 
-static void recompute_callback_1d(void *ptr){
-  sushiv_panel_t *p = (sushiv_panel_t *)ptr;
-  _mark_recompute_1d(p);
-}
-
-void _sushiv_panel1d_mark_recompute_linked(sushiv_panel_t *p){
-  int i;
-
-  /* look to see if any 1d panels link to passed in panel */
-  sushiv_instance_t *s = p->sushi;
-  for(i=0;i<s->panels;i++){
-    sushiv_panel_t *q = s->panel_list[i];
-    if(q != p && q->type == SUSHIV_PANEL_1D){
-      sushiv_panel1d_t *q1 = q->subtype->p1;
-      if(q1->link_x == p)
-	_mark_recompute_1d(q);
-      else{
-	if(q1->link_y == p)
-	  _mark_recompute_1d(q);
-      }
-    }
-  }
-}
-
-static void update_crosshair(sushiv_panel_t *p){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
-  sushiv_panel_t *link=p1->link_x;
-  Plot *plot = PLOT(p->private->graph);
-  double x=0;
-  int i;
-
-  if(!p->private->realized)return;
+  plot_set_crosshairs(plot,x,y);
   
-  if(p1->link_y)link=p1->link_y;
-
-  if(link){
-    for(i=0;i<link->dimensions;i++){
-      sushiv_dimension_t *d = link->dimension_list[i].d;
-      if(d == p1->x_d)
-	x = link->dimension_list[i].d->val;
-    }
-  }else{
-    for(i=0;i<p->dimensions;i++){
-      sushiv_dimension_t *d = p->dimension_list[i].d;
-      if(d == p1->x_d)
-	x = p->dimension_list[i].d->val;
-    }
-  }
-  
-  if(p1->flip)
-    plot_set_crosshairs(plot,0,x);
-  else
-    plot_set_crosshairs(plot,x,0);
-  
-  // in independent panels, crosshairs snap to a pixel position; the
-  // cached dimension value should be accurate with respect to the
-  // crosshairs.  in linked panels, the crosshairs snap to a pixel
-  // position in the master panel; that is handled in the master, not
-  // here.
-  for(i=0;i<p->dimensions;i++){
-    sushiv_dimension_t *d = p->dimension_list[i].d;
-    sushiv_panel1d_t *p1 = p->subtype->p1;
-    if(d == p1->x_d){
-      if(p1->flip)
-	d->val = scalespace_value(&plot->x,plot_get_crosshair_ypixel(plot));
-      else
-	d->val = scalespace_value(&plot->x,plot_get_crosshair_xpixel(plot));
-    }
-  }
   _sushiv_panel_dirty_legend(p);
 }
 
-void _sushiv_panel1d_update_linked_crosshairs(sushiv_panel_t *p, int xflag, int yflag){
-  int i;
-
-  /* look to see if any 1d panels link to passed in panel */
-  sushiv_instance_t *s = p->sushi;
-  for(i=0;i<s->panels;i++){
-    sushiv_panel_t *q = s->panel_list[i];
-    if(q != p && q->type == SUSHIV_PANEL_1D){
-      sushiv_panel1d_t *q1 = q->subtype->p1;
-      if(q1->link_x == p){
-	update_crosshair(q);
-	if(yflag)
-	  q->private->request_compute(q);
-      }else{
-	if(q1->link_y == p){
-	  update_crosshair(q);
-	  if(xflag)
-	    q->private->request_compute(q);
-	}
-      }
-    }
-  }
-}
-
-static void center_callback_1d(sushiv_dimension_list_t *dptr){
+static void center_callback_xy(sushiv_dimension_list_t *dptr){
   sushiv_dimension_t *d = dptr->d;
   sushiv_panel_t *p = dptr->p;
-  sushiv_panel1d_t *p1 = p->subtype->p1;
-  int axisp = (d == p1->x_d);
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  int axisp = (d == xy->x_d);
 
   if(!axisp){
     // mid slider of a non-axis dimension changed, rerender
-    _mark_recompute_1d(p);
+    _mark_recompute_xy(p);
   }else{
     // mid slider of an axis dimension changed, move crosshairs
     update_crosshair(p);
   }
 }
 
-static void bracket_callback_1d(sushiv_dimension_list_t *dptr){
+static void bracket_callback_xy(sushiv_dimension_list_t *dptr){
   sushiv_dimension_t *d = dptr->d;
   sushiv_panel_t *p = dptr->p;
-  sushiv_panel1d_t *p1 = p->subtype->p1;
-  int axisp = d == p1->x_d;
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  int axisp = (d == xy->x_d);
     
+  // always need to recompute, amy also need to update zoom
+
   if(axisp)
-    _mark_recompute_1d(p);
-    
+    if(!_mark_recompute_by_metric(p,0))
+      _mark_recompute_xy(p);
+  
 }
 
-static void dimchange_callback_1d(GtkWidget *button,gpointer in){
+static void dimchange_callback_xy(GtkWidget *button,gpointer in){
   sushiv_panel_t *p = (sushiv_panel_t *)in;
 
   if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(button))){
@@ -813,66 +767,77 @@
     _sushiv_undo_push(p->sushi);
     _sushiv_undo_suspend(p->sushi);
 
-    update_x_sel(p);
-    update_crosshair(p);
+    update_dim_sel(p);
+    
+    // clear data vectors so that none of the data is reused.
+    clear_xy_data(p);
+
+    update_crosshair(p); // which is to say, deactivate it
     plot_unset_box(PLOT(p->private->graph));
-    _mark_recompute_1d(p);
 
+    if(!_mark_recompute_by_metric(p,0))
+      _mark_recompute_xy(p);
+
     _sushiv_undo_resume(p->sushi);
   }
 }
 
 static void crosshair_callback(sushiv_panel_t *p){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
-  sushiv_panel_t *link = p1->link_x;
+  sushiv_panelxy_t *xy = p->subtype->xy;
   double x=PLOT(p->private->graph)->selx;
-  int i;
+  double y=PLOT(p->private->graph)->sely;
+  int i,j;
 
-  if(p1->flip)
-    x=PLOT(p->private->graph)->sely;
-  if(p1->link_y)
-    link=p1->link_y;
+  _sushiv_undo_push(p->sushi);
+  _sushiv_undo_suspend(p->sushi);
   
-  _sushiv_panel_dirty_legend(p);
+  // snap crosshairs to the closest plotted x/y point
+  int besto=-1;
+  int bestbin=-1;
+  double bestdist;
 
-  if(p1->link_x){
-    // make it the master panel's problem.
-    plot_set_crosshairs_snap(PLOT(link->private->graph),
-			     x,
-			     PLOT(link->private->graph)->sely);
-    link->private->crosshair_action(link);
-  }else if (p1->link_y){
-    // make it the master panel's problem.
-    plot_set_crosshairs_snap(PLOT(link->private->graph),
-			     PLOT(link->private->graph)->selx,
-			     x);
-    link->private->crosshair_action(link);
-  }else{
+  for(i=0;i<p->objectives;i++){
+    if(xy->x_vec[i] && xy->y_vec[i] && !mapping_inactive_p(xy->mappings+i)){
+      for(j=0;j<xy->data_v.pixels;j++){
+	double xd = x - xy->x_vec[i][j];
+	double yd = y - xy->y_vec[i][j];
+	double dist = xd*xd + yd*yd;
+	if(besto==-1 || dist<bestdist){
+	  besto = i;
+	  bestbin = j;
+	  bestdist = dist;
+	}
+      }
+    }
+  }
 
-    _sushiv_undo_push(p->sushi);
-    _sushiv_undo_suspend(p->sushi);
+  if(besto>-1){
+    x = xy->x_vec[besto][bestbin];
+    y = xy->y_vec[besto][bestbin];
 
-    for(i=0;i<p->dimensions;i++){
-      sushiv_dimension_t *d = p->dimension_list[i].d;
-      sushiv_panel1d_t *p1 = p->subtype->p1;
-      if(d == p1->x_d)
-	_sushiv_dimension_set_value(p->private->dim_scales[i],1,x);
-	            
-      p->private->oldbox_active = 0;
-    }
-    _sushiv_undo_resume(p->sushi);
+    PLOT(p->private->graph)->selx = x;
+    PLOT(p->private->graph)->sely = y;
+    xy->cross_objnum = besto;
+    
+    double dimval = scalespace_value(&xy->data_v, bestbin);
+    sushiv_dimension_set_value(p->sushi,xy->x_d->number,1,dimval);  
   }
+  
+  p->private->oldbox_active = 0;
+  _sushiv_undo_resume(p->sushi);
+  _sushiv_panel_dirty_legend(p);
+
 }
 
 static void box_callback(void *in, int state){
   sushiv_panel_t *p = (sushiv_panel_t *)in;
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+  sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot = PLOT(p->private->graph);
   
   switch(state){
   case 0: // box set
     _sushiv_undo_push(p->sushi);
-    plot_box_vals(plot,p1->oldbox);
+    plot_box_vals(plot,xy->oldbox);
     p->private->oldbox_active = plot->box_active;
     break;
   case 1: // box activate
@@ -880,9 +845,7 @@
     _sushiv_undo_suspend(p->sushi);
 
     crosshair_callback(p);
-    
-    _sushiv_dimension_set_value(p1->x_scale,0,p1->oldbox[0]);
-    _sushiv_dimension_set_value(p1->x_scale,2,p1->oldbox[1]);
+    map_callback_xy(p,1);
     p->private->oldbox_active = 0;
     _sushiv_undo_resume(p->sushi);
     break;
@@ -890,7 +853,7 @@
   _sushiv_panel_update_menus(p);
 }
 
-void _maintain_cache_1d(sushiv_panel_t *p, _sushiv_bythread_cache_1d *c, int w){
+void _maintain_cache_xy(sushiv_panel_t *p, _sushiv_bythread_cache_xy *c, int w){
   
   /* toplevel initialization */
   if(c->fout == 0){
@@ -905,17 +868,10 @@
 	c->call[o->function_map[j]]=
 	  p->sushi->function_list[o->function_map[j]]->callback;
     }
-  }
 
-  /* once to begin, as well as anytime the data width changes */
-  if(c->storage_width < w){
-    int i;
-    c->storage_width = w;
-
     for(i=0;i<p->sushi->functions;i++){
       if(c->call[i]){
-	if(c->fout[i])free(c->fout[i]);
-	c->fout[i] = malloc(w * p->sushi->function_list[i]->outputs *
+	c->fout[i] = malloc(p->sushi->function_list[i]->outputs *
 			    sizeof(**c->fout));
       }
     }
@@ -923,7 +879,7 @@
 }
 
 // subtype entry point for plot remaps; lock held
-int _sushiv_panel1d_map_redraw(sushiv_panel_t *p, _sushiv_bythread_cache *c){
+int _sushiv_panelxy_map_redraw(sushiv_panel_t *p, _sushiv_bythread_cache *c){
   if(p->private->map_progress_count)return 0;
   p->private->map_progress_count++;
 
@@ -935,7 +891,7 @@
 						     cairo_image_surface_get_height(back));
   cairo_t *ct = cairo_create(cs);
   
-  if(_sushiv_panel1d_remap(p,ct) == -1){ // returns -1 on abort
+  if(_sushiv_panelxy_remap(p,ct) == -1){ // returns -1 on abort
     cairo_destroy(ct);
     cairo_surface_destroy(cs);
   }else{
@@ -952,9 +908,9 @@
 }
 
 // subtype entry point for legend redraws; lock held
-int _sushiv_panel1d_legend_redraw(sushiv_panel_t *p){
+int _sushiv_panelxy_legend_redraw(sushiv_panel_t *p){
   Plot *plot = PLOT(p->private->graph);
-
+  
   if(p->private->legend_progress_count)return 0;
   p->private->legend_progress_count++;
   update_legend(p);
@@ -968,57 +924,143 @@
   return 1;
 }
 
+// dim scales are autozoomed; we want the initial values to quantize
+// to the same grid regardless of zoom level or starting bracket as
+// well as only encompass the desired range
+static int _generate_dimscale_xy(sushiv_dimension_t *d, int zoom, scalespace *v, scalespace *i){
+  scalespace x;
+  
+  if(d->type != SUSHIV_DIM_CONTINUOUS){
+    // non-continuous is unaffected by zoom
+    _sushiv_dimension_scales(d, d->bracket[0], d->bracket[1], 2, 2, 1, d->name, &x, v, i);
+    return 0;
+  }
+
+  // continuous dimensions are, in some ways, handled like a discrete dim.
+  double lo = d->scale->val_list[0];
+  double hi = d->scale->val_list[d->scale->vals-1];
+  _sushiv_dimension_scales(d, lo, hi, 2, 2, 1, NULL, &x, v, i);
+  
+  // generate a new low that is quantized to our coarsest grid
+  lo = scalespace_value(v,0);
+
+  // choose a new resolution, make new scales 
+
+  //  this is iterative, not direct computation, so that at each level
+  // we have a small adjustment (as opposed to one huge adjustment at
+  // the end) as well as more resolution headroom at each level
+  int sofar = 0;
+  while (sofar<zoom){
+    int pixels = v->pixels << 1;
+
+    _sushiv_dimension_scales(d, lo, hi, pixels, pixels, 1, NULL, &x, v, i);
+    if(v->massaged)return 1;
+
+    // clip scales down the the desired part of the range
+    while(v->pixels>2 &&  scalespace_value(v,1) < d->bracket[0]){
+      v->first_pixel--;
+      i->first_pixel--;
+      v->pixels--;
+      i->pixels--;
+    }
+
+    while(v->pixels>2 &&  scalespace_value(v,v->pixels-1) > d->bracket[1]){
+      v->pixels--;
+      i->pixels--;
+    }
+  }
+
+  return 0;
+}
+
+static void _rescale_xy(scalespace *old, double **oldx, double **oldy,
+			scalespace *new, double **newx, double **newy,
+			char *prefilled, int objectives){
+
+  if(!oldx || !oldy)return;
+
+  int newi = 0;
+  int oldi = 0;
+  int j;
+
+  long num = scalespace_scalenum(new,old);
+  long den = scalespace_scalenum(new,old);
+  long oldpos = scalespace_scaleoff(new,old);
+  long newpos = 0;
+
+  while(newi < new->pixels && oldi < old->pixels){
+
+    if(oldpos == newpos &&
+       oldi >= 0){
+      prefilled[newi] = 1;
+      for(j=0;j<objectives;j++){
+	if(oldx[j])
+	  newx[j][newi] = oldx[j][oldi];
+	if(oldy[j])
+	  newy[j][newi] = oldy[j][oldi];
+      }
+    }
+
+    while(newi < new->pixels && newi < oldi ){
+      newpos += den;
+      newi++;
+    }
+    while(oldi < old->pixels && oldi < newi ){
+      oldpos += num;
+      oldi++;
+    }
+  }
+}
+
 // subtype entry point for recomputation; lock held
-int _sushiv_panel1d_compute(sushiv_panel_t *p,
+int _sushiv_panelxy_compute(sushiv_panel_t *p,
 			    _sushiv_bythread_cache *c){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+  sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot;
   
   int dw,w,h,i,d;
   int serialno;
   int x_d=-1;
-  scalespace sy;
 
-  scalespace sx;
-  scalespace sxv;
-  scalespace sxi;
+  scalespace sxv = xy->data_v;
+  plot = PLOT(p->private->graph);
 
-  dw = p1->data_size;
-  w = p1->panel_w;
-  h = p1->panel_h;
+  dw = sxv.pixels;
+  w = plot->w.allocation.width;
+  h = plot->w.allocation.height;
 
-  sy = p1->y;
-
-  sx = p1->x;
-  sxv = p1->x_v;
-  sxi = p1->x_i;
-  
+  // this computation is single-threaded for now
   if(p->private->plot_progress_count)
     return 0;
 
   serialno = p->private->plot_serialno;
   p->private->plot_progress_count++;
   d = p->dimensions;
-  plot = PLOT(p->private->graph);
   
   /* render using local dimension array; several threads will be
      computing objectives */
   double dim_vals[p->sushi->dimensions];
 
   /* get iterator bounds, use iterator scale */
-  x_d = p1->x_d->number;
+  x_d = xy->x_d->number;
 
-  if(p1->flip){
-    plot->x = sy;
-    plot->y = sx;
-    plot->x_v = sy;
-    plot->y_v = sxv;
-  }else{
-    plot->x = sx;
-    plot->y = sy;
-    plot->x_v = sxv;
-    plot->y_v = sy;
+  /* generate a new data_v/data_i */
+  scalespace newv;
+  scalespace newi;
+  _generate_dimscale_xy(xy->x_d, xy->curr_zoom, &newv, &newi);
+  dw = newv.pixels;
+
+  /* compare new/old data scales; pre-fill the data vec with values
+     from old data vector if it can be reused */
+  double *new_x_vec[p->objectives];
+  double *new_y_vec[p->objectives];
+  char *prefilled = calloc(dw,sizeof(*prefilled));
+  for(i=0;i<p->objectives;i++){
+    new_x_vec[i] = calloc(dw,sizeof(**new_x_vec));
+    new_y_vec[i] = calloc(dw,sizeof(**new_y_vec));
   }
+  _rescale_xy(&sxv,xy->x_vec,xy->y_vec,   
+	      &newv,new_x_vec,new_y_vec,prefilled, p->objectives);
 
   // Initialize local dimension value array
   for(i=0;i<p->sushi->dimensions;i++){
@@ -1026,84 +1068,121 @@
     dim_vals[i]=dim->val;
   }
 
-  _maintain_cache_1d(p,&c->p1,dw);
+  _maintain_cache_xy(p,&c->xy,dw);
   
   /* unlock for computation */
   gdk_threads_leave ();
 
   plot_draw_scales(plot);
-  compute_1d(p, serialno, x_d, sxi, dw, dim_vals, &c->p1);
+  compute_xy(p, serialno, x_d, newi, dim_vals, prefilled, new_x_vec, new_y_vec, &c->xy);
   
   gdk_threads_enter ();
 
   if(serialno == p->private->plot_serialno){
+    // replace data vectors
+    p->private->plot_serialno++;
+    clear_xy_data(p);
+    if(!xy->x_vec)
+      xy->x_vec = calloc(p->objectives, sizeof(*xy->x_vec));
+    if(!xy->y_vec)
+      xy->y_vec = calloc(p->objectives, sizeof(*xy->y_vec));
+    for(i=0;i<p->objectives;i++){
+      xy->x_vec[i] = new_x_vec[i];
+      xy->y_vec[i] = new_y_vec[i];
+    }
+    free(prefilled);
+    // replace scales;
+    xy->data_v = newv;
+    xy->data_i = newi;
+
     _sushiv_panel_dirty_map(p);
     _sushiv_panel_dirty_legend(p);
     _sushiv_panel_clean_plot(p);
+  }else{
+    for(i=0;i<p->objectives;i++){
+      free(new_x_vec[i]);
+      free(new_y_vec[i]);
+    }
+    free(prefilled);
   }
+
   return 1;
 }
 
-static void panel1d_undo_log(sushiv_panel_undo_t *u, sushiv_panel_t *p){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+static void panelxy_undo_log(sushiv_panel_undo_t *u, sushiv_panel_t *p){
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  Plot *plot = PLOT(p->private->graph);
   int i;
 
   // alloc fields as necessary
   if(!u->mappings)
     u->mappings =  calloc(p->objectives,sizeof(*u->mappings));
   if(!u->scale_vals[0])
-    u->scale_vals[0] =  calloc(1,sizeof(**u->scale_vals));
+    u->scale_vals[0] =  calloc(3,sizeof(**u->scale_vals));
   if(!u->scale_vals[1])
-    u->scale_vals[1] =  calloc(1,sizeof(**u->scale_vals));
+    u->scale_vals[1] =  calloc(3,sizeof(**u->scale_vals));
   if(!u->scale_vals[2])
     u->scale_vals[2] =  calloc(p->objectives,sizeof(**u->scale_vals));
 
   // populate undo
-  u->scale_vals[0][0] = slider_get_value(p1->range_slider,0);
-  u->scale_vals[1][0] = slider_get_value(p1->range_slider,1);
+  u->scale_vals[0][0] = slider_get_value(xy->x_slider,0);
+  u->scale_vals[1][0] = slider_get_value(xy->x_slider,1);
+  u->scale_vals[0][1] = plot->selx;
+  u->scale_vals[1][1] = plot->sely;
+  u->scale_vals[0][2] = slider_get_value(xy->y_slider,0);
+  u->scale_vals[1][2] = slider_get_value(xy->y_slider,1);
 
   for(i=0;i<p->objectives;i++){
     u->mappings[i] = 
-      (p1->mappings[i].mapnum<<24) | 
-      (p1->linetype[i]<<16) |
-      (p1->pointtype[i]<<8);
-    u->scale_vals[2][i] = slider_get_value(p1->alpha_scale[i],0);
+      (xy->mappings[i].mapnum<<24) | 
+      (xy->linetype[i]<<16) |
+      (xy->pointtype[i]<<8);
+    u->scale_vals[2][i] = slider_get_value(xy->alpha_scale[i],0);
   }
 
-  u->x_d = p1->x_dnum;
-  u->box[0] = p1->oldbox[0];
-  u->box[1] = p1->oldbox[1];
+  u->x_d = xy->x_dnum;
+  u->box[0] = xy->oldbox[0];
+  u->box[1] = xy->oldbox[1];
+  u->box[2] = xy->oldbox[2];
+  u->box[3] = xy->oldbox[3];
 
   u->box_active = p->private->oldbox_active;
   
 }
 
-static void panel1d_undo_restore(sushiv_panel_undo_t *u, sushiv_panel_t *p){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+static void panelxy_undo_restore(sushiv_panel_undo_t *u, sushiv_panel_t *p){
+  sushiv_panelxy_t *xy = p->subtype->xy;
   Plot *plot = PLOT(p->private->graph);
 
   int i;
   
   // go in through widgets
    
-  slider_set_value(p1->range_slider,0,u->scale_vals[0][0]);
-  slider_set_value(p1->range_slider,1,u->scale_vals[1][0]);
+  slider_set_value(xy->x_slider,0,u->scale_vals[0][0]);
+  slider_set_value(xy->x_slider,1,u->scale_vals[1][0]);
+  plot->selx = u->scale_vals[0][1];
+  plot->sely = u->scale_vals[1][1];
+  slider_set_value(xy->y_slider,0,u->scale_vals[0][2]);
+  slider_set_value(xy->y_slider,1,u->scale_vals[1][2]);
 
   for(i=0;i<p->objectives;i++){
-    gtk_combo_box_set_active(GTK_COMBO_BOX(p1->map_pulldowns[i]), (u->mappings[i]>>24)&0xff );
-    gtk_combo_box_set_active(GTK_COMBO_BOX(p1->line_pulldowns[i]), (u->mappings[i]>>16)&0xff );
-    gtk_combo_box_set_active(GTK_COMBO_BOX(p1->point_pulldowns[i]), (u->mappings[i]>>8)&0xff );
-    slider_set_value(p1->alpha_scale[i],0,u->scale_vals[2][i]);
+    gtk_combo_box_set_active(GTK_COMBO_BOX(xy->map_pulldowns[i]), (u->mappings[i]>>24)&0xff );
+    gtk_combo_box_set_active(GTK_COMBO_BOX(xy->line_pulldowns[i]), (u->mappings[i]>>16)&0xff );
+    gtk_combo_box_set_active(GTK_COMBO_BOX(xy->point_pulldowns[i]), (u->mappings[i]>>8)&0xff );
+    slider_set_value(xy->alpha_scale[i],0,u->scale_vals[2][i]);
   }
 
-  if(p1->dim_xb && u->x_d<p->dimensions && p1->dim_xb[u->x_d])
-    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p1->dim_xb[u->x_d]),TRUE);
+  if(xy->dim_xb && u->x_d<p->dimensions && xy->dim_xb[u->x_d])
+    gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xy->dim_xb[u->x_d]),TRUE);
 
-  update_x_sel(p);
+  update_dim_sel(p);
+  crosshair_callback(p);
 
   if(u->box_active){
-    p1->oldbox[0] = u->box[0];
-    p1->oldbox[1] = u->box[1];
+    xy->oldbox[0] = u->box[0];
+    xy->oldbox[1] = u->box[1];
+    xy->oldbox[2] = u->box[2];
+    xy->oldbox[3] = u->box[3];
     plot_box_set(plot,u->box);
     p->private->oldbox_active = 1;
   }else{
@@ -1112,8 +1191,8 @@
   }
 }
 
-void _sushiv_realize_panel1d(sushiv_panel_t *p){
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+void _sushiv_realize_panelxy(sushiv_panel_t *p){
+  sushiv_panelxy_t *xy = p->subtype->xy;
   char buffer[160];
   int i;
   _sushiv_undo_suspend(p->sushi);
@@ -1140,75 +1219,81 @@
 
   /* plotbox, graph */
   {
-    unsigned flags = 0;
-    if(p1->flip)
-      flags |= PLOT_NO_X_CROSS;
-    else
-      flags |= PLOT_NO_Y_CROSS;
-
-    p1->graph_table = gtk_table_new(2,2,0);
-    p->private->plotbox = p1->graph_table;
+    xy->graph_table = gtk_table_new(3,3,0);
+    p->private->plotbox = xy->graph_table;
     gtk_box_pack_start(GTK_BOX(p->private->topbox), p->private->plotbox, 1,1,2);
 
-    p->private->graph = GTK_WIDGET(plot_new(recompute_callback_1d,p,
+    p->private->graph = GTK_WIDGET(plot_new(recompute_callback_xy,p,
 					    (void *)(void *)crosshair_callback,p,
-					    box_callback,p,flags)); 
-    if(p1->flip){
-      gtk_table_attach(GTK_TABLE(p1->graph_table),p->private->graph,0,2,0,1,
-		       GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,1);
-    }else{
-      gtk_table_attach(GTK_TABLE(p1->graph_table),p->private->graph,1,2,0,2,
-		       GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,1);
-    }
+					    box_callback,p,0));
+    
+    gtk_table_attach(GTK_TABLE(xy->graph_table),p->private->graph,1,3,0,2,
+		     GTK_EXPAND|GTK_FILL,GTK_EXPAND|GTK_FILL,0,1);
   }
 
-  /* range slider, goes in the plotbox table */
-  /* may be vertical to the left of the plot or along the bottom if the plot is flipped */
+  /* X range slider */
   {
     GtkWidget **sl = calloc(2,sizeof(*sl));
-    int lo = p1->range_scale->val_list[0];
-    int hi = p1->range_scale->val_list[p1->range_scale->vals-1];
+    int lo = xy->x_scale->val_list[0];
+    int hi = xy->x_scale->val_list[xy->x_scale->vals-1];
 
     /* the range slices/slider */ 
-    sl[0] = slice_new(map_callback_1d,p);
-    sl[1] = slice_new(map_callback_1d,p);
+    sl[0] = slice_new(map_callback_xy,p);
+    sl[1] = slice_new(map_callback_xy,p);
 
-    if(p1->flip){
-      gtk_table_attach(GTK_TABLE(p1->graph_table),sl[0],0,1,1,2,
-		       GTK_EXPAND|GTK_FILL,0,0,0);
-      gtk_table_attach(GTK_TABLE(p1->graph_table),sl[1],1,2,1,2,
-		       GTK_EXPAND|GTK_FILL,0,0,0);
-    }else{
-      gtk_table_attach(GTK_TABLE(p1->graph_table),sl[0],0,1,1,2,
-		       GTK_SHRINK,GTK_EXPAND|GTK_FILL,0,0);
-      gtk_table_attach(GTK_TABLE(p1->graph_table),sl[1],0,1,0,1,
-		       GTK_SHRINK,GTK_EXPAND|GTK_FILL,0,0);
-      gtk_table_set_col_spacing(GTK_TABLE(p1->graph_table),0,4);
-    }
+    gtk_table_attach(GTK_TABLE(xy->graph_table),sl[0],1,2,2,3,
+		     GTK_EXPAND|GTK_FILL,0,0,0);
+    gtk_table_attach(GTK_TABLE(xy->graph_table),sl[1],2,3,2,3,
+		     GTK_EXPAND|GTK_FILL,0,0,0);
 
-    p1->range_slider = slider_new((Slice **)sl,2,
-				  p1->range_scale->label_list,
-				  p1->range_scale->val_list,
-				  p1->range_scale->vals,
-				  (p1->flip?0:SLIDER_FLAG_VERTICAL));
+    xy->x_slider = slider_new((Slice **)sl,2,
+			      xy->x_scale->label_list,
+			      xy->x_scale->val_list,
+			      xy->x_scale->vals,0);
+    
+    slice_thumb_set((Slice *)sl[0],lo);
+    slice_thumb_set((Slice *)sl[1],hi);
+  }
 
+  /* Y range slider */
+  {
+    GtkWidget **sl = calloc(2,sizeof(*sl));
+    int lo = xy->y_scale->val_list[0];
+    int hi = xy->y_scale->val_list[xy->y_scale->vals-1];
+
+    /* the range slices/slider */ 
+    sl[0] = slice_new(map_callback_xy,p);
+    sl[1] = slice_new(map_callback_xy,p);
+
+    gtk_table_attach(GTK_TABLE(xy->graph_table),sl[0],0,1,1,2,
+		     GTK_SHRINK,GTK_EXPAND|GTK_FILL,0,0);
+    gtk_table_attach(GTK_TABLE(xy->graph_table),sl[1],0,1,0,1,
+		     GTK_SHRINK,GTK_EXPAND|GTK_FILL,0,0);
+    gtk_table_set_col_spacing(GTK_TABLE(xy->graph_table),0,4);
+    
+    xy->y_slider = slider_new((Slice **)sl,2,
+			      xy->y_scale->label_list,
+			      xy->y_scale->val_list,
+			      xy->y_scale->vals,
+			      SLIDER_FLAG_VERTICAL);
+
     slice_thumb_set((Slice *)sl[0],lo);
     slice_thumb_set((Slice *)sl[1],hi);
   }
 
   /* obj box */
   {
-    p1->obj_table = gtk_table_new(p->objectives,5,0);
-    gtk_box_pack_start(GTK_BOX(p->private->topbox), p1->obj_table, 0,0,1);
+    xy->obj_table = gtk_table_new(p->objectives,5,0);
+    gtk_box_pack_start(GTK_BOX(p->private->topbox), xy->obj_table, 0,0,1);
 
     /* pulldowns */
-    p1->pointtype = calloc(p->objectives,sizeof(*p1->pointtype));
-    p1->linetype = calloc(p->objectives,sizeof(*p1->linetype));
-    p1->mappings = calloc(p->objectives,sizeof(*p1->mappings));
-    p1->map_pulldowns = calloc(p->objectives,sizeof(*p1->map_pulldowns));
-    p1->line_pulldowns = calloc(p->objectives,sizeof(*p1->line_pulldowns));
-    p1->point_pulldowns = calloc(p->objectives,sizeof(*p1->point_pulldowns));
-    p1->alpha_scale = calloc(p->objectives,sizeof(*p1->alpha_scale));
+    xy->pointtype = calloc(p->objectives,sizeof(*xy->pointtype));
+    xy->linetype = calloc(p->objectives,sizeof(*xy->linetype));
+    xy->mappings = calloc(p->objectives,sizeof(*xy->mappings));
+    xy->map_pulldowns = calloc(p->objectives,sizeof(*xy->map_pulldowns));
+    xy->line_pulldowns = calloc(p->objectives,sizeof(*xy->line_pulldowns));
+    xy->point_pulldowns = calloc(p->objectives,sizeof(*xy->point_pulldowns));
+    xy->alpha_scale = calloc(p->objectives,sizeof(*xy->alpha_scale));
 
     for(i=0;i<p->objectives;i++){
       sushiv_objective_t *o = p->objective_list[i].o;
@@ -1216,7 +1301,7 @@
       /* label */
       GtkWidget *label = gtk_label_new(o->name);
       gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
-      gtk_table_attach(GTK_TABLE(p1->obj_table),label,0,1,i,i+1,
+      gtk_table_attach(GTK_TABLE(xy->obj_table),label,0,1,i,i+1,
 		       GTK_FILL,0,5,0);
       
       /* mapping pulldown */
@@ -1233,11 +1318,11 @@
 	}
 	gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
 	g_signal_connect (G_OBJECT (menu), "changed",
-			  G_CALLBACK (mapchange_callback_1d), p->objective_list+i);
-	gtk_table_attach(GTK_TABLE(p1->obj_table),menu,1,2,i,i+1,
+			  G_CALLBACK (mapchange_callback_xy), p->objective_list+i);
+	gtk_table_attach(GTK_TABLE(xy->obj_table),menu,1,2,i,i+1,
 			 GTK_SHRINK,GTK_SHRINK,5,0);
-	p1->map_pulldowns[i] = menu;
-	solid_setup(&p1->mappings[i],0.,1.,0);
+	xy->map_pulldowns[i] = menu;
+	solid_setup(&xy->mappings[i],0.,1.,0);
       }
       
       /* line pulldown */
@@ -1248,10 +1333,10 @@
 	  gtk_combo_box_append_text (GTK_COMBO_BOX (menu), line_name[j]->left);
 	gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
 	g_signal_connect (G_OBJECT (menu), "changed",
-			  G_CALLBACK (linetype_callback_1d), p->objective_list+i);
-	gtk_table_attach(GTK_TABLE(p1->obj_table),menu,2,3,i,i+1,
+			  G_CALLBACK (linetype_callback_xy), p->objective_list+i);
+	gtk_table_attach(GTK_TABLE(xy->obj_table),menu,2,3,i,i+1,
 			 GTK_SHRINK,GTK_SHRINK,5,0);
-	p1->line_pulldowns[i] = menu;
+	xy->line_pulldowns[i] = menu;
       }
       
       /* point pulldown */
@@ -1262,26 +1347,26 @@
 	  gtk_combo_box_append_text (GTK_COMBO_BOX (menu), point_name[j]->left);
 	gtk_combo_box_set_active(GTK_COMBO_BOX(menu),0);
 	g_signal_connect (G_OBJECT (menu), "changed",
-			  G_CALLBACK (pointtype_callback_1d), p->objective_list+i);
-	gtk_table_attach(GTK_TABLE(p1->obj_table),menu,3,4,i,i+1,
+			  G_CALLBACK (pointtype_callback_xy), p->objective_list+i);
+	gtk_table_attach(GTK_TABLE(xy->obj_table),menu,3,4,i,i+1,
 			 GTK_SHRINK,GTK_SHRINK,5,0);
-	p1->point_pulldowns[i] = menu;
+	xy->point_pulldowns[i] = menu;
       }
       
       /* alpha slider */
       {
 	GtkWidget **sl = calloc(1, sizeof(*sl));
-	sl[0] = slice_new(alpha_callback_1d,p->objective_list+i);
+	sl[0] = slice_new(alpha_callback_xy,p->objective_list+i);
 	
-	gtk_table_attach(GTK_TABLE(p1->obj_table),sl[0],4,5,i,i+1,
+	gtk_table_attach(GTK_TABLE(xy->obj_table),sl[0],4,5,i,i+1,
 			 GTK_EXPAND|GTK_FILL,0,0,0);
 	
-	p1->alpha_scale[i] = slider_new((Slice **)sl,1,
+	xy->alpha_scale[i] = slider_new((Slice **)sl,1,
 					(char *[]){"transparent","solid"},
 					(double []){0.,1.},
 					2,0);
 	
-	slider_set_gradient(p1->alpha_scale[i], &p1->mappings[i]);
+	slider_set_gradient(xy->alpha_scale[i], &xy->mappings[i]);
 	slice_thumb_set((Slice *)sl[0],1.);
 	
       }
@@ -1290,11 +1375,11 @@
 
   /* dim box */
   if(p->dimensions){
-    p1->dim_table = gtk_table_new(p->dimensions,3,0);
-    gtk_box_pack_start(GTK_BOX(p->private->topbox), p1->dim_table, 0,0,4);
+    xy->dim_table = gtk_table_new(p->dimensions,3,0);
+    gtk_box_pack_start(GTK_BOX(p->private->topbox), xy->dim_table, 0,0,4);
 
     p->private->dim_scales = calloc(p->dimensions,sizeof(*p->private->dim_scales));
-    p1->dim_xb = calloc(p->dimensions,sizeof(*p1->dim_xb));
+    xy->dim_xb = calloc(p->dimensions,sizeof(*xy->dim_xb));
     GtkWidget *first_x = NULL;
     
     for(i=0;i<p->dimensions;i++){
@@ -1303,25 +1388,25 @@
       /* label */
       GtkWidget *label = gtk_label_new(d->name);
       gtk_misc_set_alignment(GTK_MISC(label),1.,.5);
-      gtk_table_attach(GTK_TABLE(p1->dim_table),label,0,1,i,i+1,
+      gtk_table_attach(GTK_TABLE(xy->dim_table),label,0,1,i,i+1,
 		       GTK_FILL,0,5,0);
       
       /* x radio buttons */
-      if(!(d->flags & SUSHIV_DIM_NO_X) && !p1->link_x && !p1->link_y){
+      if(!(d->flags & SUSHIV_DIM_NO_X)){
 	if(first_x)
-	  p1->dim_xb[i] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(first_x),"X");
+	  xy->dim_xb[i] = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(first_x),"X");
 	else{
-	  first_x = p1->dim_xb[i] = gtk_radio_button_new_with_label(NULL,"X");
-	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(p1->dim_xb[i]),TRUE);
+	  first_x = xy->dim_xb[i] = gtk_radio_button_new_with_label(NULL,"X");
+	  gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(xy->dim_xb[i]),TRUE);
 	}
-	gtk_table_attach(GTK_TABLE(p1->dim_table),p1->dim_xb[i],1,2,i,i+1,
+	gtk_table_attach(GTK_TABLE(xy->dim_table),xy->dim_xb[i],1,2,i,i+1,
 			 0,0,3,0);
       }
       
       p->private->dim_scales[i] = 
-	_sushiv_new_dimension_widget(p->dimension_list+i,center_callback_1d,bracket_callback_1d);
+	_sushiv_new_dimension_widget(p->dimension_list+i,center_callback_xy,bracket_callback_xy);
       
-      gtk_table_attach(GTK_TABLE(p1->dim_table),
+      gtk_table_attach(GTK_TABLE(xy->dim_table),
 		       GTK_WIDGET(p->private->dim_scales[i]->t),
 		       2,3,i,i+1,
 		       GTK_EXPAND|GTK_FILL,0,0,0);
@@ -1329,11 +1414,11 @@
     }
     
     for(i=0;i<p->dimensions;i++)
-      if(p1->dim_xb[i])
-	g_signal_connect (G_OBJECT (p1->dim_xb[i]), "toggled",
-			  G_CALLBACK (dimchange_callback_1d), p);
+      if(xy->dim_xb[i])
+	g_signal_connect (G_OBJECT (xy->dim_xb[i]), "toggled",
+			  G_CALLBACK (dimchange_callback_xy), p);
     
-    update_x_sel(p);
+    update_dim_sel(p);
   }
   
   gtk_widget_realize(p->private->toplevel);
@@ -1345,19 +1430,22 @@
 }
 
 
-static int _save_panel1d(sushiv_panel_t *p, xmlNodePtr pn){  
-  sushiv_panel1d_t *p1 = p->subtype->p1;
+static int _save_panelxy(sushiv_panel_t *p, xmlNodePtr pn){  
+  sushiv_panelxy_t *xy = p->subtype->xy;
+  Plot *plot = PLOT(p->private->graph);
   int ret=0,i;
 
   xmlNodePtr n;
 
-  xmlNewProp(pn, (xmlChar *)"type", (xmlChar *)"1d");
+  xmlNewProp(pn, (xmlChar *)"type", (xmlChar *)"xy");
 
   // box
   if(p->private->oldbox_active){
     xmlNodePtr boxn = xmlNewChild(pn, NULL, (xmlChar *) "box", NULL);
-    xmlNewPropF(boxn, "x1", p1->oldbox[0]);
-    xmlNewPropF(boxn, "x2", p1->oldbox[1]);
+    xmlNewPropF(boxn, "x1", xy->oldbox[0]);
+    xmlNewPropF(boxn, "x2", xy->oldbox[1]);
+    xmlNewPropF(boxn, "y1", xy->oldbox[2]);
+    xmlNewPropF(boxn, "y2", xy->oldbox[3]);
   }
   
   // objective map settings
@@ -1373,37 +1461,43 @@
     // right now Y is the only type; the below is Y-specific
 
     n = xmlNewChild(on, NULL, (xmlChar *) "y-map", NULL);
-    xmlNewMapProp(n, "color", solid_map(), p1->mappings[i].mapnum);
-    xmlNewMapProp(n, "line", line_name, p1->linetype[i]);    
-    xmlNewMapProp(n, "point", point_name, p1->pointtype[i]);    
-    xmlNewPropF(n, "alpha", slider_get_value(p1->alpha_scale[i],0));
+    xmlNewMapProp(n, "color", solid_map(), xy->mappings[i].mapnum);
+    xmlNewMapProp(n, "line", line_name, xy->linetype[i]);    
+    xmlNewMapProp(n, "point", point_name, xy->pointtype[i]);    
+    xmlNewPropF(n, "alpha", slider_get_value(xy->alpha_scale[i],0));
   }
 
-  // y scale
+  // x/y scale
   n = xmlNewChild(pn, NULL, (xmlChar *) "range", NULL);
-  xmlNewPropF(n, "low-bracket", slider_get_value(p1->range_slider,0));
-  xmlNewPropF(n, "high-bracket", slider_get_value(p1->range_slider,1));
+  xmlNewPropF(n, "x-low-bracket", slider_get_value(xy->x_slider,0));
+  xmlNewPropF(n, "x-high-bracket", slider_get_value(xy->x_slider,1));
+  xmlNewPropF(n, "y-low-bracket", slider_get_value(xy->y_slider,0));
+  xmlNewPropF(n, "y-high-bracket", slider_get_value(xy->y_slider,1));
+  xmlNewPropF(n, "x-cross", plot->selx);
+  xmlNewPropF(n, "y-cross", plot->sely);
 
   // x/y dim selection
   n = xmlNewChild(pn, NULL, (xmlChar *) "axes", NULL);
-  xmlNewPropI(n, "xpos", p1->x_dnum);
+  xmlNewPropI(n, "xpos", xy->x_dnum);
 
   return ret;
 }
 
-int _load_panel1d(sushiv_panel_t *p,
+int _load_panelxy(sushiv_panel_t *p,
 		  sushiv_panel_undo_t *u,
 		  xmlNodePtr pn,
 		  int warn){
   int i;
 
   // check type
-  xmlCheckPropS(pn,"type","1d", "Panel %d type mismatch in save file.",p->number,&warn);
+  xmlCheckPropS(pn,"type","xy", "Panel %d type mismatch in save file.",p->number,&warn);
   
   // box
   u->box_active = 0;
   xmlGetChildPropFPreserve(pn, "box", "x1", &u->box[0]);
   xmlGetChildPropFPreserve(pn, "box", "x2", &u->box[1]);
+  xmlGetChildPropFPreserve(pn, "box", "y1", &u->box[2]);
+  xmlGetChildPropFPreserve(pn, "box", "y2", &u->box[3]);
 
   xmlNodePtr n = xmlGetChildS(pn, "box", NULL, NULL);
   if(n){
@@ -1443,9 +1537,12 @@
     }
   }
 
-  // y scale
-  xmlGetChildPropFPreserve(pn, "range", "low-bracket", &u->scale_vals[0][0]);
-  xmlGetChildPropF(pn, "range", "high-bracket", &u->scale_vals[1][0]);
+  xmlGetChildPropFPreserve(pn, "range", "x-low-bracket", &u->scale_vals[0][0]);
+  xmlGetChildPropFPreserve(pn, "range", "x-high-bracket", &u->scale_vals[1][0]);
+  xmlGetChildPropFPreserve(pn, "range", "y-low-bracket", &u->scale_vals[0][2]);
+  xmlGetChildPropFPreserve(pn, "range", "y-high-bracket", &u->scale_vals[1][2]);
+  xmlGetChildPropFPreserve(pn, "range", "x-cross", &u->scale_vals[0][1]);
+  xmlGetChildPropF(pn, "range", "y-cross", &u->scale_vals[1][1]);
 
   // x/y dim selection
   xmlGetChildPropI(pn, "axes", "xpos", &u->x_d);
@@ -1453,79 +1550,45 @@
   return warn;
 }
 
-int sushiv_new_panel_1d(sushiv_instance_t *s,
+int sushiv_new_panel_xy(sushiv_instance_t *s,
 			int number,
 			const char *name,
-			sushiv_scale_t *scale,
+			sushiv_scale_t *xscale,
+			sushiv_scale_t *yscale,
 			int *objectives,
 			int *dimensions,	
 			unsigned flags){
 
   int ret = _sushiv_new_panel(s,number,name,objectives,dimensions,flags);
   sushiv_panel_t *p;
-  sushiv_panel1d_t *p1;
+  sushiv_panelxy_t *xy;
 
   if(ret<0)return ret;
   p = s->panel_list[number];
-  p1 = calloc(1, sizeof(*p1));
+  xy = calloc(1, sizeof(*xy));
   p->subtype = calloc(1, sizeof(*p->subtype));
 
-  p->subtype->p1 = p1;
-  p->type = SUSHIV_PANEL_1D;
-  p1->range_scale = scale;
+  p->subtype->xy = xy;
+  p->type = SUSHIV_PANEL_XY;
+  xy->x_scale = xscale;
+  xy->y_scale = yscale;
   p->private->bg_type = SUSHIV_BG_WHITE;
 
-  if(p->flags && SUSHIV_PANEL_FLIP)
-    p1->flip=1;
-
-  p->private->realize = _sushiv_realize_panel1d;
-  p->private->map_action = _sushiv_panel1d_map_redraw;
-  p->private->legend_action = _sushiv_panel1d_legend_redraw;
-  p->private->compute_action = _sushiv_panel1d_compute;
-  p->private->request_compute = _mark_recompute_1d;
+  p->private->realize = _sushiv_realize_panelxy;
+  p->private->map_action = _sushiv_panelxy_map_redraw;
+  p->private->legend_action = _sushiv_panelxy_legend_redraw;
+  p->private->compute_action = _sushiv_panelxy_compute;
+  p->private->request_compute = _mark_recompute_xy;
   p->private->crosshair_action = crosshair_callback;
-  p->private->print_action = sushiv_panel1d_print;
-  p->private->save_action = _save_panel1d;
-  p->private->load_action = _load_panel1d;
+  p->private->print_action = sushiv_panelxy_print;
+  p->private->save_action = _save_panelxy;
+  p->private->load_action = _load_panelxy;
 
-  p->private->undo_log = panel1d_undo_log;
-  p->private->undo_restore = panel1d_undo_restore;
+  p->private->undo_log = panelxy_undo_log;
+  p->private->undo_restore = panelxy_undo_restore;
   p->private->def_oversample_n = p->private->oversample_n = 1;
   p->private->def_oversample_d = p->private->oversample_d = 8;
   
   return 0;
 }
 
-int sushiv_new_panel_1d_linked(sushiv_instance_t *s,
-			       int number,
-			       const char *name,
-			       sushiv_scale_t *scale,
-			       int *objectives,
-			       int link,
-			       unsigned flags){
-  
-  if(link < 0 || 
-     link >= s->panels || 
-     s->panel_list[link]==NULL ||
-     s->panel_list[link]->type != SUSHIV_PANEL_2D){
-    fprintf(stderr,"1d linked panel must be linked to preexisting 2d panel.\n");
-    return -EINVAL;
-  }
-
-  int ret = sushiv_new_panel_1d(s,number,name,scale,objectives,(int []){-1},flags);
-
-  sushiv_panel_t *p;
-  sushiv_panel1d_t *p1;
-  sushiv_panel_t *p2 = s->panel_list[link];
-
-  if(ret<0)return ret;
-  p = s->panel_list[number];
-  p1 = p->subtype->p1;
-
-  if(flags && SUSHIV_PANEL_LINK_Y)
-    p1->link_y = p2;
-  else
-    p1->link_x = p2;
-
-  return 0;
-}

Modified: trunk/sushivision/panel-xy.h
===================================================================
--- trunk/sushivision/panel-xy.h	2007-03-18 14:46:07 UTC (rev 12776)
+++ trunk/sushivision/panel-xy.h	2007-03-19 08:33:06 UTC (rev 12777)
@@ -31,20 +31,20 @@
   scalespace x;
   scalespace y;
   double oldbox[4];
-  sushiv_scale_t x_scale;
-  sushiv_scale_t y_scale;
-  Slider x_slider;
-  Slider y_slider;
+  sushiv_scale_t *x_scale;
+  sushiv_scale_t *y_scale;
+  Slider *x_slider;
+  Slider *y_slider;
   double x_bracket[2];
   double y_bracket[2];
-  double x_val;
-  double y_val;
+  int cross_objnum;
   
   scalespace data_v; // the x scale aligned to data vector's bins
   scalespace data_i; // the 'counting' scale used to iterate for compute
   double **x_vec;
   double **y_vec;
-  double scale_metric;
+  int curr_zoom;
+  int prev_zoom;
 
   mapping *mappings;
   int *linetype;



More information about the commits mailing list