file: parcoord.c

/* parcoord.c - function to plotting data using parallel coordinates for XmdvTool */ /* Copyright 1994, Matthew O. Ward * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without fee * is granted provided that the above copyright notice appears in all copies. * It is provided "as is" without express or implied warranty. */ /* display data using parallel coordinates. Each dimensional axis is layed out in a vertical line, evenly spaced between dimensions. The top and bottom of each line coincide with the maximum and minimum for that dimension. Each data point creates a polyline across these axes. Labels are printed along the top of each dimension, and brush coverage display consists of a single shaded region across the drawing area. */ #include "XmdvTool.h" #include "parcoord.h" #include "brush_oper.h" #include "util.h" #include "multi_select.h" extern Widget appShell; extern GC gc, xor_gc; extern unsigned long color_cells[NUM_COLOR_CELLS]; extern XColor outline_col; extern int dims, data_size; extern double dim_min[MAXDIM], dim_max[MAXDIM]; extern char names[MAXDIM][MAXLABEL]; extern double *br_pos, *br_size; /* the brushes */ extern Brush brushes[MAXBRUSH]; /* is this a color display? */ extern int COLOR; extern int X_SIZE, Y_SIZE; char message[MAXLABEL]; Arg wargs[10]; void do_par(Widget w) { int i, j, dimwidth, halfwidth; double data[MAXDIM]; XPoint xpts[MAXDIM*2+1]; XFontStruct *font; /* the font to draw text with */ int font_height; /* the height of the font */ int dummy; /* dummy var passed to XTextExtents() */ XCharStruct overall; /* for finding extents */ int x,y; /* x/y location for labels */ int brush; /* the current brush number */ unsigned long pixel; /* the brush color pixel value */ /* compute layout of axes */ dimwidth = X_SIZE/dims; halfwidth = dimwidth/2; /* if brush coverage is to be displayed, compute polyline by going first */ /* through the top edges of the brush and then through the bottom edges */ if(COLOR == 1) for(brush=0; brush<MAXBRUSH; brush++) { /* if this brush is not being displayed, skip it */ if(brushes[brush].display == FALSE) continue; /* set the appropriate brush color */ XSetForeground(XtDisplay(w),gc, color_cells[BRUSH_COLOR(brush)]); for(i=0, j=0; j<dims; j++) { /* x positions are fixed y positions normalized over axis height */ xpts[i].x = j*dimwidth + halfwidth; xpts[i].y = (brushes[brush].pos[j] + brushes[brush].size[j]/2. - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[i].y = Y_SIZE - xpts[i].y; i++; } /* same thing for bottom extent of brush */ for(j = dims-1;j >= 0;j--) { xpts[i].x = j*dimwidth + halfwidth; xpts[i].y = (brushes[brush].pos[j] - brushes[brush].size[j]/2. - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[i].y = Y_SIZE - xpts[i].y; i++; } xpts[i].x = xpts[0].x; xpts[i].y = xpts[0].y; /* output brush coverage */ XFillPolygon(XtDisplay(w), XtWindow(w), gc, xpts, dims*2+1, Complex, CoordModeOrigin); /* draw boundary coverage if necessary */ if(brushes[brush].bound != BOUND_STEP) ParCoordDrawBound(brush); } if(COLOR == 1) { /* first draw all points in the data color */ for(i=0; i<data_size; i++) { get_data(data, i); pixel = ColorFromOperations(data); /* if this point is masked, skip it */ if(pixel == COLOR_NONE) continue; /* first time through only paint regular data */ if(pixel != color_cells[CCELL_DATA]) continue; XSetForeground(XtDisplay(w),gc, pixel); for(j=0; j<dims; j++) { xpts[j].x = j*dimwidth + halfwidth; xpts[j].y = (data[j] - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[j].y = Y_SIZE - xpts[j].y; } XDrawLines(XtDisplay(w), XtWindow(w), gc, xpts, dims, CoordModeOrigin); } /* now paint all points covered by an operation */ for(i=0; i<data_size; i++) { get_data(data, i); pixel = ColorFromOperations(data); /* if this point is masked, skip it */ if(pixel == COLOR_NONE) continue; /* second time through don't paint regular data */ if(pixel == color_cells[CCELL_DATA]) continue; XSetForeground(XtDisplay(w),gc, pixel); for(j=0; j<dims; j++) { xpts[j].x = j*dimwidth + halfwidth; xpts[j].y = (data[j] - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[j].y = Y_SIZE - xpts[j].y; } XDrawLines(XtDisplay(w), XtWindow(w), gc, xpts, dims, CoordModeOrigin); } } else { XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]); for(i=0; i<data_size; i++) { get_data(data, i); for(j=0; j<dims; j++) { xpts[j].x = j*dimwidth + halfwidth; xpts[j].y = (data[j] - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[j].y = Y_SIZE - xpts[j].y; } XDrawLines(XtDisplay(w), XtWindow(w), gc, xpts, dims, CoordModeOrigin); } } /* finally, draw axes and labels */ XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]); for(i=0; i<dims; i++) XDrawLine(XtDisplay(w), XtWindow(w), gc, i*dimwidth+halfwidth, 0, i*dimwidth+halfwidth, Y_SIZE); /* do labels */ /* get the font */ font = XQueryFont(XtDisplay(w), XGContextFromGC(gc)); /* Get initial extents */ XTextExtents(font, "X", 1, &dummy, &dummy, &dummy, &overall); font_height = overall.ascent + overall.descent; /* add letters one at a time until space runs out */ for(i=0; i<dims; i++) { /* initial coordinates */ x = i*dimwidth + halfwidth + overall.width/2; y = font_height * 1.1; for(j=0; j<strlen(names[i]); j++) { XTextExtents(font, &names[i][j], 1, &dummy, &dummy, &dummy, &overall); if(x+overall.width > (i+1)*dimwidth+halfwidth-overall.width) break; XDrawString(XtDisplay(w), XtWindow(w), gc, x, y, &names[i][j], 1); x += overall.width; } } } /* * RedrawSingleParCoord() - Redraw a single polyline in the the parallel * coordinate display. */ void RedrawSingleParCoord(Widget w, int point) { int j, dimwidth, halfwidth; double data[MAXDIM]; XPoint xpts[MAXDIM*2+1]; /* compute layout of axes */ dimwidth = X_SIZE/dims; halfwidth = dimwidth/2; /* set the color */ if(COLOR == 1) { if(MultiSelectCovered(point)) XSetForeground(XtDisplay(w),gc, color_cells[CCELL_PAINT]); /*********** this needs to be fixed at some point ***********/ else if(covered(data) == 1) XSetForeground(XtDisplay(w),gc, color_cells[CCELL_HIGHLIGHT]); else XSetForeground(XtDisplay(w),gc, color_cells[CCELL_DATA]); } else XSetForeground(XtDisplay(w),gc, color_cells[CCELL_TEXT]); /* draw polyline */ get_data(data, point); for(j = 0;j < dims;j++) { xpts[j].x = j*dimwidth + halfwidth; xpts[j].y = (data[j] - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[j].y = Y_SIZE - xpts[j].y; } XDrawLines(XtDisplay(w), XtWindow(w), gc, xpts, dims, CoordModeOrigin); } /* * ParCoordDrawAverage() - Draw an average value on the parallel * coordinate display. * * PARAMETERS * data The average point to draw * * RETURNS * void */ void ParCoordDrawAverage(double data[MAXDIM]) { Widget canvas_w; int j, dimwidth, halfwidth; XPoint xpts[MAXDIM*2+1]; /* get the canvas widget */ if(!(canvas_w = WcFullNameToWidget(appShell,"*canvas"))) { fprintf(stderr, "Error getting *canvas in ParCoordDrawAverage()\n"); return; } /* compute layout of axes */ dimwidth = X_SIZE/dims; halfwidth = dimwidth/2; /* draw polyline */ for(j = 0;j < dims;j++) { xpts[j].x = j*dimwidth + halfwidth; xpts[j].y = (data[j] - dim_min[j]) * ((double) Y_SIZE) / (dim_max[j] - dim_min[j]); xpts[j].y = Y_SIZE - xpts[j].y; } XDrawLines(XtDisplay(canvas_w), XtWindow(canvas_w), gc, xpts, dims, CoordModeOrigin); } /* * ParCoordDrawBound() - Draw the brush boundary in the parallel * coordinate view. * * PARAMETERS * br_num Brush number to draw boundary for * * RETURNS * void */ void ParCoordDrawBound(int br_num) { int i; Widget canvas_w; /* the canvas */ XPoint xpts[MAXDIM]; /* XPoint array for drawline polyline */ int dimwidth, halfwidth; /* get the canvas widget */ if(!(canvas_w = WcFullNameToWidget(appShell,"*canvas"))) { fprintf(stderr, "Error getting *canvas in ParCoordDrawBound()\n"); return; } /* compute layout of axes */ dimwidth = X_SIZE/dims; halfwidth = dimwidth/2; /* set the appropriate color */ XSetForeground(XtDisplay(canvas_w), xor_gc, color_cells[BRUSH_COLOR(br_num)]); for(i=0; i<dims; i++) { xpts[i].x = i*dimwidth + halfwidth; xpts[i].y = (brushes[br_num].pos[i] + brushes[br_num].size[i]/2.0 + brushes[br_num].bound_offset[i] - dim_min[i]) * ((double) Y_SIZE) / (dim_max[i] - dim_min[i]); xpts[i].y = Y_SIZE - xpts[i].y; } XDrawLines(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc, xpts, dims, CoordModeOrigin); for(i=0; i<dims; i++) { xpts[i].x = i*dimwidth + halfwidth; xpts[i].y = (brushes[br_num].pos[i] - brushes[br_num].size[i]/2.0 - brushes[br_num].bound_offset[i] - dim_min[i]) * ((double) Y_SIZE) / (dim_max[i] - dim_min[i]); xpts[i].y = Y_SIZE - xpts[i].y; } XDrawLines(XtDisplay(canvas_w), XtWindow(canvas_w), xor_gc, xpts, dims, CoordModeOrigin); }


Back to Source File Index


C++ to HTML Conversion by ctoohtml