SciPlot-1.36/ 40755 765 144 0 6213435732 11117 5ustar robusersSciPlot-1.36/SciPlot.c100644 765 144 303627 6213435732 13010 0ustar robusers/*---------------------------------------------------------------------------- * SciPlot A generalized plotting widget * * Copyright (c) 1996 Robert W. McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #include #include #include #include "SciPlotP.h" #define offset(field) XtOffsetOf(SciPlotRec, plot.field) static XtResource resources[] = { {XtNchartType, XtCMargin, XtRInt, sizeof(int), offset(ChartType), XtRImmediate, (XtPointer) XtCARTESIAN}, {XtNdegrees, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(Degrees), XtRImmediate, (XtPointer) True}, {XtNdrawMajor, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(DrawMajor), XtRImmediate, (XtPointer) True}, {XtNdrawMajorTics, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(DrawMajorTics), XtRImmediate, (XtPointer) True}, {XtNdrawMinor, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(DrawMinor), XtRImmediate, (XtPointer) True}, {XtNdrawMinorTics, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(DrawMinorTics), XtRImmediate, (XtPointer) True}, {XtNmonochrome, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(Monochrome), XtRImmediate, (XtPointer) False}, {XtNshowLegend, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(ShowLegend), XtRImmediate, (XtPointer) True}, {XtNshowTitle, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(ShowTitle), XtRImmediate, (XtPointer) True}, {XtNshowXLabel, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(ShowXLabel), XtRImmediate, (XtPointer) True}, {XtNshowYLabel, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(ShowYLabel), XtRImmediate, (XtPointer) True}, {XtNxLabel, XtCString, XtRString, sizeof(String), offset(TransientXLabel), XtRString, "X Axis"}, {XtNyLabel, XtCString, XtRString, sizeof(String), offset(TransientYLabel), XtRString, "Y Axis"}, {XtNplotTitle, XtCString, XtRString, sizeof(String), offset(TransientPlotTitle), XtRString, "Plot"}, {XtNmargin, XtCMargin, XtRInt, sizeof(int), offset(Margin), XtRImmediate, (XtPointer) 5}, {XtNtitleMargin, XtCMargin, XtRInt, sizeof(int), offset(TitleMargin), XtRImmediate, (XtPointer) 16}, {XtNlegendLineSize, XtCMargin, XtRInt, sizeof(int), offset(LegendLineSize), XtRImmediate, (XtPointer) 16}, {XtNdefaultMarkerSize, XtCMargin, XtRInt, sizeof(int), offset(DefaultMarkerSize), XtRImmediate, (XtPointer) 3}, {XtNlegendMargin, XtCMargin, XtRInt, sizeof(int), offset(LegendMargin), XtRImmediate, (XtPointer) 3}, {XtNlegendThroughPlot, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(LegendThroughPlot), XtRImmediate, (XtPointer) False}, {XtNtitleFont, XtCMargin, XtRInt, sizeof(int), offset(TitleFont), XtRImmediate, (XtPointer) (XtFONT_HELVETICA | 24)}, {XtNlabelFont, XtCMargin, XtRInt, sizeof(int), offset(LabelFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 18)}, {XtNaxisFont, XtCMargin, XtRInt, sizeof(int), offset(AxisFont), XtRImmediate, (XtPointer) (XtFONT_TIMES | 10)}, {XtNxAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(XAutoScale), XtRImmediate, (XtPointer) True}, {XtNyAutoScale, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(YAutoScale), XtRImmediate, (XtPointer) True}, {XtNxAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(XAxisNumbers), XtRImmediate, (XtPointer) True}, {XtNyAxisNumbers, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(YAxisNumbers), XtRImmediate, (XtPointer) True}, {XtNxLog, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(XLog), XtRImmediate, (XtPointer) False}, {XtNyLog, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(YLog), XtRImmediate, (XtPointer) False}, {XtNxOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(XOrigin), XtRImmediate, (XtPointer) False}, {XtNyOrigin, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(YOrigin), XtRImmediate, (XtPointer) False}, {XtNyNumbersHorizontal, XtCBoolean, XtRBoolean, sizeof(Boolean), offset(YNumHorz), XtRImmediate, (XtPointer) True}, }; static SciPlotFontDesc font_desc_table[] = { {XtFONT_TIMES, "Times", "times", False, True}, {XtFONT_COURIER, "Courier", "courier", True, False}, {XtFONT_HELVETICA, "Helvetica", "helvetica", True, False}, {XtFONT_LUCIDA, "Lucida", "lucidabright", False, False}, {XtFONT_LUCIDASANS, "LucidaSans", "lucida", False, False}, {XtFONT_NCSCHOOLBOOK, "NewCenturySchlbk", "new century schoolbook", False, True}, {-1, NULL, NULL, False, False}, }; /* * Private function declarations */ static void Redisplay(); static void Resize(); static Boolean SetValues(); static void GetValuesHook(); static void Initialize(); static void Realize(); static void Destroy(); static void ComputeAll(); static void ComputeAllDimensions(); static void DrawAll(); static void ItemDrawAll(); static void ItemDraw(); static void EraseAll(); static void FontInit(); static int ColorStore(); static int FontStore(); static int FontnumReplace(); SciPlotClassRec sciplotClassRec = { { /* core_class fields */ #ifdef MOTIF /* superclass */ (WidgetClass) & xmPrimitiveClassRec, #else /* superclass */ (WidgetClass) & widgetClassRec, #endif /* class_name */ "SciPlot", /* widget_size */ sizeof(SciPlotRec), /* class_initialize */ NULL, /* class_part_initialize */ NULL, /* class_inited */ False, /* initialize */ Initialize, /* initialize_hook */ NULL, /* realize */ Realize, /* actions */ NULL, /* num_actions */ 0, /* resources */ resources, /* num_resources */ XtNumber(resources), /* xrm_class */ NULLQUARK, /* compress_motion */ True, /* compress_exposure */ XtExposeCompressMultiple, /* compress_enterleave */ True, /* visible_interest */ True, /* destroy */ Destroy, /* resize */ Resize, /* expose */ Redisplay, /* set_values */ SetValues, /* set_values_hook */ NULL, /* set_values_almost */ XtInheritSetValuesAlmost, /* get_values_hook */ GetValuesHook, /* accept_focus */ NULL, /* version */ XtVersion, /* callback_private */ NULL, /* tm_table */ NULL, /* query_geometry */ NULL, /* display_accelerator */ XtInheritDisplayAccelerator, /* extension */ NULL }, #ifdef MOTIF { /* primitive_class fields */ /* border_highlight */ (XtWidgetProc) _XtInherit, /* border_unhighligh */ (XtWidgetProc) _XtInherit, /* translations */ XtInheritTranslations, /* arm_and_activate */ (XtWidgetProc) _XtInherit, /* syn_resources */ NULL, /* num_syn_resources */ 0, /* extension */ NULL }, #endif { /* plot_class fields */ /* dummy */ 0 /* (some stupid compilers barf on empty structures) */ } }; WidgetClass sciplotWidgetClass = (WidgetClass) & sciplotClassRec; static void Initialize(Widget treq, Widget tnew, ArgList args, Cardinal *num) { SciPlotWidget new; new = (SciPlotWidget) tnew; new->plot.plotlist = NULL; new->plot.alloc_plotlist = 0; new->plot.num_plotlist = 0; new->plot.alloc_drawlist = NUMPLOTITEMALLOC; new->plot.drawlist = (SciPlotItem *) XtCalloc(new->plot.alloc_drawlist, sizeof(SciPlotItem)); new->plot.num_drawlist = 0; new->plot.cmap = DefaultColormap(XtDisplay(new), DefaultScreen(XtDisplay(new))); new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1); strcpy(new->plot.xlabel, new->plot.TransientXLabel); new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1); strcpy(new->plot.ylabel, new->plot.TransientYLabel); new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1); strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle); new->plot.TransientXLabel=NULL; new->plot.TransientYLabel=NULL; new->plot.TransientPlotTitle=NULL; new->plot.colors = NULL; new->plot.num_colors = 0; new->plot.fonts = NULL; new->plot.num_fonts = 0; new->plot.update = FALSE; new->plot.UserMin.x = new->plot.UserMin.y = 0.0; new->plot.UserMax.x = new->plot.UserMax.y = 10.0; new->plot.titleFont = FontStore(new, new->plot.TitleFont); new->plot.labelFont = FontStore(new, new->plot.LabelFont); new->plot.axisFont = FontStore(new, new->plot.AxisFont); } static void GCInitialize(SciPlotWidget new) { XGCValues values; XtGCMask mask; long colorsave; values.line_style = LineSolid; values.line_width = 0; values.fill_style = FillSolid; values.background = WhitePixelOfScreen(XtScreen(new)); values.background = new->core.background_pixel; new->plot.BackgroundColor = ColorStore(new, values.background); #ifdef MOTIF new->core.background_pixel = values.background; #endif values.foreground = colorsave = BlackPixelOfScreen(XtScreen(new)); new->plot.ForegroundColor = ColorStore(new, values.foreground); mask = GCLineStyle | GCLineWidth | GCFillStyle | GCForeground | GCBackground; new->plot.defaultGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values); values.foreground = colorsave; values.line_style = LineOnOffDash; new->plot.dashGC = XCreateGC(XtDisplay(new),XtWindow(new), mask, &values); } static void Realize(Widget aw, XtValueMask * value_mask, XSetWindowAttributes * attributes) { SciPlotWidget w = (SciPlotWidget) aw; #define superclass (&widgetClassRec) (*superclass->core_class.realize) (aw, value_mask, attributes); #undef superclass GCInitialize(w); } static void Destroy(SciPlotWidget w) { int i; SciPlotFont *pf; SciPlotList *p; XFreeGC(XtDisplay(w), w->plot.defaultGC); XFreeGC(XtDisplay(w), w->plot.dashGC); XtFree((char *) w->plot.xlabel); XtFree((char *) w->plot.ylabel); XtFree((char *) w->plot.plotTitle); for (i = 0; i < w->plot.num_fonts; i++) { pf = &w->plot.fonts[i]; XFreeFont(XtDisplay((Widget) w), pf->font); } XtFree((char *) w->plot.fonts); XtFree((char *) w->plot.colors); for (i = 0; i < w->plot.alloc_plotlist; i++) { p = w->plot.plotlist + i; if (p->allocated > 0) XtFree((char *) p->data); if (p->legend) XtFree(p->legend); } if (w->plot.alloc_plotlist > 0) XtFree((char *) w->plot.plotlist); EraseAll(w); XtFree((char *) w->plot.drawlist); } static Boolean SetValues(SciPlotWidget current, SciPlotWidget request, SciPlotWidget new, ArgList args, Cardinal nargs) { Boolean redisplay = FALSE; if (current->plot.XLog != new->plot.XLog) redisplay = TRUE; else if (current->plot.YLog != new->plot.YLog) redisplay = TRUE; else if (current->plot.XOrigin != new->plot.XOrigin) redisplay = TRUE; else if (current->plot.YOrigin != new->plot.YOrigin) redisplay = TRUE; else if (current->plot.XAxisNumbers != new->plot.XAxisNumbers) redisplay = TRUE; else if (current->plot.YAxisNumbers != new->plot.YAxisNumbers) redisplay = TRUE; else if (current->plot.DrawMajor != new->plot.DrawMajor) redisplay = TRUE; else if (current->plot.DrawMajorTics != new->plot.DrawMajorTics) redisplay = TRUE; else if (current->plot.DrawMinor != new->plot.DrawMinor) redisplay = TRUE; else if (current->plot.DrawMinorTics != new->plot.DrawMinorTics) redisplay = TRUE; else if (current->plot.ChartType != new->plot.ChartType) redisplay = TRUE; else if (current->plot.Degrees != new->plot.Degrees) redisplay = TRUE; else if (current->plot.ShowLegend != new->plot.ShowLegend) redisplay = TRUE; else if (current->plot.ShowTitle != new->plot.ShowTitle) redisplay = TRUE; else if (current->plot.ShowXLabel != new->plot.ShowXLabel) redisplay = TRUE; else if (current->plot.ShowYLabel != new->plot.ShowYLabel) redisplay = TRUE; else if (current->plot.ShowTitle != new->plot.ShowTitle) redisplay = TRUE; else if (current->plot.Monochrome != new->plot.Monochrome) redisplay = TRUE; if (new->plot.TransientXLabel) { if (current->plot.TransientXLabel != new->plot.TransientXLabel || strcmp(new->plot.TransientXLabel,current->plot.xlabel)!=0) { redisplay = TRUE; XtFree(current->plot.xlabel); new->plot.xlabel = (char *) XtMalloc(strlen(new->plot.TransientXLabel) + 1); strcpy(new->plot.xlabel, new->plot.TransientXLabel); new->plot.TransientXLabel=NULL; } } if (new->plot.TransientYLabel) { if (current->plot.TransientYLabel != new->plot.TransientYLabel || strcmp(new->plot.TransientYLabel,current->plot.ylabel)!=0) { redisplay = TRUE; XtFree(current->plot.ylabel); new->plot.ylabel = (char *) XtMalloc(strlen(new->plot.TransientYLabel) + 1); strcpy(new->plot.ylabel, new->plot.TransientYLabel); new->plot.TransientYLabel=NULL; } } if (new->plot.TransientPlotTitle) { if (current->plot.TransientPlotTitle != new->plot.TransientPlotTitle || strcmp(new->plot.TransientPlotTitle,current->plot.plotTitle)!=0) { redisplay = TRUE; XtFree(current->plot.plotTitle); new->plot.plotTitle = (char *) XtMalloc(strlen(new->plot.TransientPlotTitle) + 1); strcpy(new->plot.plotTitle, new->plot.TransientPlotTitle); new->plot.TransientPlotTitle=NULL; } } if (current->plot.AxisFont != new->plot.AxisFont) { redisplay = TRUE; FontnumReplace(new, new->plot.axisFont, new->plot.AxisFont); } if (current->plot.TitleFont != new->plot.TitleFont) { redisplay = TRUE; FontnumReplace(new, new->plot.titleFont, new->plot.TitleFont); } if (current->plot.LabelFont != new->plot.LabelFont) { redisplay = TRUE; FontnumReplace(new, new->plot.labelFont, new->plot.LabelFont); } new->plot.update = redisplay; return redisplay; } static void GetValuesHook(SciPlotWidget w, ArgList args, Cardinal *num_args) { int i; char **loc; for (i=0; i<*num_args; i++) { loc=(char **)args[i].value; if (strcmp(args[i].name,XtNplotTitle)==0) *loc=w->plot.plotTitle; else if (strcmp(args[i].name,XtNxLabel)==0) *loc=w->plot.xlabel; else if (strcmp(args[i].name,XtNyLabel)==0) *loc=w->plot.ylabel; } } static void Redisplay(SciPlotWidget w) { if (!XtIsRealized((Widget)w)) return; if (w->plot.update) { Resize(w); w->plot.update = FALSE; } else { ItemDrawAll(w); } } static void Resize(SciPlotWidget w) { if (!XtIsRealized((Widget)w)) return; EraseAll(w); ComputeAll(w); DrawAll(w); } /* * Private SciPlot utility functions */ static int ColorStore (SciPlotWidget w, Pixel color) { w->plot.num_colors++; w->plot.colors = (Pixel *) XtRealloc((char *) w->plot.colors, sizeof(Pixel) * w->plot.num_colors); w->plot.colors[w->plot.num_colors - 1] = color; return w->plot.num_colors - 1; } static void FontnumStore (SciPlotWidget w, int fontnum, int flag) { SciPlotFont *pf; int fontflag, sizeflag, attrflag; pf = &w->plot.fonts[fontnum]; fontflag = flag & XtFONT_NAME_MASK; sizeflag = flag & XtFONT_SIZE_MASK; attrflag = flag & XtFONT_ATTRIBUTE_MASK; switch (fontflag) { case XtFONT_TIMES: case XtFONT_COURIER: case XtFONT_HELVETICA: case XtFONT_LUCIDA: case XtFONT_LUCIDASANS: case XtFONT_NCSCHOOLBOOK: break; default: fontflag = XtFONT_NAME_DEFAULT; break; } if (sizeflag < 1) sizeflag = XtFONT_SIZE_DEFAULT; switch (attrflag) { case XtFONT_BOLD: case XtFONT_ITALIC: case XtFONT_BOLD_ITALIC: break; default: attrflag = XtFONT_ATTRIBUTE_DEFAULT; break; } pf->id = flag; FontInit(w, pf); } static int FontnumReplace (SciPlotWidget w, int fontnum, int flag) { SciPlotFont *pf; pf = &w->plot.fonts[fontnum]; XFreeFont(XtDisplay(w), pf->font); FontnumStore(w, fontnum, flag); return fontnum; } static int FontStore (SciPlotWidget w, int flag) { int fontnum; w->plot.num_fonts++; w->plot.fonts = (SciPlotFont *) XtRealloc((char *) w->plot.fonts, sizeof(SciPlotFont) * w->plot.num_fonts); fontnum = w->plot.num_fonts - 1; FontnumStore(w, fontnum, flag); return fontnum; } static SciPlotFontDesc * FontDescLookup (int flag) { SciPlotFontDesc *pfd; pfd = font_desc_table; while (pfd->flag >= 0) { #ifdef DEBUG_SCIPLOT printf("checking if %d == %d (font %s)\n", flag & XtFONT_NAME_MASK, pfd->flag, pfd->PostScript); #endif if ((flag & XtFONT_NAME_MASK) == pfd->flag) return pfd; pfd++; } return NULL; } static void FontnumPostScriptString (SciPlotWidget w, int fontnum, char *str) { char temp[128]; int flag, bold, italic; SciPlotFontDesc *pfd; flag = w->plot.fonts[fontnum].id; pfd = FontDescLookup(flag); if (pfd) { strcpy(temp, pfd->PostScript); bold = False; italic = False; if (flag & XtFONT_BOLD) { bold = True; strcat(temp, "-Bold"); } if (flag & XtFONT_ITALIC) { italic = True; if (!bold) strcat(temp, "-"); if (pfd->PSUsesOblique) strcat(temp, "Oblique"); else strcat(temp, "Italic"); } if (!bold && !italic && pfd->PSUsesRoman) { strcat(temp, "-Roman"); } sprintf(str, "/%s findfont %d scalefont", temp, (flag & XtFONT_SIZE_MASK)); } else sprintf(str, "/Courier findfond 10 scalefont"); } static void FontX11String (int flag, char *str) { SciPlotFontDesc *pfd; pfd = FontDescLookup(flag); if (pfd) { sprintf(str, "-*-%s-%s-%s-*-*-%d-*-*-*-*-*-*-*", pfd->X11, (flag & XtFONT_BOLD ? "bold" : "medium"), (flag & XtFONT_ITALIC ? (pfd->PSUsesOblique ? "o" : "i") : "r"), (flag & XtFONT_SIZE_MASK)); } else sprintf(str, "fixed"); #ifdef DEBUG_SCIPLOT printf("font string=%s\n", str); #endif } static void FontInit (SciPlotWidget w, SciPlotFont *pf) { char str[256], **list; int num; FontX11String(pf->id, str); list = XListFonts(XtDisplay(w), str, 100, &num); #ifdef DEBUG_SCIPLOT if (1) { int i; i = 0; while (i < num) { printf("Found font: %s\n", list[i]); i++; } } #endif if (num <= 0) { pf->id &= ~XtFONT_ATTRIBUTE_MASK; pf->id |= XtFONT_ATTRIBUTE_DEFAULT; FontX11String(pf->id, str); list = XListFonts(XtDisplay(w), str, 100, &num); #ifdef DEBUG_SCIPLOT if (1) { int i; i = 0; while (i < num) { printf("Attr reset: found: %s\n", list[i]); i++; } } #endif } if (num <= 0) { pf->id &= ~XtFONT_NAME_MASK; pf->id |= XtFONT_NAME_DEFAULT; FontX11String(pf->id, str); list = XListFonts(XtDisplay(w), str, 100, &num); #ifdef DEBUG_SCIPLOT if (1) { int i; i = 0; while (i < num) { printf("Name reset: found: %s\n", list[i]); i++; } } #endif } if (num <= 0) { pf->id &= ~XtFONT_SIZE_MASK; pf->id |= XtFONT_SIZE_DEFAULT; FontX11String(pf->id, str); list = XListFonts(XtDisplay(w), str, 100, &num); #ifdef DEBUG_SCIPLOT if (1) { int i; i = 0; while (i < num) { printf("Size reset: found: %s\n", list[i]); i++; } } #endif } if (num <= 0) strcpy(str, "fixed"); else XFreeFontNames(list); pf->font = XLoadQueryFont(XtDisplay(w), str); } static XFontStruct * FontFromFontnum (SciPlotWidget w, int fontnum) { XFontStruct *f; if (fontnum >= w->plot.num_fonts) fontnum = 0; f = w->plot.fonts[fontnum].font; return f; } static real FontHeight(XFontStruct *f) { return (real) (f->max_bounds.ascent + f->max_bounds.descent); } static real FontnumHeight(SciPlotWidget w, int fontnum) { XFontStruct *f; f = FontFromFontnum(w, fontnum); return FontHeight(f); } static real FontDescent(XFontStruct *f) { return (real) (f->max_bounds.descent); } static real FontnumDescent(SciPlotWidget w, int fontnum) { XFontStruct *f; f = FontFromFontnum(w, fontnum); return FontDescent(f); } static real FontAscent(XFontStruct *f) { return (real) (f->max_bounds.ascent); } static real FontnumAscent(SciPlotWidget w, int fontnum) { XFontStruct *f; f = FontFromFontnum(w, fontnum); return FontAscent(f); } static real FontTextWidth(XFontStruct *f, char *c) { return (real) XTextWidth(f, c, strlen(c)); } static real FontnumTextWidth(SciPlotWidget w, int fontnum, char *c) { XFontStruct *f; f = FontFromFontnum(w, fontnum); return FontTextWidth(f, c); } /* * Private List functions */ static int _ListNew (SciPlotWidget w) { int index; SciPlotList *p; Boolean found; /* First check to see if there is any free space in the index */ found = FALSE; for (index = 0; index < w->plot.num_plotlist; index++) { p = w->plot.plotlist + index; if (!p->used) { found = TRUE; break; } } /* If no space is found, increase the size of the index */ if (!found) { w->plot.num_plotlist++; if (w->plot.alloc_plotlist == 0) { w->plot.alloc_plotlist = NUMPLOTLINEALLOC; w->plot.plotlist = (SciPlotList *) XtCalloc(w->plot.alloc_plotlist, sizeof(SciPlotList)); if (!w->plot.plotlist) { printf("Can't calloc memory for SciPlotList\n"); exit(1); } w->plot.alloc_plotlist = NUMPLOTLINEALLOC; } else if (w->plot.num_plotlist > w->plot.alloc_plotlist) { w->plot.alloc_plotlist += NUMPLOTLINEALLOC; w->plot.plotlist = (SciPlotList *) XtRealloc((char *) w->plot.plotlist, w->plot.alloc_plotlist * sizeof(SciPlotList)); if (!w->plot.plotlist) { printf("Can't realloc memory for SciPlotList\n"); exit(1); } } index = w->plot.num_plotlist - 1; p = w->plot.plotlist + index; } p->LineStyle = p->LineColor = p->PointStyle = p->PointColor = 0; p->number = p->allocated = 0; p->data = NULL; p->legend = NULL; p->draw = p->used = TRUE; p->markersize = (real) w->plot.DefaultMarkerSize; return index; } static void _ListDelete (SciPlotList *p) { p->draw = p->used = FALSE; p->number = p->allocated = 0; if (p->data) XtFree((char *) p->data); p->data = NULL; if (p->legend) XtFree((char *) p->legend); p->legend = NULL; } static SciPlotList * _ListFind (SciPlotWidget w, int id) { SciPlotList *p; if ((id >= 0) && (id < w->plot.num_plotlist)) { p = w->plot.plotlist + id; if (p->used) return p; } return NULL; } static void _ListSetStyle (SciPlotList *p, int pcolor, int pstyle, int lcolor, int lstyle) { /* Note! Do checks in here later on... */ if (lstyle >= 0) p->LineStyle = lstyle; if (lcolor >= 0) p->LineColor = lcolor; if (pstyle >= 0) p->PointStyle = pstyle; if (pcolor >= 0) p->PointColor = pcolor; } static void _ListSetLegend (SciPlotList *p, char *legend) { /* Note! Do checks in here later on... */ p->legend = (char *) XtMalloc(strlen(legend) + 1); strcpy(p->legend, legend); } static void _ListAllocData (SciPlotList *p, int num) { if (p->data) { XtFree((char *) p->data); p->allocated = 0; } p->allocated = num + NUMPLOTDATAEXTRA; p->data = (realpair *) XtCalloc(p->allocated, sizeof(realpair)); if (!p->data) { p->number = p->allocated = 0; } } static void _ListReallocData (SciPlotList *p, int more) { if (!p->data) { _ListAllocData(p, more); } else if (p->number + more > p->allocated) { p->allocated += more + NUMPLOTDATAEXTRA; p->data = (realpair *) XtRealloc((char *) p->data, p->allocated * sizeof(realpair)); if (!p->data) { p->number = p->allocated = 0; } } } static void _ListAddReal (SciPlotList *p, int num, real *xlist, real *ylist) { int i; _ListReallocData(p, num); if (p->data) { for (i = 0; i < num; i++) { p->data[i + p->number].x = xlist[i]; p->data[i + p->number].y = ylist[i]; } p->number += num; } } static void _ListAddFloat (SciPlotList *p, int num, float *xlist, float *ylist) { int i; _ListReallocData(p, num); if (p->data) { for (i = 0; i < num; i++) { p->data[i + p->number].x = xlist[i]; p->data[i + p->number].y = ylist[i]; } p->number += num; } } static void _ListAddDouble (SciPlotList *p, int num, double *xlist, double *ylist) { int i; _ListReallocData(p, num); if (p->data) { for (i = 0; i < num; i++) { p->data[i + p->number].x = xlist[i]; p->data[i + p->number].y = ylist[i]; } p->number += num; } } static void _ListSetReal(SciPlotList *p, int num, real *xlist, real *ylist) { if ((!p->data) || (p->allocated < num)) _ListAllocData(p, num); p->number = 0; _ListAddReal(p, num, xlist, ylist); } static void _ListSetFloat (SciPlotList *p, int num, float *xlist, float *ylist) { if ((!p->data) || (p->allocated < num)) _ListAllocData(p, num); p->number = 0; _ListAddFloat(p, num, xlist, ylist); } static void _ListSetDouble (SciPlotList *p, int num, double *xlist, double *ylist) { if ((!p->data) || (p->allocated < num)) _ListAllocData(p, num); p->number = 0; _ListAddDouble(p, num, xlist, ylist); } /* * Private SciPlot functions */ /* * The following vertical text drawing routine uses the "Fill Stippled" idea * found in xvertext-5.0, by Alan Richardson (mppa3@syma.sussex.ac.uk). * * The following code is my interpretation of his idea, including some * hacked together excerpts from his source. The credit for the clever bits * belongs to him. * * To be complete, portions of the subroutine XDrawVString are * Copyright (c) 1993 Alan Richardson (mppa3@syma.sussex.ac.uk) */ static void XDrawVString (Display *display, Window win, GC gc, int x, int y, char *str, int len, XFontStruct *f) { XImage *before, *after; char *dest, *source; int xloop, yloop, xdest, ydest; Pixmap pix, rotpix; int width, height; GC drawGC; width = (int) FontTextWidth(f, str); height = (int) FontHeight(f); pix = XCreatePixmap(display, win, width, height, 1); rotpix = XCreatePixmap(display, win, height, width, 1); drawGC = XCreateGC(display, pix, 0L, NULL); XSetBackground(display, drawGC, 0); XSetFont(display, drawGC, f->fid); XSetForeground(display, drawGC, 0); XFillRectangle(display, pix, drawGC, 0, 0, width, height); XFillRectangle(display, rotpix, drawGC, 0, 0, height, width); XSetForeground(display, drawGC, 1); XDrawImageString(display, pix, drawGC, 0, (int) FontAscent(f), str, strlen(str)); source = (char *) XtCalloc((((width + 7) / 8) * height), 1); before = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)), 1, XYPixmap, 0, source, width, height, 8, 0); before->byte_order = before->bitmap_bit_order = MSBFirst; XGetSubImage(display, pix, 0, 0, width, height, 1L, XYPixmap, before, 0, 0); source = (char *) XtCalloc((((height + 7) / 8) * width), 1); after = XCreateImage(display, DefaultVisual(display, DefaultScreen(display)), 1, XYPixmap, 0, source, height, width, 8, 0); after->byte_order = after->bitmap_bit_order = MSBFirst; for (yloop = 0; yloop < height; yloop++) { for (xloop = 0; xloop < width; xloop++) { source = before->data + (xloop / 8) + (yloop * before->bytes_per_line); if (*source & (128 >> (xloop % 8))) { dest = after->data + (yloop / 8) + ((width - 1 - xloop) * after->bytes_per_line); *dest |= (128 >> (yloop % 8)); } } } #ifdef DEBUG_SCIPLOT_VTEXT if (1) { char sourcebit; for (yloop = 0; yloop < before->height; yloop++) { for (xloop = 0; xloop < before->width; xloop++) { source = before->data + (xloop / 8) + (yloop * before->bytes_per_line); sourcebit = *source & (128 >> (xloop % 8)); if (sourcebit) putchar('X'); else putchar('.'); } putchar('\n'); } for (yloop = 0; yloop < after->height; yloop++) { for (xloop = 0; xloop < after->width; xloop++) { source = after->data + (xloop / 8) + (yloop * after->bytes_per_line); sourcebit = *source & (128 >> (xloop % 8)); if (sourcebit) putchar('X'); else putchar('.'); } putchar('\n'); } } #endif xdest = x - (int) FontAscent(f); if (xdest < 0) xdest = 0; ydest = y - width; XPutImage(display, rotpix, drawGC, after, 0, 0, 0, 0, after->width, after->height); XSetFillStyle(display, gc, FillStippled); XSetStipple(display, gc, rotpix); XSetTSOrigin(display, gc, xdest, ydest); XFillRectangle(display, win, gc, xdest, ydest, after->width, after->height); XSetFillStyle(display, gc, FillSolid); XFreeGC(display, drawGC); XDestroyImage(before); XDestroyImage(after); XFreePixmap(display, pix); XFreePixmap(display, rotpix); /* Note that it appears that there is a memory leak here, but XDestroyImage * frees the image data that is XtCalloc'ed */ } static char dots[] = {2, 1, 1}; static char widedots[] = {2, 1, 4}; static GC ItemGetGC (SciPlotWidget w, SciPlotItem *item) { GC gc; short color; switch (item->kind.any.style) { case XtLINE_SOLID: gc = w->plot.defaultGC; break; case XtLINE_DOTTED: XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &dots[1], (int) dots[0]); gc = w->plot.dashGC; break; case XtLINE_WIDEDOT: XSetDashes(XtDisplay(w), w->plot.dashGC, 0, &widedots[1], (int) widedots[0]); gc = w->plot.dashGC; break; default: return NULL; break; } if (w->plot.Monochrome) if (item->kind.any.color > 0) color = w->plot.ForegroundColor; else color = w->plot.BackgroundColor; else if (item->kind.any.color >= w->plot.num_colors) color = w->plot.ForegroundColor; else if (item->kind.any.color <= 0) color = w->plot.BackgroundColor; else color = item->kind.any.color; XSetForeground(XtDisplay(w), gc, w->plot.colors[color]); return gc; } static GC ItemGetFontGC (SciPlotWidget w, SciPlotItem *item) { GC gc; short color, fontnum; gc = w->plot.dashGC; if (w->plot.Monochrome) if (item->kind.any.color > 0) color = w->plot.ForegroundColor; else color = w->plot.BackgroundColor; else if (item->kind.any.color >= w->plot.num_colors) color = w->plot.ForegroundColor; else if (item->kind.any.color <= 0) color = w->plot.BackgroundColor; else color = item->kind.any.color; XSetForeground(XtDisplay(w), gc, w->plot.colors[color]); if (item->kind.text.font >= w->plot.num_fonts) fontnum = 0; else fontnum = item->kind.text.font; /* * fontnum==0 hack: 0 is supposed to be the default font, but the program * can't seem to get the default font ID from the GC for some reason. So, * use a different GC where the default font still exists. */ XSetFont(XtDisplay(w), gc, w->plot.fonts[fontnum].font->fid); return gc; } static void ItemDraw (SciPlotWidget w, SciPlotItem *item) { XPoint point[8]; XSegment seg; XRectangle rect; int i; GC gc; if (!XtIsRealized((Widget) w)) return; if ((item->type > SciPlotStartTextTypes) && (item->type < SciPlotEndTextTypes)) gc = ItemGetFontGC(w, item); else gc = ItemGetGC(w, item); if (!gc) return; switch (item->type) { case SciPlotLine: seg.x1 = (short) item->kind.line.x1; seg.y1 = (short) item->kind.line.y1; seg.x2 = (short) item->kind.line.x2; seg.y2 = (short) item->kind.line.y2; XDrawSegments(XtDisplay(w), XtWindow(w), gc, &seg, 1); break; case SciPlotRect: XDrawRectangle(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.rect.x), (int) (item->kind.rect.y), (unsigned int) (item->kind.rect.w), (unsigned int) (item->kind.rect.h)); break; case SciPlotFRect: XFillRectangle(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.rect.x), (int) (item->kind.rect.y), (unsigned int) (item->kind.rect.w), (unsigned int) (item->kind.rect.h)); XDrawRectangle(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.rect.x), (int) (item->kind.rect.y), (unsigned int) (item->kind.rect.w), (unsigned int) (item->kind.rect.h)); break; case SciPlotPoly: i = 0; while (i < item->kind.poly.count) { point[i].x = (int) item->kind.poly.x[i]; point[i].y = (int) item->kind.poly.y[i]; i++; } point[i].x = (int) item->kind.poly.x[0]; point[i].y = (int) item->kind.poly.y[0]; XDrawLines(XtDisplay(w), XtWindow(w), gc, point, i + 1, CoordModeOrigin); break; case SciPlotFPoly: i = 0; while (i < item->kind.poly.count) { point[i].x = (int) item->kind.poly.x[i]; point[i].y = (int) item->kind.poly.y[i]; i++; } point[i].x = (int) item->kind.poly.x[0]; point[i].y = (int) item->kind.poly.y[0]; XFillPolygon(XtDisplay(w), XtWindow(w), gc, point, i + 1, Complex, CoordModeOrigin); XDrawLines(XtDisplay(w), XtWindow(w), gc, point, i + 1, CoordModeOrigin); break; case SciPlotCircle: XDrawArc(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.circ.x - item->kind.circ.r), (int) (item->kind.circ.y - item->kind.circ.r), (unsigned int) (item->kind.circ.r * 2), (unsigned int) (item->kind.circ.r * 2), 0 * 64, 360 * 64); break; case SciPlotFCircle: XFillArc(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.circ.x - item->kind.circ.r), (int) (item->kind.circ.y - item->kind.circ.r), (unsigned int) (item->kind.circ.r * 2), (unsigned int) (item->kind.circ.r * 2), 0 * 64, 360 * 64); break; case SciPlotText: XDrawString(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.text.x), (int) (item->kind.text.y), item->kind.text.text, (int) item->kind.text.length); break; case SciPlotVText: XDrawVString(XtDisplay(w), XtWindow(w), gc, (int) (item->kind.text.x), (int) (item->kind.text.y), item->kind.text.text, (int) item->kind.text.length, FontFromFontnum(w, item->kind.text.font)); break; case SciPlotClipRegion: rect.x = (short) item->kind.line.x1; rect.y = (short) item->kind.line.y1; rect.width = (short) item->kind.line.x2; rect.height = (short) item->kind.line.y2; XSetClipRectangles(XtDisplay(w), w->plot.dashGC, 0, 0, &rect, 1, Unsorted); XSetClipRectangles(XtDisplay(w), w->plot.defaultGC, 0, 0, &rect, 1, Unsorted); break; case SciPlotClipClear: XSetClipMask(XtDisplay(w), w->plot.dashGC, None); XSetClipMask(XtDisplay(w), w->plot.defaultGC, None); break; default: break; } } static void ItemDrawAll (SciPlotWidget w) { SciPlotItem *item; int i; if (!XtIsRealized((Widget) w)) return; item = w->plot.drawlist; i = 0; while (i < w->plot.num_drawlist) { ItemDraw(w, item); i++; item++; } } /* * PostScript (r) functions ------------------------------------------------ * */ typedef struct { char *command; char *prolog; } PScommands; static PScommands psc[] = { {"ma", "moveto"}, {"da", "lineto stroke newpath"}, {"la", "lineto"}, {"poly", "closepath stroke newpath"}, {"fpoly", "closepath fill newpath"}, {"box", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath stroke newpath"}, {"fbox", "1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath fill newpath"}, {"clipbox", "gsave 1 index 0 rlineto 0 exch rlineto neg 0 rlineto closepath clip newpath"}, {"unclip", "grestore newpath"}, {"cr", "0 360 arc stroke newpath"}, {"fcr", "0 360 arc fill newpath"}, {"vma", "gsave moveto 90 rotate"}, {"norm", "grestore"}, {"solid", "[] 0 setdash"}, {"dot", "[.25 2] 0 setdash"}, {"widedot", "[.25 8] 0 setdash"}, {"rgb", "setrgbcolor"}, {NULL, NULL} }; enum PSenums { PSmoveto, PSlineto, PSpolyline, PSendpoly, PSendfill, PSbox, PSfbox, PSclipbox, PSunclip, PScircle, PSfcircle, PSvmoveto, PSnormal, PSsolid, PSdot, PSwidedot, PSrgb }; static void ItemPSDrawAll (SciPlotWidget w, FILE *fd, double yflip, Boolean usecolor) { int i, loopcount; SciPlotItem *item; XcmsColor currentcolor; int previousfont, previousline, currentfont, currentline, previouscolor; item = w->plot.drawlist; loopcount = 0; previousfont = 0; previouscolor = -1; previousline = XtLINE_SOLID; while (loopcount < w->plot.num_drawlist) { /* 2 switch blocks: 1st sets up defaults, 2nd actually draws things. */ currentline = previousline; currentfont = previousfont; switch (item->type) { case SciPlotLine: case SciPlotCircle: currentline = item->kind.any.style; break; default: break; } if (currentline != XtLINE_NONE) { if (currentline != previousline) { switch (item->kind.any.style) { case XtLINE_SOLID: fprintf(fd, "%s ", psc[PSsolid].command); break; case XtLINE_DOTTED: fprintf(fd, "%s ", psc[PSdot].command); break; case XtLINE_WIDEDOT: fprintf(fd, "%s ", psc[PSwidedot].command); break; } previousline = currentline; } if (usecolor && item->kind.any.color != previouscolor) { /* Get Pixel index */ currentcolor.pixel = w->plot.colors[item->kind.any.color]; /* Get RGBi components [0.0,1.0] */ XcmsQueryColor( XtDisplay(w), w->plot.cmap, ¤tcolor, XcmsRGBiFormat ); /* output PostScript command */ fprintf(fd, "%f %f %f %s ", currentcolor.spec.RGBi.red, currentcolor.spec.RGBi.green, currentcolor.spec.RGBi.blue, psc[PSrgb].command); previouscolor=item->kind.any.color; } switch (item->type) { case SciPlotLine: fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", item->kind.line.x1, yflip - item->kind.line.y1, psc[PSmoveto].command, item->kind.line.x2, yflip - item->kind.line.y2, psc[PSlineto].command); break; case SciPlotRect: fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", item->kind.rect.x, yflip - item->kind.rect.y - (item->kind.rect.h - 1.0), psc[PSmoveto].command, item->kind.rect.w - 1.0, item->kind.rect.h - 1.0, psc[PSbox].command); break; case SciPlotFRect: fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", item->kind.rect.x, yflip - item->kind.rect.y - (item->kind.rect.h - 1.0), psc[PSmoveto].command, item->kind.rect.w - 1.0, item->kind.rect.h - 1.0, psc[PSfbox].command); break; case SciPlotPoly: fprintf(fd, "%.2f %.2f %s ", item->kind.poly.x[0], yflip - item->kind.poly.y[0], psc[PSmoveto].command); for (i = 1; i < item->kind.poly.count; i++) { fprintf(fd, "%.2f %.2f %s ", item->kind.poly.x[i], yflip - item->kind.poly.y[i], psc[PSpolyline].command); } fprintf(fd, "%s\n", psc[PSendpoly].command); break; case SciPlotFPoly: fprintf(fd, "%.2f %.2f %s ", item->kind.poly.x[0], yflip - item->kind.poly.y[0], psc[PSmoveto].command); for (i = 1; i < item->kind.poly.count; i++) { fprintf(fd, "%.2f %.2f %s ", item->kind.poly.x[i], yflip - item->kind.poly.y[i], psc[PSpolyline].command); } fprintf(fd, "%s\n", psc[PSendfill].command); break; case SciPlotCircle: fprintf(fd, "%.2f %.2f %.2f %s\n", item->kind.circ.x, yflip - item->kind.circ.y, item->kind.circ.r, psc[PScircle].command); break; case SciPlotFCircle: fprintf(fd, "%.2f %.2f %.2f %s\n", item->kind.circ.x, yflip - item->kind.circ.y, item->kind.circ.r, psc[PSfcircle].command); break; case SciPlotText: fprintf(fd, "font-%d %.2f %.2f %s (%s) show\n", item->kind.text.font, item->kind.text.x, yflip - item->kind.text.y, psc[PSmoveto].command, item->kind.text.text); break; case SciPlotVText: fprintf(fd, "font-%d %.2f %.2f %s (%s) show %s\n", item->kind.text.font, item->kind.text.x, yflip - item->kind.text.y, psc[PSvmoveto].command, item->kind.text.text, psc[PSnormal].command); break; case SciPlotClipRegion: fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", item->kind.line.x1, yflip - item->kind.line.y1 - item->kind.line.y2, psc[PSmoveto].command, item->kind.line.x2, item->kind.line.y2, psc[PSclipbox].command); break; case SciPlotClipClear: fprintf(fd, "%s\n", psc[PSunclip].command); break; default: break; } } loopcount++; item++; } } Boolean SciPlotPSCreateFancy (SciPlotWidget w, char *filename, int drawborder, char *titles, Boolean usecolor) { FILE *fd; float scale, xoff, yoff, xmax, ymax, yflip, aspect, border, titlefontsize; int i; PScommands *p; char fontname[128]; if (!(fd = fopen(filename, "w"))) { XtWarning("SciPlotPSCreate: Unable to open postscript file."); return False; } DrawAll(w); aspect = (float) w->core.width / (float) w->core.height; border = 36.0; if (aspect > (612.0 / 792.0)) { scale = (612.0 - (2 * border)) / (float) w->core.width; xoff = border; yoff = (792.0 - (2 * border) - scale * (float) w->core.height) / 2.0; xmax = xoff + scale * (float) w->core.width; ymax = yoff + scale * (float) w->core.height; } else { scale = (792.0 - (2 * border)) / (float) w->core.height; yoff = border; xoff = (612.0 - (2 * border) - scale * (float) w->core.width) / 2.0; xmax = xoff + scale * (float) w->core.width; ymax = yoff + scale * (float) w->core.height; } yflip = w->core.height; fprintf(fd, "%s\n%s %.2f %s\n%s %f %f %f %f\n%s\n", "%!PS-ADOBE-3.0 EPSF-3.0", "%%Creator: SciPlot Widget", _SCIPLOT_WIDGET_VERSION, "Copyright (c) 1995 Robert W. McMullen", "%%BoundingBox:", xoff, yoff, xmax, ymax, "%%EndComments"); p = psc; while (p->command) { fprintf(fd, "/%s {%s} bind def\n", p->command, p->prolog); p++; } for (i = 0; i < w->plot.num_fonts; i++) { FontnumPostScriptString(w, i, fontname); fprintf(fd, "/font-%d {%s setfont} bind def\n", i, fontname); } titlefontsize = 10.0; fprintf(fd, "/font-title {/%s findfont %f scalefont setfont} bind def\n", "Times-Roman", titlefontsize); fprintf(fd, "%f setlinewidth\n", 0.001); fprintf(fd, "newpath gsave\n%f %f translate %f %f scale\n", xoff, yoff, scale, scale); ItemPSDrawAll(w, fd, yflip, usecolor); fprintf(fd, "grestore\n"); if (drawborder) { fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", border, border, psc[PSmoveto].command, 612.0 - 2.0 * border, 792.0 - 2.0 * border, psc[PSbox].command); } if (titles) { char *ptr; char buf[256]; int len, i, j; float x, y; x = border + titlefontsize; y = 792.0 - border - (2.0 * titlefontsize); len = strlen(titles); ptr = titles; i = 0; while (i < len) { j = 0; while ((*ptr != '\n') && (i < len)) { if ((*ptr == '(') || (*ptr == ')')) buf[j++] = '\\'; buf[j++] = *ptr; ptr++; i++; } buf[j] = '\0'; ptr++; i++; fprintf(fd, "font-title %.2f %.2f %s (%s) show\n", x, y, psc[PSmoveto].command, buf); y -= titlefontsize * 1.5; } if (border) { y += titlefontsize * 0.5; fprintf(fd, "%.2f %.2f %s %.2f %.2f %s\n", border, y, psc[PSmoveto].command, 612.0 - border, y, psc[PSlineto].command); } } fprintf(fd, "showpage\n"); fclose(fd); return True; } Boolean SciPlotPSCreate (Widget wi, char *filename) { SciPlotWidget w; if (!XtIsSciPlot(wi)) { XtWarning("SciPlotPSCreate: Not a SciPlot widget."); return False; } w = (SciPlotWidget) wi; return SciPlotPSCreateFancy(w, filename, False, NULL, False); } Boolean SciPlotPSCreateColor (Widget wi, char *filename) { SciPlotWidget w; if (!XtIsSciPlot(wi)) { XtWarning("SciPlotPSCreate: Not a SciPlot widget."); return False; } w = (SciPlotWidget) wi; return SciPlotPSCreateFancy(w, filename, False, NULL, True); } /* * Private device independent drawing functions */ static void EraseClassItems (SciPlotWidget w, SciPlotDrawingEnum drawing) { SciPlotItem *item; int i; if (!XtIsRealized((Widget) w)) return; item = w->plot.drawlist; i = 0; while (i < w->plot.num_drawlist) { if (item->drawing_class == drawing) { item->kind.any.color = 0; item->kind.any.style = XtLINE_SOLID; ItemDraw(w, item); } i++; item++; } } static void EraseAllItems (SciPlotWidget w) { SciPlotItem *item; int i; item = w->plot.drawlist; i = 0; while (i < w->plot.num_drawlist) { if ((item->type > SciPlotStartTextTypes) && (item->type < SciPlotEndTextTypes)) XtFree(item->kind.text.text); i++; item++; } w->plot.num_drawlist = 0; } static void EraseAll (SciPlotWidget w) { EraseAllItems(w); if (XtIsRealized((Widget) w)) XClearWindow(XtDisplay(w), XtWindow(w)); } static SciPlotItem * ItemGetNew (SciPlotWidget w) { SciPlotItem *item; w->plot.num_drawlist++; if (w->plot.num_drawlist >= w->plot.alloc_drawlist) { w->plot.alloc_drawlist += NUMPLOTITEMEXTRA; w->plot.drawlist = (SciPlotItem *) XtRealloc((char *) w->plot.drawlist, w->plot.alloc_drawlist * sizeof(SciPlotItem)); if (!w->plot.drawlist) { printf("Can't realloc memory for SciPlotItem list\n"); exit(1); } #ifdef DEBUG_SCIPLOT printf("Alloced #%d for drawlist\n", w->plot.alloc_drawlist); #endif } item = w->plot.drawlist + (w->plot.num_drawlist - 1); item->type = SciPlotFALSE; item->drawing_class = w->plot.current_id; return item; } static void LineSet(SciPlotWidget w, real x1, real y1, real x2, real y2, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.line.x1 = (real) x1; item->kind.line.y1 = (real) y1; item->kind.line.x2 = (real) x2; item->kind.line.y2 = (real) y2; item->type = SciPlotLine; ItemDraw(w, item); } static void RectSet(SciPlotWidget w, real x1, real y1, real x2, real y2, int color, int style) { SciPlotItem *item; real x, y, width, height; if (x1 < x2) x = x1, width = (x2 - x1 + 1); else x = x2, width = (x1 - x2 + 1); if (y1 < y2) y = y1, height = (y2 - y1 + 1); else y = y2, height = (y1 - y2 + 1); item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.rect.x = (real) x; item->kind.rect.y = (real) y; item->kind.rect.w = (real) width; item->kind.rect.h = (real) height; item->type = SciPlotRect; ItemDraw(w, item); } static void FilledRectSet (SciPlotWidget w, real x1, real y1, real x2, real y2, int color, int style) { SciPlotItem *item; real x, y, width, height; if (x1 < x2) x = x1, width = (x2 - x1 + 1); else x = x2, width = (x1 - x2 + 1); if (y1 < y2) y = y1, height = (y2 - y1 + 1); else y = y2, height = (y1 - y2 + 1); item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.rect.x = (real) x; item->kind.rect.y = (real) y; item->kind.rect.w = (real) width; item->kind.rect.h = (real) height; item->type = SciPlotFRect; ItemDraw(w, item); } static void TriSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.poly.count = 3; item->kind.poly.x[0] = (real) x1; item->kind.poly.y[0] = (real) y1; item->kind.poly.x[1] = (real) x2; item->kind.poly.y[1] = (real) y2; item->kind.poly.x[2] = (real) x3; item->kind.poly.y[2] = (real) y3; item->type = SciPlotPoly; ItemDraw(w, item); } static void FilledTriSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.poly.count = 3; item->kind.poly.x[0] = (real) x1; item->kind.poly.y[0] = (real) y1; item->kind.poly.x[1] = (real) x2; item->kind.poly.y[1] = (real) y2; item->kind.poly.x[2] = (real) x3; item->kind.poly.y[2] = (real) y3; item->type = SciPlotFPoly; ItemDraw(w, item); } static void QuadSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.poly.count = 4; item->kind.poly.x[0] = (real) x1; item->kind.poly.y[0] = (real) y1; item->kind.poly.x[1] = (real) x2; item->kind.poly.y[1] = (real) y2; item->kind.poly.x[2] = (real) x3; item->kind.poly.y[2] = (real) y3; item->kind.poly.x[3] = (real) x4; item->kind.poly.y[3] = (real) y4; item->type = SciPlotPoly; ItemDraw(w, item); } static void FilledQuadSet (SciPlotWidget w, real x1, real y1, real x2, real y2, real x3, real y3, real x4, real y4, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.poly.count = 4; item->kind.poly.x[0] = (real) x1; item->kind.poly.y[0] = (real) y1; item->kind.poly.x[1] = (real) x2; item->kind.poly.y[1] = (real) y2; item->kind.poly.x[2] = (real) x3; item->kind.poly.y[2] = (real) y3; item->kind.poly.x[3] = (real) x4; item->kind.poly.y[3] = (real) y4; item->type = SciPlotFPoly; ItemDraw(w, item); } static void CircleSet (SciPlotWidget w, real x, real y, real r, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.circ.x = (real) x; item->kind.circ.y = (real) y; item->kind.circ.r = (real) r; item->type = SciPlotCircle; ItemDraw(w, item); } static void FilledCircleSet (SciPlotWidget w, real x, real y, real r, int color, int style) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = (short) style; item->kind.circ.x = (real) x; item->kind.circ.y = (real) y; item->kind.circ.r = (real) r; item->type = SciPlotFCircle; ItemDraw(w, item); } static void TextSet (SciPlotWidget w, real x, real y, char *text, int color, int font) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = 0; item->kind.text.x = (real) x; item->kind.text.y = (real) y; item->kind.text.length = strlen(text); item->kind.text.text = XtMalloc((int) item->kind.text.length + 1); item->kind.text.font = font; strcpy(item->kind.text.text, text); item->type = SciPlotText; ItemDraw(w, item); #ifdef DEBUG_SCIPLOT_TEXT if (1) { real x1, y1; y -= FontnumAscent(w, font); y1 = y + FontnumHeight(w, font) - 1.0; x1 = x + FontnumTextWidth(w, font, text) - 1.0; RectSet(w, x, y, x1, y1, color, XtLINE_SOLID); } #endif } static void TextCenter (SciPlotWidget w, real x, real y, char *text, int color, int font) { x -= FontnumTextWidth(w, font, text) / 2.0; y += FontnumHeight(w, font) / 2.0 - FontnumDescent(w, font); TextSet(w, x, y, text, color, font); } static void VTextSet (SciPlotWidget w, real x, real y, char *text, int color, int font) { SciPlotItem *item; item = ItemGetNew(w); item->kind.any.color = (short) color; item->kind.any.style = 0; item->kind.text.x = (real) x; item->kind.text.y = (real) y; item->kind.text.length = strlen(text); item->kind.text.text = XtMalloc((int) item->kind.text.length + 1); item->kind.text.font = font; strcpy(item->kind.text.text, text); item->type = SciPlotVText; ItemDraw(w, item); #ifdef DEBUG_SCIPLOT_TEXT if (1) { real x1, y1; x += FontnumDescent(w, font); x1 = x - FontnumHeight(w, font) - 1.0; y1 = y - FontnumTextWidth(w, font, text) - 1.0; RectSet(w, x, y, x1, y1, color, XtLINE_SOLID); } #endif } static void VTextCenter (SciPlotWidget w, real x, real y, char *text, int color, int font) { x += FontnumHeight(w, font) / 2.0 - FontnumDescent(w, font); y += FontnumTextWidth(w, font, text) / 2.0; VTextSet(w, x, y, text, color, font); } static void ClipSet (SciPlotWidget w) { SciPlotItem *item; if (w->plot.ChartType == XtCARTESIAN) { item = ItemGetNew(w); item->kind.any.style = XtLINE_SOLID; item->kind.any.color = 1; item->kind.line.x1 = w->plot.x.Origin; item->kind.line.x2 = w->plot.x.Size; item->kind.line.y1 = w->plot.y.Origin; item->kind.line.y2 = w->plot.y.Size; #ifdef DEBUG_SCIPLOT printf("clipping region: x=%f y=%f w=%f h=%f\n", item->kind.line.x1, item->kind.line.y1, item->kind.line.x2, item->kind.line.y2 ); #endif item->type = SciPlotClipRegion; ItemDraw(w, item); } } static void ClipClear (SciPlotWidget w) { SciPlotItem *item; if (w->plot.ChartType == XtCARTESIAN) { item = ItemGetNew(w); item->kind.any.style = XtLINE_SOLID; item->kind.any.color = 1; item->type = SciPlotClipClear; ItemDraw(w, item); } } /* * Private data point to screen location converters */ static real PlotX (SciPlotWidget w, real xin) { real xout; if (w->plot.XLog) xout = w->plot.x.Origin + ((log10(xin) - log10(w->plot.x.DrawOrigin)) * (w->plot.x.Size / w->plot.x.DrawSize)); else xout = w->plot.x.Origin + ((xin - w->plot.x.DrawOrigin) * (w->plot.x.Size / w->plot.x.DrawSize)); return xout; } static real PlotY (SciPlotWidget w, real yin) { real yout; if (w->plot.YLog) yout = w->plot.y.Origin + w->plot.y.Size - ((log10(yin) - log10(w->plot.y.DrawOrigin)) * (w->plot.y.Size / w->plot.y.DrawSize)); else yout = w->plot.y.Origin + w->plot.y.Size - ((yin - w->plot.y.DrawOrigin) * (w->plot.y.Size / w->plot.y.DrawSize)); return yout; } static void PlotRTRadians (SciPlotWidget w, real r, real t, real *xout, real *yout) { *xout = w->plot.x.Center + (r * (real) cos(t) / w->plot.PolarScale * w->plot.x.Size / 2.0); *yout = w->plot.y.Center + (-r * (real) sin(t) / w->plot.PolarScale * w->plot.x.Size / 2.0); } static void PlotRTDegrees (SciPlotWidget w, real r, real t, real *xout, real *yout) { t *= DEG2RAD; PlotRTRadians(w, r, t, xout, yout); } static void PlotRT (SciPlotWidget w, real r, real t, real *xout, real *yout) { if (w->plot.Degrees) t *= DEG2RAD; PlotRTRadians(w, r, t, xout, yout); } /* * Private calculation utilities for axes */ #define NUMBER_MINOR 8 #define MAX_MAJOR 8 static float CAdeltas[8] = {0.1, 0.2, 0.25, 0.5, 1.0, 2.0, 2.5, 5.0}; static int CAdecimals[8] = {0, 0, 1, 0, 0, 0, 1, 0}; static int CAminors[8] = {4, 4, 4, 5, 4, 4, 4, 5}; static void ComputeAxis (SciPlotAxis *axis, real min, real max, Boolean log) { real range, rnorm, delta, calcmin, calcmax; int nexp, majornum, minornum, majordecimals, decimals, i; range = max - min; if (log) { if (range==0.0) { calcmin = powi(10.0, (int) floor(log10(min))); calcmax = 10.0*calcmin; } else { calcmin = powi(10.0, (int) floor(log10(min))); calcmax = powi(10.0, (int) ceil(log10(max))); } /* printf("calcmin=%e min=%e calcmax=%e max=%e\n",calcmin,min, */ /* calcmax,max); */ delta = 10.0; axis->DrawOrigin = calcmin; axis->DrawMax = calcmax; axis->DrawSize = log10(calcmax) - log10(calcmin); axis->MajorInc = delta; axis->MajorNum = (int) (log10(calcmax) - log10(calcmin)) + 1; axis->MinorNum = 10; axis->Precision = -(int) (log10(calcmin) * 1.0001); #ifdef DEBUG_SCIPLOT printf("calcmin=%e log=%e (int)log=%d Precision=%d\n", calcmin, log10(calcmin), (int) (log10(calcmin) * 1.0001), axis->Precision); #endif if (axis->Precision < 0) axis->Precision = 0; } else { if (range==0.0) nexp=0; else nexp = (int) floor(log10(range)); rnorm = range / powi(10.0, nexp); for (i = 0; i < NUMBER_MINOR; i++) { delta = CAdeltas[i]; minornum = CAminors[i]; majornum = (int) ((rnorm + 0.9999 * delta) / delta); majordecimals = CAdecimals[i]; if (majornum <= MAX_MAJOR) break; } delta *= powi(10.0, nexp); #ifdef DEBUG_SCIPLOT printf("nexp=%d range=%f rnorm=%f delta=%f\n", nexp, range, rnorm, delta); #endif if (min < 0.0) calcmin = ((float) ((int) ((min - .9999 * delta) / delta))) * delta; else if ((min > 0.0) && (min < 1.0)) calcmin = ((float) ((int) ((1.0001 * min) / delta))) * delta; else if (min >= 1.0) calcmin = ((float) ((int) ((.9999 * min) / delta))) * delta; else calcmin = min; if (max < 0.0) calcmax = ((float) ((int) ((.9999 * max) / delta))) * delta; else if (max > 0.0) calcmax = ((float) ((int) ((max + .9999 * delta) / delta))) * delta; else calcmax = max; axis->DrawOrigin = calcmin; axis->DrawMax = calcmax; axis->DrawSize = calcmax - calcmin; axis->MajorInc = delta; axis->MajorNum = majornum; axis->MinorNum = minornum; delta = log10(axis->MajorInc); if (delta > 0.0) decimals = -(int) floor(delta) + majordecimals; else decimals = (int) ceil(-delta) + majordecimals; if (decimals < 0) decimals = 0; #ifdef DEBUG_SCIPLOT printf("delta=%f majordecimals=%d decimals=%d\n", delta, majordecimals, decimals); #endif axis->Precision = decimals; } #ifdef DEBUG_SCIPLOT printf("Tics: min=%f max=%f size=%f major inc=%f #major=%d #minor=%d decimals=%d\n", axis->DrawOrigin, axis->DrawMax, axis->DrawSize, axis->MajorInc, axis->MajorNum, axis->MinorNum, axis->Precision); #endif } static void ComputeDrawingRange (SciPlotWidget w) { if (w->plot.ChartType == XtCARTESIAN) { ComputeAxis(&w->plot.x, w->plot.Min.x, w->plot.Max.x, w->plot.XLog); ComputeAxis(&w->plot.y, w->plot.Min.y, w->plot.Max.y, w->plot.YLog); } else { ComputeAxis(&w->plot.x, (real) 0.0, w->plot.Max.x, (Boolean) FALSE); w->plot.PolarScale = w->plot.x.DrawMax; } } static Boolean CheckMinMax (SciPlotWidget w) { register int i, j; register SciPlotList *p; register real val; if (w->plot.ChartType == XtCARTESIAN) { for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { for (j = 0; j < p->number; j++) { /* Don't count the "break in line segment" flag for Min/Max */ if (p->data[j].x > SCIPLOT_SKIP_VAL && p->data[j].y > SCIPLOT_SKIP_VAL) { val = p->data[j].x; if (val > w->plot.x.DrawMax || val < w->plot.x.DrawOrigin) return True; val = p->data[j].y; if (val > w->plot.y.DrawMax || val < w->plot.y.DrawOrigin) return True; } } } } } else { for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { for (j = 0; j < p->number; j++) { val = p->data[j].x; if (val > w->plot.Max.x || val < w->plot.Min.x) return True; } } } } return False; } static void ComputeMinMax (SciPlotWidget w) { register int i, j; register SciPlotList *p; register real val; Boolean firstx, firsty; w->plot.Min.x = w->plot.Min.y = w->plot.Max.x = w->plot.Max.y = 1.0; firstx = True; firsty = True; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { for (j = 0; j < p->number; j++) { /* Don't count the "break in line segment" flag for Min/Max */ if (p->data[j].x > SCIPLOT_SKIP_VAL && p->data[j].y > SCIPLOT_SKIP_VAL) { val = p->data[j].x; if (!w->plot.XLog || (w->plot.XLog && (val > 0.0))) { if (firstx) { w->plot.Min.x = w->plot.Max.x = val; firstx = False; } else { if (val > w->plot.Max.x) w->plot.Max.x = val; else if (val < w->plot.Min.x) w->plot.Min.x = val; } } val = p->data[j].y; if (!w->plot.YLog || (w->plot.YLog && (val > 0.0))) { if (firsty) { w->plot.Min.y = w->plot.Max.y = val; firsty = False; } else { if (val > w->plot.Max.y) w->plot.Max.y = val; else if (val < w->plot.Min.y) w->plot.Min.y = val; } } } } } } /* fix defaults if there is only one point. */ if (firstx) { if (w->plot.XLog) { w->plot.Min.x = 1.0; w->plot.Max.x = 10.0; } else { w->plot.Min.x = 0.0; w->plot.Max.x = 10.0; } } if (firsty) { if (w->plot.YLog) { w->plot.Min.y = 1.0; w->plot.Max.y = 10.0; } else { w->plot.Min.y = 0.0; w->plot.Max.y = 10.0; } } if (w->plot.ChartType == XtCARTESIAN) { if (!w->plot.XLog) { if (!w->plot.XAutoScale) { w->plot.Min.x = w->plot.UserMin.x; w->plot.Max.x = w->plot.UserMax.x; } else if (w->plot.XOrigin) { if (w->plot.Min.x > 0.0) w->plot.Min.x = 0.0; if (w->plot.Max.x < 0.0) w->plot.Max.x = 0.0; } if (fabs(w->plot.Min.x - w->plot.Max.x) < 1.e-10) { w->plot.Min.x -= .5; w->plot.Max.x += .5; } } if (!w->plot.YLog) { if (!w->plot.YAutoScale) { w->plot.Min.y = w->plot.UserMin.y; w->plot.Max.y = w->plot.UserMax.y; } else if (w->plot.YOrigin) { if (w->plot.Min.y > 0.0) w->plot.Min.y = 0.0; if (w->plot.Max.y < 0.0) w->plot.Max.y = 0.0; } if (fabs(w->plot.Min.y - w->plot.Max.y) < 1.e-10) { w->plot.Min.y -= .5; w->plot.Max.y += .5; } } } else { if (fabs(w->plot.Min.x) > fabs(w->plot.Max.x)) w->plot.Max.x = fabs(w->plot.Min.x); } #ifdef DEBUG_SCIPLOT printf("Min: (%f,%f)\tMax: (%f,%f)\n", w->plot.Min.x, w->plot.Min.y, w->plot.Max.x, w->plot.Max.y); #endif } static void ComputeLegendDimensions (SciPlotWidget w) { real current, xmax, ymax; int i; SciPlotList *p; if (w->plot.ShowLegend) { xmax = 0.0; ymax = 2.0 * (real) w->plot.LegendMargin; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { current = (real) w->plot.Margin + (real) w->plot.LegendMargin * 3.0 + (real) w->plot.LegendLineSize + FontnumTextWidth(w, w->plot.axisFont, p->legend); if (current > xmax) xmax = current; ymax += FontnumHeight(w, w->plot.axisFont); } } w->plot.x.LegendSize = xmax; w->plot.x.LegendPos = (real) w->plot.Margin; w->plot.y.LegendSize = ymax; w->plot.y.LegendPos = 0.0; } else { w->plot.x.LegendSize = w->plot.x.LegendPos = w->plot.y.LegendSize = w->plot.y.LegendPos = 0.0; } } static void ComputeDimensions (SciPlotWidget w) { real x, y, width, height, axisnumbersize, axisXlabelsize, axisYlabelsize; /* x,y is the origin of the upper left corner of the drawing area inside * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now. */ x = (real) w->plot.Margin; y = (real) w->plot.Margin; /* width = (real)w->core.width - (real)w->plot.Margin - x - * ** legendwidth - AxisFontHeight */ width = (real) w->core.width - (real) w->plot.Margin - x - w->plot.x.LegendSize; /* height = (real)w->core.height - (real)w->plot.Margin - y * - Height of axis numbers (including margin) * - Height of axis label (including margin) * - Height of Title (including margin) */ height = (real) w->core.height - (real) w->plot.Margin - y; w->plot.x.Origin = x; w->plot.y.Origin = y; /* Adjust the size depending upon what sorts of text are visible. */ if (w->plot.ShowTitle) height -= (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont); if (w->plot.ChartType == XtCARTESIAN) { axisnumbersize = (real) w->plot.Margin + FontnumHeight(w, w->plot.axisFont); if (w->plot.XAxisNumbers) { height -= axisnumbersize; } if (w->plot.YAxisNumbers) { width -= axisnumbersize; w->plot.x.Origin += axisnumbersize; } if (w->plot.ShowXLabel) { axisXlabelsize = (real) w->plot.Margin + FontnumHeight(w, w->plot.labelFont); height -= axisXlabelsize; } if (w->plot.ShowYLabel) { axisYlabelsize = (real) w->plot.Margin + FontnumHeight(w, w->plot.labelFont); width -= axisYlabelsize; w->plot.x.Origin += axisYlabelsize; } } w->plot.x.Size = width; w->plot.y.Size = height; /* Adjust parameters for polar plot */ if (w->plot.ChartType == XtPOLAR) { if (height < width) w->plot.x.Size = height; } w->plot.x.Center = w->plot.x.Origin + (width / 2.0); w->plot.y.Center = w->plot.y.Origin + (height / 2.0); } static void AdjustDimensionsCartesian (SciPlotWidget w) { real xextra, yextra, val, xhorz; real x, y, width, height, axisnumbersize, axisXlabelsize, axisYlabelsize; char numberformat[16], label[16]; int precision; /* Compute xextra and yextra, which are the extra distances that the text * labels on the axes stick outside of the graph. */ xextra = yextra = 0.0; if (w->plot.XAxisNumbers) { precision = w->plot.x.Precision; if (w->plot.XLog) { val = w->plot.x.DrawMax; precision -= w->plot.x.MajorNum; if (precision < 0) precision = 0; } else val = w->plot.x.DrawOrigin + floor(w->plot.x.DrawSize / w->plot.x.MajorInc) * w->plot.x.MajorInc; x = PlotX(w, val); sprintf(numberformat, "%%.%df", precision); sprintf(label, numberformat, val); x += FontnumTextWidth(w, w->plot.axisFont, label); if ((int) x > w->core.width) { xextra = ceil(x - w->core.width + w->plot.Margin); if (xextra < 0.0) xextra = 0.0; } } yextra=xhorz=0.0; if (w->plot.YAxisNumbers) { precision = w->plot.y.Precision; if (w->plot.YLog) { int p1,p2; p1=precision; val = w->plot.y.DrawOrigin; if (p1 > 0) p1--; val = w->plot.y.DrawMax; p2 = precision - w->plot.y.MajorNum; if (p2 < 0) p2 = 0; if (p1>p2) precision=p1; else precision=p2; } else val = w->plot.y.DrawOrigin + floor(w->plot.y.DrawSize / w->plot.y.MajorInc * 1.0001) * w->plot.y.MajorInc; y = PlotY(w, val); sprintf(numberformat, "%%.%df", precision); sprintf(label, numberformat, val); #ifdef DEBUG_SCIPLOT printf("ylabel=%s\n", label); #endif if (w->plot.YNumHorz) { yextra=FontnumHeight(w, w->plot.axisFont)/2.0; xhorz=FontnumTextWidth(w, w->plot.axisFont, label) + (real)w->plot.Margin; } else { y -= FontnumTextWidth(w, w->plot.axisFont, label); if ((int) y <= 0) { yextra = ceil(w->plot.Margin - y); if (yextra < 0.0) yextra = 0.0; } } } /* x,y is the origin of the upper left corner of the drawing area inside * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now. */ x = (real) w->plot.Margin + xhorz; y = (real) w->plot.Margin + yextra; /* width = (real)w->core.width - (real)w->plot.Margin - x - * legendwidth - AxisFontHeight */ width = (real) w->core.width - (real) w->plot.Margin - x - xextra; /* height = (real)w->core.height - (real)w->plot.Margin - y * - Height of axis numbers (including margin) * - Height of axis label (including margin) * - Height of Title (including margin) */ height = (real) w->core.height - (real) w->plot.Margin - y; w->plot.x.Origin = x; w->plot.y.Origin = y; /* Adjust the size depending upon what sorts of text are visible. */ if (w->plot.ShowTitle) height -= (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont); axisXlabelsize = 0.0; axisYlabelsize = 0.0; axisnumbersize = (real) w->plot.Margin + FontnumHeight(w, w->plot.axisFont); if (w->plot.XAxisNumbers) { height -= axisnumbersize; } if (w->plot.YAxisNumbers && !w->plot.YNumHorz) { width -= axisnumbersize; w->plot.x.Origin += axisnumbersize; } if (w->plot.ShowXLabel) { axisXlabelsize = (real) w->plot.Margin + FontnumHeight(w, w->plot.labelFont); height -= axisXlabelsize; } if (w->plot.ShowYLabel) { axisYlabelsize = (real) w->plot.Margin + FontnumHeight(w, w->plot.labelFont); width -= axisYlabelsize; w->plot.x.Origin += axisYlabelsize; } /* Move legend position to the right of the plot */ if (w->plot.LegendThroughPlot) { w->plot.x.LegendPos += w->plot.x.Origin + width - w->plot.x.LegendSize; w->plot.y.LegendPos += w->plot.y.Origin; } else { width -= w->plot.x.LegendSize; w->plot.x.LegendPos += w->plot.x.Origin + width; w->plot.y.LegendPos += w->plot.y.Origin; } w->plot.x.Size = width; w->plot.y.Size = height; w->plot.y.AxisPos = w->plot.y.Origin + w->plot.y.Size + (real) w->plot.Margin + FontnumAscent(w, w->plot.axisFont); if (w->plot.YNumHorz) { w->plot.x.AxisPos = w->plot.x.Origin - (real) w->plot.Margin; } else { w->plot.x.AxisPos = w->plot.x.Origin - (real) w->plot.Margin - FontnumDescent(w, w->plot.axisFont); } w->plot.y.LabelPos = w->plot.y.Origin + w->plot.y.Size + (real) w->plot.Margin + (FontnumHeight(w, w->plot.labelFont) / 2.0); if (w->plot.XAxisNumbers) w->plot.y.LabelPos += axisnumbersize; if (w->plot.YAxisNumbers) { if (w->plot.YNumHorz) { w->plot.x.LabelPos = w->plot.x.Origin - xhorz - (real) w->plot.Margin - (FontnumHeight(w, w->plot.labelFont) / 2.0); } else { w->plot.x.LabelPos = w->plot.x.Origin - axisnumbersize - (real) w->plot.Margin - (FontnumHeight(w, w->plot.labelFont) / 2.0); } } else { w->plot.x.LabelPos = w->plot.x.Origin - (real) w->plot.Margin - (FontnumHeight(w, w->plot.labelFont) / 2.0); } w->plot.y.TitlePos = (real) w->core.height - (real) w->plot.Margin; w->plot.x.TitlePos = (real) w->plot.Margin; #ifdef DEBUG_SCIPLOT printf("y.Origin: %f\n", w->plot.y.Origin); printf("y.Size: %f\n", w->plot.y.Size); printf("axisnumbersize: %f\n", axisnumbersize); printf("y.axisLabelSize: %f\n", axisYlabelsize); printf("y.TitleSize: %f\n", (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont)); printf("y.Margin: %f\n", (real) w->plot.Margin); printf("total-------------------%f\n", w->plot.y.Origin + w->plot.y.Size + axisnumbersize + axisYlabelsize + (real) w->plot.Margin + (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont)); printf("total should be---------%f\n", (real) w->core.height); #endif } static void AdjustDimensionsPolar (SciPlotWidget w) { real x, y, xextra, yextra, val; real width, height, size; char numberformat[16], label[16]; /* Compute xextra and yextra, which are the extra distances that the text * labels on the axes stick outside of the graph. */ xextra = yextra = 0.0; val = w->plot.PolarScale; PlotRTDegrees(w, val, 0.0, &x, &y); sprintf(numberformat, "%%.%df", w->plot.x.Precision); sprintf(label, numberformat, val); x += FontnumTextWidth(w, w->plot.axisFont, label); if ((int) x > w->core.width) { xextra = x - w->core.width + w->plot.Margin; if (xextra < 0.0) xextra = 0.0; } yextra = 0.0; /* x,y is the origin of the upper left corner of the drawing area inside * the widget. Doesn't necessarily have to be (Margin,Margin) as it is now. */ w->plot.x.Origin = (real) w->plot.Margin; w->plot.y.Origin = (real) w->plot.Margin; /* width = (real)w->core.width - (real)w->plot.Margin - x - * legendwidth - AxisFontHeight */ width = (real) w->core.width - (real) w->plot.Margin - w->plot.x.Origin - xextra; /* height = (real)w->core.height - (real)w->plot.Margin - y * - Height of axis numbers (including margin) * - Height of axis label (including margin) * - Height of Title (including margin) */ height = (real) w->core.height - (real) w->plot.Margin - w->plot.y.Origin - yextra; /* Adjust the size depending upon what sorts of text are visible. */ if (w->plot.ShowTitle) height -= (real) w->plot.TitleMargin + FontnumHeight(w, w->plot.titleFont); /* Only need to carry one number for the size, (since it is a circle!) */ if (height < width) size = height; else size = width; /* Assign some preliminary values */ w->plot.x.Center = w->plot.x.Origin + (width / 2.0); w->plot.y.Center = w->plot.y.Origin + (height / 2.0); w->plot.x.LegendPos += width - w->plot.x.LegendSize; w->plot.y.LegendPos += w->plot.y.Origin; /* * Check and see if the legend can fit in the blank space in the upper right * * To fit, the legend must: * 1) be less than half the width/height of the plot * 2) hmmm. */ if (!w->plot.LegendThroughPlot) { real radius = size / 2.0; real dist; x = w->plot.x.LegendPos - w->plot.x.Center; y = (w->plot.y.LegendPos + w->plot.y.LegendSize) - w->plot.y.Center; dist = sqrt(x * x + y * y); /* printf("rad=%f dist=%f: legend=(%f,%f) center=(%f,%f)\n", */ /* radius,dist,w->plot.x.LegendPos,w->plot.y.LegendPos, */ /* w->plot.x.Center,w->plot.y.Center); */ /* It doesn't fit if this check is true. Make the plot smaller */ /* This is a first cut horrible algorithm. My calculus is a bit * rusty tonight--can't seem to figure out how to maximize a circle * in a rectangle with a rectangular chunk out of it. */ if (dist < radius) { width -= w->plot.x.LegendSize; height -= w->plot.y.LegendSize; /* readjust some parameters */ w->plot.x.Center = w->plot.x.Origin + width / 2.0; w->plot.y.Center = w->plot.y.Origin + w->plot.y.LegendSize + height / 2.0; if (height < width) size = height; else size = width; } } /* OK, customization is finished when we reach here. */ w->plot.x.Size = w->plot.y.Size = size; w->plot.y.TitlePos = w->plot.y.Center + w->plot.y.Size / 2.0 + (real) w->plot.TitleMargin + FontnumAscent(w, w->plot.titleFont); w->plot.x.TitlePos = w->plot.x.Origin; } static void AdjustDimensions (SciPlotWidget w) { if (w->plot.ChartType == XtCARTESIAN) { AdjustDimensionsCartesian(w); } else { AdjustDimensionsPolar(w); } } static void ComputeAllDimensions (SciPlotWidget w) { ComputeLegendDimensions(w); ComputeDimensions(w); ComputeDrawingRange(w); AdjustDimensions(w); } static void ComputeAll (SciPlotWidget w) { ComputeMinMax(w); ComputeAllDimensions(w); } /* * Private drawing routines */ static void DrawMarker (SciPlotWidget w, real xpaper, real ypaper, real size, int color, int style) { real sizex, sizey; switch (style) { case XtMARKER_CIRCLE: CircleSet(w, xpaper, ypaper, size, color, XtLINE_SOLID); break; case XtMARKER_FCIRCLE: FilledCircleSet(w, xpaper, ypaper, size, color, XtLINE_SOLID); break; case XtMARKER_SQUARE: size -= .5; RectSet(w, xpaper - size, ypaper - size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_FSQUARE: size -= .5; FilledRectSet(w, xpaper - size, ypaper - size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_UTRIANGLE: sizex = size * .866; sizey = size / 2.0; TriSet(w, xpaper, ypaper - size, xpaper + sizex, ypaper + sizey, xpaper - sizex, ypaper + sizey, color, XtLINE_SOLID); break; case XtMARKER_FUTRIANGLE: sizex = size * .866; sizey = size / 2.0; FilledTriSet(w, xpaper, ypaper - size, xpaper + sizex, ypaper + sizey, xpaper - sizex, ypaper + sizey, color, XtLINE_SOLID); break; case XtMARKER_DTRIANGLE: sizex = size * .866; sizey = size / 2.0; TriSet(w, xpaper, ypaper + size, xpaper + sizex, ypaper - sizey, xpaper - sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_FDTRIANGLE: sizex = size * .866; sizey = size / 2.0; FilledTriSet(w, xpaper, ypaper + size, xpaper + sizex, ypaper - sizey, xpaper - sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_RTRIANGLE: sizey = size * .866; sizex = size / 2.0; TriSet(w, xpaper + size, ypaper, xpaper - sizex, ypaper + sizey, xpaper - sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_FRTRIANGLE: sizey = size * .866; sizex = size / 2.0; FilledTriSet(w, xpaper + size, ypaper, xpaper - sizex, ypaper + sizey, xpaper - sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_LTRIANGLE: sizey = size * .866; sizex = size / 2.0; TriSet(w, xpaper - size, ypaper, xpaper + sizex, ypaper + sizey, xpaper + sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_FLTRIANGLE: sizey = size * .866; sizex = size / 2.0; FilledTriSet(w, xpaper - size, ypaper, xpaper + sizex, ypaper + sizey, xpaper + sizex, ypaper - sizey, color, XtLINE_SOLID); break; case XtMARKER_DIAMOND: QuadSet(w, xpaper, ypaper - size, xpaper + size, ypaper, xpaper, ypaper + size, xpaper - size, ypaper, color, XtLINE_SOLID); break; case XtMARKER_FDIAMOND: FilledQuadSet(w, xpaper, ypaper - size, xpaper + size, ypaper, xpaper, ypaper + size, xpaper - size, ypaper, color, XtLINE_SOLID); break; case XtMARKER_HOURGLASS: QuadSet(w, xpaper - size, ypaper - size, xpaper + size, ypaper - size, xpaper - size, ypaper + size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_FHOURGLASS: FilledQuadSet(w, xpaper - size, ypaper - size, xpaper + size, ypaper - size, xpaper - size, ypaper + size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_BOWTIE: QuadSet(w, xpaper - size, ypaper - size, xpaper - size, ypaper + size, xpaper + size, ypaper - size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_FBOWTIE: FilledQuadSet(w, xpaper - size, ypaper - size, xpaper - size, ypaper + size, xpaper + size, ypaper - size, xpaper + size, ypaper + size, color, XtLINE_SOLID); break; case XtMARKER_DOT: FilledCircleSet(w, xpaper, ypaper, 1.5, color, XtLINE_SOLID); break; default: break; } } static void DrawLegend (SciPlotWidget w) { real x, y, len, height, height2, len2, ascent; int i; SciPlotList *p; w->plot.current_id = SciPlotDrawingLegend; if (w->plot.ShowLegend) { x = w->plot.x.LegendPos; y = w->plot.y.LegendPos; len = (real) w->plot.LegendLineSize; len2 = len / 2.0; height = FontnumHeight(w, w->plot.axisFont); height2 = height / 2.0; ascent = FontnumAscent(w, w->plot.axisFont); RectSet(w, x, y, x + w->plot.x.LegendSize - 1.0 - (real) w->plot.Margin, y + w->plot.y.LegendSize - 1.0, w->plot.ForegroundColor, XtLINE_SOLID); x += (real) w->plot.LegendMargin; y += (real) w->plot.LegendMargin; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { LineSet(w, x, y + height2, x + len, y + height2, p->LineColor, p->LineStyle); DrawMarker(w, x + len2, y + height2, p->markersize, p->PointColor, p->PointStyle); TextSet(w, x + len + (real) w->plot.LegendMargin, y + ascent, p->legend, w->plot.ForegroundColor, w->plot.axisFont); y += height; } } } } static void DrawCartesianAxes (SciPlotWidget w) { real x, y, x1, y1, x2, y2, tic, val, height, majorval; int j, precision; char numberformat[16], label[16]; w->plot.current_id = SciPlotDrawingAxis; height = FontnumHeight(w, w->plot.labelFont); x1 = PlotX(w, w->plot.x.DrawOrigin); y1 = PlotY(w, w->plot.y.DrawOrigin); x2 = PlotX(w, w->plot.x.DrawMax); y2 = PlotY(w, w->plot.y.DrawMax); LineSet(w, x1, y1, x2, y1, w->plot.ForegroundColor, XtLINE_SOLID); LineSet(w, x1, y1, x1, y2, w->plot.ForegroundColor, XtLINE_SOLID); precision = w->plot.x.Precision; sprintf(numberformat, "%%.%df", precision); if (w->plot.XLog) { val = w->plot.x.DrawOrigin; if (precision > 0) precision--; } else { val = w->plot.x.DrawOrigin; } x = PlotX(w, val); if (w->plot.DrawMajorTics) LineSet(w, x, y1 + 5, x, y1 - 5, w->plot.ForegroundColor, XtLINE_SOLID); if (w->plot.XAxisNumbers) { sprintf(label, numberformat, val); TextSet(w, x, w->plot.y.AxisPos, label, w->plot.ForegroundColor, w->plot.axisFont); } majorval = val; while ((majorval * 1.0001) < w->plot.x.DrawMax) { if (w->plot.XLog) { /* Hack to make sure that 9.99999e? still gets interpreted as 10.0000e? */ if (majorval * 1.1 > w->plot.x.DrawMax) break; tic = majorval; if (w->plot.DrawMinor || w->plot.DrawMinorTics) { for (j = 2; j < w->plot.x.MinorNum; j++) { val = tic * (real) j; x = PlotX(w, val); if (w->plot.DrawMinor) LineSet(w, x, y1, x, y2, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMinorTics) LineSet(w, x, y1, x, y1 - 3, w->plot.ForegroundColor, XtLINE_SOLID); } } val = tic * (real) w->plot.x.MinorNum; sprintf(numberformat, "%%.%df", precision); if (precision > 0) precision--; } else { tic = majorval; if (w->plot.DrawMinor || w->plot.DrawMinorTics) { for (j = 1; j < w->plot.x.MinorNum; j++) { val = tic + w->plot.x.MajorInc * (real) j / w->plot.x.MinorNum; x = PlotX(w, val); if (w->plot.DrawMinor) LineSet(w, x, y1, x, y2, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMinorTics) LineSet(w, x, y1, x, y1 - 3, w->plot.ForegroundColor, XtLINE_SOLID); } } val = tic + w->plot.x.MajorInc; } x = PlotX(w, val); if (w->plot.DrawMajor) LineSet(w, x, y1, x, y2, w->plot.ForegroundColor, XtLINE_DOTTED); else if (w->plot.DrawMinor) LineSet(w, x, y1, x, y2, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMajorTics) LineSet(w, x, y1 + 5, x, y1 - 5, w->plot.ForegroundColor, XtLINE_SOLID); if (w->plot.XAxisNumbers) { sprintf(label, numberformat, val); TextSet(w, x, w->plot.y.AxisPos, label, w->plot.ForegroundColor, w->plot.axisFont); } majorval = val; } precision = w->plot.y.Precision; sprintf(numberformat, "%%.%df", precision); if (w->plot.YLog) { val = w->plot.y.DrawOrigin; if (precision > 0) precision--; } else { val = w->plot.y.DrawOrigin; } y = PlotY(w, val); if (w->plot.DrawMajorTics) LineSet(w, x1 + 5, y, x1 - 5, y, w->plot.ForegroundColor, XtLINE_SOLID); if (w->plot.YAxisNumbers) { sprintf(label, numberformat, val); if (w->plot.YNumHorz) { y+=FontnumHeight(w, w->plot.axisFont)/2.0 - FontnumDescent(w, w->plot.axisFont); TextSet(w, w->plot.x.AxisPos - FontnumTextWidth(w, w->plot.axisFont, label), y, label, w->plot.ForegroundColor, w->plot.axisFont); } else { VTextSet(w, w->plot.x.AxisPos, y, label, w->plot.ForegroundColor, w->plot.axisFont); } } majorval = val; /* majorval*1.0001 is a fudge to get rid of rounding errors that seem to * occur when continuing to add the major axis increment. */ while ((majorval * 1.0001) < w->plot.y.DrawMax) { if (w->plot.YLog) { /* Hack to make sure that 9.99999e? still gets interpreted as 10.0000e? */ if (majorval * 1.1 > w->plot.y.DrawMax) break; tic = majorval; if (w->plot.DrawMinor || w->plot.DrawMinorTics) { for (j = 2; j < w->plot.y.MinorNum; j++) { val = tic * (real) j; y = PlotY(w, val); if (w->plot.DrawMinor) LineSet(w, x1, y, x2, y, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMinorTics) LineSet(w, x1, y, x1 + 3, y, w->plot.ForegroundColor, XtLINE_SOLID); } } val = tic * (real) w->plot.y.MinorNum; sprintf(numberformat, "%%.%df", precision); if (precision > 0) precision--; } else { tic = majorval; if (w->plot.DrawMinor || w->plot.DrawMinorTics) { for (j = 1; j < w->plot.y.MinorNum; j++) { val = tic + w->plot.y.MajorInc * (real) j / w->plot.y.MinorNum; y = PlotY(w, val); if (w->plot.DrawMinor) LineSet(w, x1, y, x2, y, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMinorTics) LineSet(w, x1, y, x1 + 3, y, w->plot.ForegroundColor, XtLINE_SOLID); } } val = tic + w->plot.y.MajorInc; } y = PlotY(w, val); if (w->plot.DrawMajor) LineSet(w, x1, y, x2, y, w->plot.ForegroundColor, XtLINE_DOTTED); else if (w->plot.DrawMinor) LineSet(w, x1, y, x2, y, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMajorTics) LineSet(w, x1 - 5, y, x1 + 5, y, w->plot.ForegroundColor, XtLINE_SOLID); if (w->plot.YAxisNumbers) { sprintf(label, numberformat, val); if (w->plot.YNumHorz) { y+=FontnumHeight(w, w->plot.axisFont)/2.0 - FontnumDescent(w, w->plot.axisFont); TextSet(w, w->plot.x.AxisPos - FontnumTextWidth(w, w->plot.axisFont, label), y, label, w->plot.ForegroundColor, w->plot.axisFont); } else { VTextSet(w, w->plot.x.AxisPos, y, label, w->plot.ForegroundColor, w->plot.axisFont); } } majorval = val; } if (w->plot.ShowTitle) TextSet(w, w->plot.x.TitlePos, w->plot.y.TitlePos, w->plot.plotTitle, w->plot.ForegroundColor, w->plot.titleFont); if (w->plot.ShowXLabel) TextCenter(w, w->plot.x.Origin + (w->plot.x.Size / 2.0), w->plot.y.LabelPos, w->plot.xlabel, w->plot.ForegroundColor, w->plot.labelFont); if (w->plot.ShowYLabel) VTextCenter(w, w->plot.x.LabelPos, w->plot.y.Origin + (w->plot.y.Size / 2.0), w->plot.ylabel, w->plot.ForegroundColor, w->plot.labelFont); } static void DrawCartesianPlot (SciPlotWidget w) { int i, j, jstart; SciPlotList *p; w->plot.current_id = SciPlotDrawingAny; ClipSet(w); w->plot.current_id = SciPlotDrawingLine; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { real x1, y1, x2, y2; Boolean skipnext=False; jstart = 0; while ((jstart < p->number) && (((p->data[jstart].x <= SCIPLOT_SKIP_VAL || p->data[jstart].y <= SCIPLOT_SKIP_VAL) || (w->plot.XLog && (p->data[jstart].x <= 0.0)) || (w->plot.YLog && (p->data[jstart].y <= 0.0))))) jstart++; if (jstart < p->number) { x1 = PlotX(w, p->data[jstart].x); y1 = PlotY(w, p->data[jstart].y); } for (j = jstart; j < p->number; j++) { if (p->data[j].x <= SCIPLOT_SKIP_VAL || p->data[j].y <= SCIPLOT_SKIP_VAL) { skipnext=True; continue; } if (!((w->plot.XLog && (p->data[j].x <= 0.0)) || (w->plot.YLog && (p->data[j].y <= 0.0)))) { x2 = PlotX(w, p->data[j].x); y2 = PlotY(w, p->data[j].y); if (!skipnext) LineSet(w, x1, y1, x2, y2, p->LineColor, p->LineStyle); x1 = x2; y1 = y2; } skipnext=False; } } } w->plot.current_id = SciPlotDrawingAny; ClipClear(w); w->plot.current_id = SciPlotDrawingLine; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { real x2, y2; for (j = 0; j < p->number; j++) { if (!((w->plot.XLog && (p->data[j].x <= 0.0)) || (w->plot.YLog && (p->data[j].y <= 0.0)) || p->data[j].x <= SCIPLOT_SKIP_VAL || p->data[j].y <= SCIPLOT_SKIP_VAL )) { x2 = PlotX(w, p->data[j].x); y2 = PlotY(w, p->data[j].y); if ((x2 >= w->plot.x.Origin) && (x2 <= w->plot.x.Origin + w->plot.x.Size) && (y2 >= w->plot.y.Origin) && (y2 <= w->plot.y.Origin + w->plot.y.Size)) { DrawMarker(w, x2, y2, p->markersize, p->PointColor, p->PointStyle); } } } } } } static void DrawPolarAxes (SciPlotWidget w) { real x1, y1, x2, y2, max, tic, val, height; int i, j; char numberformat[16], label[16]; w->plot.current_id = SciPlotDrawingAxis; sprintf(numberformat, "%%.%df", w->plot.x.Precision); height = FontnumHeight(w, w->plot.labelFont); max = w->plot.PolarScale; PlotRTDegrees(w, 0.0, 0.0, &x1, &y1); PlotRTDegrees(w, max, 0.0, &x2, &y2); LineSet(w, x1, y1, x2, y2, 1, XtLINE_SOLID); for (i = 45; i < 360; i += 45) { PlotRTDegrees(w, max, (real) i, &x2, &y2); LineSet(w, x1, y1, x2, y2, w->plot.ForegroundColor, XtLINE_DOTTED); } for (i = 1; i <= w->plot.x.MajorNum; i++) { tic = w->plot.PolarScale * (real) i / (real) w->plot.x.MajorNum; if (w->plot.DrawMinor || w->plot.DrawMinorTics) { for (j = 1; j < w->plot.x.MinorNum; j++) { val = tic - w->plot.x.MajorInc * (real) j / w->plot.x.MinorNum; PlotRTDegrees(w, val, 0.0, &x2, &y2); if (w->plot.DrawMinor) CircleSet(w, x1, y1, x2 - x1, w->plot.ForegroundColor, XtLINE_WIDEDOT); if (w->plot.DrawMinorTics) LineSet(w, x2, y2 - 2.5, x2, y2 + 2.5, w->plot.ForegroundColor, XtLINE_SOLID); } } PlotRTDegrees(w, tic, 0.0, &x2, &y2); if (w->plot.DrawMajor) CircleSet(w, x1, y1, x2 - x1, w->plot.ForegroundColor, XtLINE_DOTTED); if (w->plot.DrawMajorTics) LineSet(w, x2, y2 - 5.0, x2, y2 + 5.0, w->plot.ForegroundColor, XtLINE_SOLID); if (w->plot.XAxisNumbers) { sprintf(label, numberformat, tic); TextSet(w, x2, y2 + height, label, w->plot.ForegroundColor, w->plot.axisFont); } } if (w->plot.ShowTitle) TextSet(w, w->plot.x.TitlePos, w->plot.y.TitlePos, w->plot.plotTitle, w->plot.ForegroundColor, w->plot.titleFont); } static void DrawPolarPlot (SciPlotWidget w) { int i, j; SciPlotList *p; w->plot.current_id = SciPlotDrawingLine; for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { int jstart; real x1, y1, x2, y2; Boolean skipnext=False; jstart = 0; while ((jstart < p->number) && (p->data[jstart].x <= SCIPLOT_SKIP_VAL || p->data[jstart].y <= SCIPLOT_SKIP_VAL)) jstart++; if (jstart < p->number) { PlotRT(w, p->data[0].x, p->data[0].y, &x1, &y1); } for (j = jstart; j < p->number; j++) { if (p->data[j].x <= SCIPLOT_SKIP_VAL || p->data[j].y <= SCIPLOT_SKIP_VAL) { skipnext=True; continue; } PlotRT(w, p->data[j].x, p->data[j].y, &x2, &y2); if (!skipnext) { LineSet(w, x1, y1, x2, y2, p->LineColor, p->LineStyle); DrawMarker(w, x1, y1, p->markersize, p->PointColor, p->PointStyle); DrawMarker(w, x2, y2, p->markersize, p->PointColor, p->PointStyle); } x1 = x2; y1 = y2; skipnext=False; } } } } static void DrawAll (SciPlotWidget w) { if (w->plot.ChartType == XtCARTESIAN) { DrawCartesianAxes(w); DrawLegend(w); DrawCartesianPlot(w); } else { DrawPolarAxes(w); DrawLegend(w); DrawPolarPlot(w); } } static Boolean DrawQuick (SciPlotWidget w) { Boolean range_check; range_check = CheckMinMax(w); EraseClassItems(w, SciPlotDrawingLine); EraseAllItems(w); DrawAll(w); return range_check; } /* * Public Plot functions */ int SciPlotAllocNamedColor (Widget wi, char *name) { XColor used, exact; SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; if (!XAllocNamedColor(XtDisplay(w), w->plot.cmap, name, &used, &exact)) return 1; return ColorStore(w, used.pixel); } int SciPlotAllocRGBColor (Widget wi, int r, int g, int b) { XColor used; SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; used.pixel = 0; r *= 256; g *= 256; b *= 256; if (r > 65535) r = 65535; if (g > 65535) g = 65535; if (b > 65535) b = 65535; used.red = (unsigned short) r; used.green = (unsigned short) g; used.blue = (unsigned short) b; if (!XAllocColor(XtDisplay(w), w->plot.cmap, &used)) return 1; return ColorStore(w, used.pixel); } void SciPlotSetBackgroundColor (Widget wi, int color) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; if (color < w->plot.num_colors) { w->plot.BackgroundColor = color; w->core.background_pixel = w->plot.colors[color]; XSetWindowBackground( XtDisplay(w), XtWindow(w), w->core.background_pixel); } } void SciPlotSetForegroundColor (Widget wi, int color) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; if (color < w->plot.num_colors) w->plot.ForegroundColor = color; } void SciPlotListDelete (Widget wi, int idnum) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListDelete(p); } int SciPlotListCreateFromData (Widget wi, int num, real *xlist, real *ylist, char *legend, int pcolor, int pstyle, int lcolor, int lstyle) { int idnum; SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; idnum = _ListNew(w); p = w->plot.plotlist + idnum; _ListSetReal(p, num, xlist, ylist); _ListSetLegend(p, legend); _ListSetStyle(p, pcolor, pstyle, lcolor, lstyle); return idnum; } int SciPlotListCreateFloat (Widget wi, int num, float *xlist, float *ylist, char *legend) { int idnum; SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; idnum = _ListNew(w); p = w->plot.plotlist + idnum; _ListSetFloat(p, num, xlist, ylist); _ListSetLegend(p, legend); _ListSetStyle(p, 1, XtMARKER_CIRCLE, 1, XtLINE_SOLID); return idnum; } void SciPlotListUpdateFloat (Widget wi, int idnum, int num, float *xlist, float *ylist) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListSetFloat(p, num, xlist, ylist); } void SciPlotListAddFloat (Widget wi, int idnum, int num, float *xlist, float *ylist) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListAddFloat(p, num, xlist, ylist); } int SciPlotListCreateDouble (Widget wi, int num, double *xlist, double *ylist, char *legend) { int idnum; SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; idnum = _ListNew(w); p = w->plot.plotlist + idnum; _ListSetDouble(p, num, xlist, ylist); _ListSetLegend(p, legend); _ListSetStyle(p, 1, XtMARKER_CIRCLE, 1, XtLINE_SOLID); return idnum; } void SciPlotListUpdateDouble (Widget wi, int idnum, int num, double *xlist, double *ylist) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListSetDouble(p, num, xlist, ylist); } void SciPlotListAddDouble (Widget wi, int idnum, int num, double *xlist, double *ylist) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListAddDouble(p, num, xlist, ylist); } void SciPlotListSetStyle (Widget wi, int idnum, int pcolor, int pstyle, int lcolor, int lstyle) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) _ListSetStyle(p, pcolor, pstyle, lcolor, lstyle); } void SciPlotListSetMarkerSize (Widget wi, int idnum, float size) { SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; p = _ListFind(w, idnum); if (p) p->markersize=size; } void SciPlotSetXAutoScale (Widget wi) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; w->plot.XAutoScale = True; } void SciPlotSetXUserScale (Widget wi, double min, double max) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; if (min < max) { w->plot.XAutoScale = False; w->plot.UserMin.x = (real) min; w->plot.UserMax.x = (real) max; } } void SciPlotSetYAutoScale (Widget wi) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; w->plot.YAutoScale = True; } void SciPlotSetYUserScale (Widget wi, double min, double max) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; if (min < max) { w->plot.YAutoScale = False; w->plot.UserMin.y = (real) min; w->plot.UserMax.y = (real) max; } } void SciPlotPrintStatistics (Widget wi) { int i, j; SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; printf("Title=%s\nxlabel=%s\tylabel=%s\n", w->plot.plotTitle, w->plot.xlabel, w->plot.ylabel); printf("ChartType=%d\n", w->plot.ChartType); printf("Degrees=%d\n", w->plot.Degrees); printf("XLog=%d\tYLog=%d\n", w->plot.XLog, w->plot.YLog); printf("XAutoScale=%d\tYAutoScale=%d\n", w->plot.XAutoScale, w->plot.YAutoScale); for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { printf("\nLegend=%s\n", p->legend); printf("Styles: point=%d line=%d Color: point=%d line=%d\n", p->PointStyle, p->LineStyle, p->PointColor, p->LineColor); for (j = 0; j < p->number; j++) printf("%f\t%f\n", p->data[j].x, p->data[j].y); printf("\n"); } } } void SciPlotExportData (Widget wi, FILE *fd) { int i, j; SciPlotList *p; SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; fprintf(fd, "Title=\"%s\"\n", w->plot.plotTitle); fprintf(fd, "Xaxis=\"%s\"\n", w->plot.xlabel); fprintf(fd, "Yaxis=\"%s\"\n\n", w->plot.ylabel); for (i = 0; i < w->plot.num_plotlist; i++) { p = w->plot.plotlist + i; if (p->draw) { fprintf(fd, "Line=\"%s\"\n",p->legend); for (j = 0; j < p->number; j++) fprintf(fd, "%e\t%e\n", p->data[j].x, p->data[j].y); fprintf(fd, "\n"); } } } int SciPlotStoreAllocatedColor(Widget wi, Pixel p) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return -1; w = (SciPlotWidget) wi; return ColorStore(w, p); } void SciPlotUpdate (Widget wi) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return; w = (SciPlotWidget) wi; EraseAll(w); #ifdef DEBUG_SCIPLOT SciPlotPrintStatistics(w); #endif ComputeAll(w); DrawAll(w); } Boolean SciPlotQuickUpdate (Widget wi) { SciPlotWidget w; if (!XtIsSciPlot(wi)) return False; w = (SciPlotWidget) wi; return DrawQuick(w); } SciPlot-1.36/SciPlotUtil.c100644 765 144 61137 6213435732 13623 0ustar robusers/* * Copyright (C) 1996 by Rob McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "SciPlot.h" /* Globals */ static int DialogCount=0; /* Number of dialogs on screen */ typedef struct { char *text; int num; } textnumpair; textnumpair colors_list[] = { {"blue", 0}, {"red", 0}, {"ForestGreen", 0}, {"DarkGoldenrod", 0}, {"orange", 0}, {"magenta", 0}, {"grey", 0}, {"purple", 0}, }; #define NUM_COLORS 8 textnumpair marker_list[] = { {"XtMARKER_SQUARE", XtMARKER_SQUARE}, {"XtMARKER_CIRCLE", XtMARKER_CIRCLE}, {"XtMARKER_UTRIANG ", XtMARKER_UTRIANGLE}, {"XtMARKER_DTRIANG ", XtMARKER_DTRIANGLE}, {"XtMARKER_DIAMOND", XtMARKER_DIAMOND}, {"XtMARKER_HOURGLA ", XtMARKER_HOURGLASS}, {"XtMARKER_BOWTIE", XtMARKER_BOWTIE}, {"XtMARKER_LTRIANG ", XtMARKER_LTRIANGLE}, {"XtMARKER_RTRIANG", XtMARKER_RTRIANGLE}, {"XtMARKER_FCIRCLE ", XtMARKER_FCIRCLE}, {"XtMARKER_FSQUARE", XtMARKER_FSQUARE}, {"XtMARKER_FUTRIAN", XtMARKER_FUTRIANGLE}, {"XtMARKER_FDTRIAN ", XtMARKER_FDTRIANGLE}, {"XtMARKER_FDIAMON ", XtMARKER_FDIAMOND}, {"XtMARKER_FHOURGL", XtMARKER_FHOURGLASS}, {"XtMARKER_FBOWTIE", XtMARKER_FBOWTIE}, {"XtMARKER_FLTRIAN", XtMARKER_FLTRIANGLE}, {"XtMARKER_FRTRIAN", XtMARKER_FRTRIANGLE} }; #define NUM_MARKERS 18 /* String Utilities */ #ifndef TRUE #define TRUE 1 #endif #ifndef FALSE #define FALSE 0 #endif #define MAXFIELD 40 #define STRING_MAX 63 char field[MAXFIELD][STRING_MAX+1]; float ffield[MAXFIELD]; #define PARSE_SEPARATORS ",= \t\n" static void upper(char *str) { int i; char *dest; dest = str; for (i = strlen(str); i > 0; i--) { if (*str != ' ') *dest++ = toupper(*str); str++; } *dest = (char) 0; } static char * strparse(char *str, char *primary) { static int start, len; static char *save; static char quotes[] = "'\""; int skip, i, plen, qlen; char c, *begin; if (primary) { if (str) { save = str; len = strlen(str); start = 0; } if (start >= len) return NULL; plen = strlen(primary); qlen = strlen(quotes); /* find first valid character: */ skip = TRUE; while ((start < len) && (skip)) { c = save[start]; skip = FALSE; for (i = 0; i < plen; i++) { if (c == primary[i]) { skip = TRUE; break; } } if (skip) start++; } if (start >= len) return NULL; begin = &save[start]; /* OK, are pointing to first delimeter */ if (*begin == '\"') { begin++; start++; while (start < len) { c = save[start]; if (c == '\"') { save[start] = '\0'; start++; break; } else if (c == '\0') { break; } start++; } } else { skip = FALSE; while ((start < len) && (!skip)) { c = save[start]; skip = FALSE; for (i = 0; i < plen; i++) if (c == primary[i]) { skip = TRUE; break; } if (skip) { save[start] = '\0'; start++; break; } else start++; } } return begin; } return NULL; } static int sepfield(char *str, int count) { char *ptr, *end; char tmpval[1024]; strcpy(tmpval, str); ptr = strchr(tmpval, '#'); end = tmpval + strlen(tmpval); if (ptr) *ptr = (char) 0; ptr = strparse(tmpval, PARSE_SEPARATORS); while (ptr) { strncpy(field[count], ptr, STRING_MAX - 1); field[count][STRING_MAX - 1] = (char) 0; count++; ptr = strparse((char *) NULL, PARSE_SEPARATORS); } #ifdef DEBUG printf("sepfield: %d\t", count); for (j = 0; j < count; j++) printf("->%s<-", field[j]); printf("\n"); #endif return count; } static void tofloat(int count) { int i; float val; for (i = 0; i < count; i++) { val = (float) atof(field[i]); ffield[i] = val; } for (i = count; i < MAXFIELD; i++) ffield[i] = 0.0; #ifdef DEBUG if (1) { int j; printf("tofloat: (%d)", count); for (j = 0; j < count; j++) printf("->%f<-", ffield[j]); printf("\n"); } #endif } #define isfloat(c) (isdigit(c) || c=='.' || c=='-') #define isfloatany(c) (isdigit(c) || c=='.' || c=='e' || c=='E' || c=='-' || c=='+') static int checkfloat(int loc) { char *c; c = field[loc]; if (*c && (isfloat(*c))) { c++; while (*c) { if (!isfloatany(*c)) return 0; c++; } } else { return 0; } #ifdef DEBUG printf("%s is a float\n", field[loc]); #endif return 1; } static int reads(int fd, char *buf, int num) { int count; count = 0; while (count < num) { if (read(fd, buf, 1) == 1) { count++; if (*buf == '\n') break; buf++; } else if (count > 0) break; else { count = -1; break; } } *buf = '\0'; return count; } /* * Read a line (ended by \n) from the specified file and call sepfield() to * break the line up into fields. */ int getfields(FILE *fd) { int count; static char cmdline[1024]; do { count = reads(fileno(fd), cmdline, 1000); if (count<=0) return -1; count = sepfield(cmdline, 0); } while (count==0); return count; } /* * Utils */ /* Internal structure for each plot dialog */ typedef struct { Widget label1; Widget label2; Widget label3; Widget title; Widget xlabel; Widget ylabel; Widget shell; Widget plot; Widget text; } PlotDialogData; static void QuitCallback(Widget btn, XtPointer client, XtPointer call) { exit(0); } static void DismissCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; XtPopdown(stuff->shell); XtDestroyWidget(stuff->shell); free(stuff); DialogCount--; if (DialogCount == 0) exit(0); } static void LogXCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNxLog, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNxLog, state, NULL); } static void LogYCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNyLog, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNyLog, state, NULL); } static void NumbersXCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNxAxisNumbers, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNxAxisNumbers, state, NULL); } static void NumbersYCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNyAxisNumbers, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNyAxisNumbers, state, NULL); } static void OriginXCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNxOrigin, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNxOrigin, state, NULL); } static void OriginYCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNyOrigin, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNyOrigin, state, NULL); } static void MajorCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNdrawMajor, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNdrawMajor, state, NULL); } static void MinorCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNdrawMinor, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNdrawMinor, state, NULL); } static void LegendCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNshowLegend, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNshowLegend, state, NULL); } static void TitleChangeCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; char *ret; ret=XmTextFieldGetString(btn); XtVaSetValues(stuff->plot, XtNplotTitle, ret, NULL); XtFree(ret); } static void TitleCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNshowTitle, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNshowTitle, state, NULL); #ifdef DEBUG if (1) { char label[256],*txt1,*txt2,*txt3; static int count=0; sprintf(label,"Title #%d",++count); XtVaSetValues(stuff->plot, XtNplotTitle, label, NULL); XtVaGetValues(stuff->plot, XtNplotTitle, &txt1, XtNxLabel, &txt2, XtNyLabel, &txt3, NULL); printf("title=%s\nx label=%s\ny label=%s\n",txt); #endif } static void LabelXChangeCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; char *ret; ret=XmTextFieldGetString(btn); XtVaSetValues(stuff->plot, XtNxLabel, ret, NULL); XtFree(ret); } static void LabelXCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNshowXLabel, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNshowXLabel, state, NULL); #ifdef DEBUG if (1) { char label[256]; static int count=0; sprintf(label,"X Label #%d",++count); XtVaSetValues(stuff->plot, XtNxLabel, label, NULL); } #endif } static void LabelYChangeCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; char *ret; ret=XmTextFieldGetString(btn); XtVaSetValues(stuff->plot, XtNyLabel, ret, NULL); XtFree(ret); } static void LabelYCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; Boolean state; XtVaGetValues(stuff->plot, XtNshowYLabel, &state, NULL); state=!state; XtVaSetValues(stuff->plot, XtNshowYLabel, state, NULL); #ifdef DEBUG if (1) { char label[256]; static int count=0; sprintf(label,"Y Label #%d",++count); XtVaSetValues(stuff->plot, XtNyLabel, label, NULL); } #endif } static void PSCallback(Widget btn, XtPointer client, XtPointer call) { PlotDialogData *stuff = (PlotDialogData *) client; char *filename; #ifdef EXTRA_FANCY char txt[1024],*ptr; ptr=XmTextFieldGetString(stuff->label1); strcpy(txt,ptr); strcat(txt,"\n"); XtFree(ptr); ptr=XmTextFieldGetString(stuff->label2); strcat(txt,ptr); strcat(txt,"\n\n"); XtFree(ptr); ptr=XmTextFieldGetString(stuff->label3); strcat(txt,ptr); strcat(txt,"\n"); XtFree(ptr); filename = XmTextFieldGetString(stuff->text); if (strlen(filename) > 0) SciPlotPSCreateFancy(stuff->plot,filename, TRUE,txt,NULL); XtFree(filename); #else filename = XmTextFieldGetString(stuff->text); if (strlen(filename) > 0) SciPlotPSCreateColor(stuff->plot,filename); XtFree(filename); #endif } /* * Create an plot dialog using Motif widgets */ static PlotDialogData * SciPlotDialogInternal(Widget parent, char *title) { Widget paned, box, topbox, botbox, btn, t1; PlotDialogData *info; char *text; #ifdef EXTRA_FANCY char buf[256]; time_t now; struct tm *t; #endif info = (PlotDialogData *) malloc(sizeof(PlotDialogData)); DialogCount++; text = malloc(strlen(title) + 256); sprintf(text, "Plot #%d: %s ", DialogCount, title); paned=XmCreateFormDialog(parent,text,NULL,0); info->shell=XtParent(paned); XtVaSetValues(paned, XmNdialogStyle,XmDIALOG_MODELESS, XmNnoResize,False, XmNautoUnmanage,False, NULL); topbox = box = XtVaCreateManagedWidget("box", xmRowColumnWidgetClass,paned, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, XmNpacking, XmPACK_COLUMN, XmNnumColumns, 2, XmNorientation, XmVERTICAL, NULL); #ifdef EXTRA_FANCY btn = XtVaCreateManagedWidget("Desc 1:", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("Desc 2:", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("Desc 3:", xmLabelWidgetClass, box, NULL); #endif btn = XtVaCreateManagedWidget("Xlabel:", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("Ylabel:", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("Title:", xmLabelWidgetClass, box, NULL); #ifdef EXTRA_FANCY info->label1 = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, XmNskipAdjust, True, NULL); info->label2 = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, XmNskipAdjust, True, NULL); now=time(NULL); t=localtime(&now); strftime(buf,256,"%c",t); info->label3 = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, XmNvalue, buf, XmNcursorPosition, 100, XmNskipAdjust, True, NULL); #endif info->xlabel = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, NULL); info->ylabel = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, NULL); info->title = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, NULL); XtAddCallback(info->xlabel, XmNactivateCallback, LabelXChangeCallback, (XtPointer) info); XtAddCallback(info->ylabel, XmNactivateCallback, LabelYChangeCallback, (XtPointer) info); XtAddCallback(info->title, XmNactivateCallback, TitleChangeCallback, (XtPointer) info); box = XtVaCreateManagedWidget("box", xmRowColumnWidgetClass,paned, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, XmNorientation, XmHORIZONTAL, XmNpacking, XmPACK_TIGHT, NULL); btn = XtVaCreateManagedWidget("Quit", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, QuitCallback, (XtPointer) NULL); btn = XtVaCreateManagedWidget("Dismiss", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, DismissCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Make Postscript", xmPushButtonWidgetClass, box, NULL); sprintf(text, "plot%d.ps", DialogCount); t1 = XtVaCreateManagedWidget("entry", xmTextFieldWidgetClass, box, XmNwidth, 200, XmNvalue, text, XmNcursorPosition, 100, NULL); info->text = t1; XtAddCallback(btn, XmNactivateCallback, PSCallback, (XtPointer) info); botbox = box = XtVaCreateManagedWidget("box", xmRowColumnWidgetClass,paned, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, box, XmNorientation, XmHORIZONTAL, XmNpacking, XmPACK_TIGHT, NULL); btn = XtVaCreateManagedWidget("Log", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("X", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, LogXCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Y", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, LogYCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Origin", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("X", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, OriginXCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Y", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, OriginYCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Numbers", xmLabelWidgetClass, box, NULL); btn = XtVaCreateManagedWidget("X", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, NumbersXCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Y", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, NumbersYCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Major", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, MajorCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Minor", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, MinorCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Title", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, TitleCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("X Label", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, LabelXCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Y Label", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, LabelYCallback, (XtPointer) info); btn = XtVaCreateManagedWidget("Legend", xmPushButtonWidgetClass, box, NULL); XtAddCallback(btn, XmNactivateCallback, LegendCallback, (XtPointer) info); info->plot = XtVaCreateManagedWidget("plot", sciplotWidgetClass, paned, XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, topbox, XmNbottomAttachment, XmATTACH_WIDGET, XmNbottomWidget, botbox, XtNheight, (XtArgVal) 600, XtNwidth, (XtArgVal) 500, XtNplotTitle, title, /* XtNlabelFont, XtFONT_TIMES|8, */ /* XtNtitleFont, XtFONT_TIMES|8, */ /* XtNtitleMargin, 4, */ /* XtNaxisFont, XtFONT_TIMES|8, */ NULL); free(text); XtManageChild(paned); XtManageChild(info->shell); return info; } static void SciPlotDialogInternalPopup(PlotDialogData *info) { char *x,*y,*t; XtVaGetValues(info->plot, XtNplotTitle, &t, XtNxLabel, &x, XtNyLabel, &y, NULL); XmTextFieldSetString(info->title,t); XmTextFieldSetString(info->xlabel,x); XmTextFieldSetString(info->ylabel,y); XtManageChild(info->shell); } Widget SciPlotDialog(Widget parent, char *title) { PlotDialogData *info; info = SciPlotDialogInternal(parent,title); return info->plot; } void SciPlotDialogPopup(Widget w) { XtManageChild(XtParent(XtParent(w))); } /* * Process a text input stream for plot commands */ void SciPlotReadDataFile(Widget parent, FILE * fd) { int count; PlotDialogData *working; float xlist[10], ylist[10]; int line[256], linecount; Boolean readnext; int num, i; working = NULL; count = getfields(fd); while (count > 0) { if (count > 0) { readnext = True; upper(field[0]); if (strcmp(field[0], "TITLE") == 0 || strcmp(field[0], "NEW") == 0 ) { /* Pop up the last dialog if it exists */ if (working) SciPlotDialogInternalPopup(working); working = SciPlotDialogInternal(parent, field[1]); for (i = 0; i < NUM_COLORS; i++) { colors_list[i].num = SciPlotAllocNamedColor(working->plot, colors_list[i].text); } linecount = 0; } else if (strcmp(field[0], "POLAR") == 0) { Boolean degflag; degflag = True; if (count > 1) { upper(field[1]); if (strncmp(field[1], "RAD", 3) == 0) degflag = False; } XtVaSetValues(working->plot, XtNchartType, XtPOLAR, XtNdegrees, degflag, NULL); } else if (strcmp(field[0], "XAXIS") == 0) { if (working) { if (count > 1) XtVaSetValues(working->plot, XtNxLabel, field[1], NULL); if (count>2) { for (i=2; iplot, XtNxLog, True, NULL); else if (strcmp(field[i], "NOZERO") == 0) XtVaSetValues(working->plot, XtNxOrigin, False, NULL); } } } } else if (strcmp(field[0], "YAXIS") == 0) { if (working) { if (count > 1) XtVaSetValues(working->plot, XtNyLabel, field[1], NULL); if (count>2) { for (i=2; iplot, XtNyLog, True, NULL); else if (strcmp(field[i], "NOZERO") == 0) XtVaSetValues(working->plot, XtNyOrigin, False, NULL); } } } } else if (strcmp(field[0], "LEGEND") == 0) { int colorcount, markercount, linestyle; if (working && count > 1) { if (count >= 4) { XtVaSetValues(working->plot, XtNxLabel, field[2], XtNyLabel, field[3], NULL); } line[0] = SciPlotListCreateFromFloat(working->plot, 0, NULL, NULL, field[1]); do { count = getfields(fd); readnext = False; num = checkfloat(0); if (count > 0 && num) { tofloat(count); xlist[0] = ffield[0]; ylist[0] = ffield[1]; SciPlotListAddFloat(working->plot, line[0], 1, xlist, ylist); } } while (count > 0 && num); colorcount = linecount % NUM_COLORS; markercount = linecount % NUM_MARKERS; linestyle = -1; SciPlotListSetStyle(working->plot, line[0], colors_list[colorcount].num, marker_list[markercount].num, colors_list[colorcount].num, linestyle); linecount++; } } else if (strcmp(field[0], "LINE") == 0) { int colorcount, markercount, linestyle, maxlines; Boolean skip; if (working && count > 1) { for (i = 1; i < count; i++) { line[i] = SciPlotListCreateFromFloat(working->plot, 0, NULL, NULL, field[i]); } maxlines = count; do { count = getfields(fd); readnext = False; num = checkfloat(0); if (strcmp(field[0],"skip")==0) skip=True; else skip=False; if (count > 0 && (num || skip)) { if (skip) { for (i = 1; i < maxlines; i++) { xlist[0] = ylist[0] = SCIPLOT_SKIP_VAL; SciPlotListAddFloat(working->plot, line[i], 1, xlist, ylist); } } else { tofloat(count); xlist[0] = ffield[0]; for (i = 1; i < maxlines; i++) { ylist[0] = ffield[i]; SciPlotListAddFloat(working->plot, line[i], 1, xlist, ylist); } } } } while (count > 0 && (num || skip)); for (i = 1; i < maxlines; i++) { linecount++; colorcount = linecount % NUM_COLORS; markercount = linecount % NUM_MARKERS; linestyle = -1; SciPlotListSetStyle(working->plot, line[i], colors_list[colorcount].num, marker_list[markercount].num, colors_list[colorcount].num, linestyle); /* SciPlotListSetMarkerSize(working->plot, line[i], (float) linecount*4); */ } } } } if (readnext) count = getfields(fd); } if (working) SciPlotDialogInternalPopup(working); } SciPlot-1.36/xyplot.c100644 765 144 3555 6213435732 12727 0ustar robusers/* * Copyright (C) 1996 by Rob McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #include #include #include #include #include #include "SciPlot.h" #include "SciPlotUtil.h" void ArgProcess(Widget parent,int argc, char *argv[]) { int argloc; FILE *fd; if (argc > 1) { argloc = 1; while (argloc <= argc) { fd = fopen(argv[argloc++], "r"); if (fd) { SciPlotReadDataFile(parent, fd); fclose(fd); } } } else { SciPlotReadDataFile(parent, stdin); } } int main(int argc, char *argv[]) { XtAppContext app_con; Widget toplevel, mainw, dummy; toplevel = XtAppInitialize(&app_con, "SciPlot", NULL, 0, &argc, argv, NULL, NULL, 0); mainw=XmCreateMainWindow(toplevel,"dummy",NULL,0); dummy=XmCreatePushButton(mainw,"dummy",NULL,0); XtSetMappedWhenManaged(toplevel, False); XtSetMappedWhenManaged(mainw, False); XtManageChild(mainw); XtManageChild(dummy); XtRealizeWidget(toplevel); ArgProcess(mainw,argc,argv); XtAppMainLoop(app_con); return 0; } SciPlot-1.36/realtime.c100644 765 144 4306 6213435732 13165 0ustar robusers/* * Copyright (C) 1995 by Rob McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #include #include #include #include #include "SciPlot.h" #include "SciPlotUtil.h" XtAppContext app_con; int line; float xdata[10]; float ydata[10]; /* ARGSUSED */ static void Update(XtPointer client_data, XtIntervalId * idp) { Widget plot = (Widget) client_data; int index; index=rand()%10; if (index>0) ydata[index]+=1.0; SciPlotListUpdateFromFloat(plot, line, 10, xdata, ydata); if (SciPlotQuickUpdate(plot)) { SciPlotUpdate(plot); } XtAppAddTimeOut(app_con,500,Update,plot); } int main(int argc, char *argv[]) { Widget toplevel, dummy, plot; int i; toplevel = XtAppInitialize(&app_con, "SciPlot", NULL, 0, &argc, argv, NULL, NULL, 0); dummy = XtVaCreateManagedWidget("dummy", coreWidgetClass, toplevel, XtNwidth,10, XtNheight,10, NULL); XtSetMappedWhenManaged(toplevel, False); plot=SciPlotDialog(toplevel,"Real Time Test"); for (i=0; i<10; i++) { xdata[i]=i+1.0; ydata[i]=i/2.0; } line = SciPlotListCreateFromFloat(plot, 10, xdata, ydata, "race"); XtRealizeWidget(toplevel); SciPlotUpdate(plot); srand((unsigned int) getpid()); /* Initialize it with a fairly random seed */ XtAppAddTimeOut(app_con,500,Update,plot); XtAppMainLoop(app_con); return 0; } SciPlot-1.36/SciPlot.h100644 765 144 13645 6213435732 12773 0ustar robusers/*---------------------------------------------------------------------------- * SciPlot A generalized plotting widget * * Copyright (c) 1996 Robert W. McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #ifndef _SCIPLOT_H #define _SCIPLOT_H #ifdef __cplusplus extern "C" { #endif #include #define _SCIPLOT_WIDGET_VERSION 1.36 #ifndef XtIsSciPlot #define XtIsSciPlot(w) XtIsSubclass((Widget)w, sciplotWidgetClass) #endif #include #include /* NOTE: float.h is required by POSIX */ #define SCIPLOT_SKIP_VAL (-FLT_MAX) typedef float real; typedef struct { real x,y; } realpair; #define XtNchartType "chartType" #define XtNdegrees "degrees" #define XtNdefaultMarkerSize "defaultMarkerSize" #define XtNdrawMajor "drawMajor" #define XtNdrawMajorTics "drawMajorTics" #define XtNdrawMinor "drawMinor" #define XtNdrawMinorTics "drawMinorTics" #define XtNxAutoScale "xAutoScale" #define XtNyAutoScale "yAutoScale" #define XtNxAxisNumbers "xAxisNumbers" #define XtNyAxisNumbers "yAxisNumbers" #define XtNxLog "xLog" #define XtNyLog "yLog" #define XtNxOrigin "xOrigin" #define XtNyOrigin "yOrigin" #define XtNxLabel "xLabel" #define XtNyLabel "yLabel" #define XtNplotTitle "plotTitle" #define XtNmargin "margin" #define XtNmonochrome "monochrome" #define XtNtitleMargin "titleMargin" #define XtNshowLegend "showLegend" #define XtNshowTitle "showTitle" #define XtNshowXLabel "showXLabel" #define XtNshowYLabel "showYLabel" #define XtNlegendLineSize "legendLineSize" #define XtNlegendMargin "legendMargin" #define XtNlegendThroughPlot "legendThroughPlot" #define XtNtitleFont "titleFont" #define XtNlabelFont "labelFont" #define XtNaxisFont "axisFont" #define XtNyNumbersHorizontal "yNumbersHorizontal" #define XtPOLAR 0 #define XtCARTESIAN 1 #define XtMARKER_NONE 0 #define XtMARKER_CIRCLE 1 #define XtMARKER_SQUARE 2 #define XtMARKER_UTRIANGLE 3 #define XtMARKER_DTRIANGLE 4 #define XtMARKER_LTRIANGLE 5 #define XtMARKER_RTRIANGLE 6 #define XtMARKER_DIAMOND 7 #define XtMARKER_HOURGLASS 8 #define XtMARKER_BOWTIE 9 #define XtMARKER_FCIRCLE 10 #define XtMARKER_FSQUARE 11 #define XtMARKER_FUTRIANGLE 12 #define XtMARKER_FDTRIANGLE 13 #define XtMARKER_FLTRIANGLE 14 #define XtMARKER_FRTRIANGLE 15 #define XtMARKER_FDIAMOND 16 #define XtMARKER_FHOURGLASS 17 #define XtMARKER_FBOWTIE 18 #define XtMARKER_DOT 19 #define XtFONT_SIZE_MASK 0xff #define XtFONT_SIZE_DEFAULT 12 #define XtFONT_NAME_MASK 0xf00 #define XtFONT_TIMES 0x000 #define XtFONT_COURIER 0x100 #define XtFONT_HELVETICA 0x200 #define XtFONT_LUCIDA 0x300 #define XtFONT_LUCIDASANS 0x400 #define XtFONT_NCSCHOOLBOOK 0x500 #define XtFONT_NAME_DEFAULT XtFONT_TIMES #define XtFONT_ATTRIBUTE_MASK 0xf000 #define XtFONT_BOLD 0x1000 #define XtFONT_ITALIC 0x2000 #define XtFONT_BOLD_ITALIC 0x3000 #define XtFONT_ATTRIBUTE_DEFAULT 0 #define XtLINE_NONE 0 #define XtLINE_SOLID 1 #define XtLINE_DOTTED 2 #define XtLINE_WIDEDOT 3 #define XtLINE_USERDASH 4 extern WidgetClass sciplotWidgetClass; typedef struct _SciPlotClassRec *SciPlotWidgetClass; typedef struct _SciPlotRec *SciPlotWidget; /* ** Public function declarations */ /* Old compatibility functions */ #define SciPlotListCreateFromFloat SciPlotListCreateFloat #define SciPlotListUpdateFromFloat SciPlotListUpdateFloat #define SciPlotListCreateFromDouble SciPlotListCreateDouble #define SciPlotListUpdateFromDouble SciPlotListUpdateDouble #if __STDC__ || defined(__cplusplus) #define P_(s) s #else #define P_(s) () #endif /* SciPlot.c */ Boolean SciPlotPSCreate P_((Widget wi, char *filename)); Boolean SciPlotPSCreateColor P_((Widget wi, char *filename)); int SciPlotAllocNamedColor P_((Widget wi, char *name)); int SciPlotAllocRGBColor P_((Widget wi, int r, int g, int b)); void SciPlotSetBackgroundColor P_((Widget wi, int color)); void SciPlotSetForegroundColor P_((Widget wi, int color)); void SciPlotListDelete P_((Widget wi, int idnum)); int SciPlotListCreateFromData P_((Widget wi, int num, real *xlist, real *ylist, char *legend, int pcolor, int pstyle, int lcolor, int lstyle)); int SciPlotListCreateFloat P_((Widget wi, int num, float *xlist, float *ylist, char *legend)); void SciPlotListUpdateFloat P_((Widget wi, int idnum, int num, float *xlist, float *ylist)); void SciPlotListAddFloat P_((Widget wi, int idnum, int num, float *xlist, float *ylist)); int SciPlotListCreateDouble P_((Widget wi, int num, double *xlist, double *ylist, char *legend)); void SciPlotListUpdateDouble P_((Widget wi, int idnum, int num, double *xlist, double *ylist)); void SciPlotListAddDouble P_((Widget wi, int idnum, int num, double *xlist, double *ylist)); void SciPlotListSetStyle P_((Widget wi, int idnum, int pcolor, int pstyle, int lcolor, int lstyle)); void SciPlotListSetMarkerSize P_((Widget wi, int idnum, float size)); void SciPlotSetXAutoScale P_((Widget wi)); void SciPlotSetXUserScale P_((Widget wi, double min, double max)); void SciPlotSetYAutoScale P_((Widget wi)); void SciPlotSetYUserScale P_((Widget wi, double min, double max)); void SciPlotPrintStatistics P_((Widget wi)); void SciPlotExportData P_((Widget wi, FILE *fd)); void SciPlotUpdate P_((Widget wi)); Boolean SciPlotQuickUpdate P_((Widget wi)); #undef P_ #ifdef __cplusplus }; #endif #endif /* _SCIPLOT_H */ SciPlot-1.36/SciPlotP.h100644 765 144 12457 6213435732 13113 0ustar robusers/*---------------------------------------------------------------------------- * SciPlot A generalized plotting widget * * Copyright (c) 1996 Robert W. McMullen * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * * * Author: Rob McMullen * http://www.ae.utexas.edu/~rwmcm */ #ifndef _SCIPLOTP_H #define _SCIPLOTP_H #ifdef __cplusplus extern "C" { #endif #include #ifdef MOTIF #if XmVersion == 1001 #include #else #include #endif #endif #ifdef __sgi #include #include #endif /* __sgi */ #include "SciPlot.h" #include #define powi(a,i) (real)pow(a,(double)((int)i)) #define NUMPLOTLINEALLOC 5 #define NUMPLOTDATAEXTRA 25 #define NUMPLOTITEMALLOC 256 #define NUMPLOTITEMEXTRA 64 #define DEG2RAD (3.1415926535897931160E0/180.0) typedef struct { int dummy; /* keep compiler happy with dummy field */ } SciPlotClassPart; typedef struct _SciPlotClassRec { CoreClassPart core_class; #ifdef MOTIF XmPrimitiveClassPart primitive_class; #endif SciPlotClassPart plot_class; } SciPlotClassRec; extern SciPlotClassRec sciplotClassRec; typedef enum { SciPlotFALSE, SciPlotPoint, SciPlotLine, SciPlotRect, SciPlotFRect, SciPlotCircle, SciPlotFCircle, SciPlotStartTextTypes, SciPlotText, SciPlotVText, SciPlotEndTextTypes, SciPlotPoly, SciPlotFPoly, SciPlotClipRegion, SciPlotClipClear, SciPlotENDOFLIST } SciPlotTypeEnum; typedef enum { SciPlotDrawingAny, SciPlotDrawingAxis, SciPlotDrawingLegend, SciPlotDrawingLine } SciPlotDrawingEnum; typedef struct _SciPlotItem { SciPlotTypeEnum type; SciPlotDrawingEnum drawing_class; union { struct { short color; short style; real x, y; } pt; struct { short color; short style; real x1, y1, x2, y2; } line; struct { short color; short style; real x, y, w, h; } rect; struct { short color; short style; real x, y, r; } circ; struct { short color; short style; short count; real x[4], y[4]; } poly; struct { short color; short style; short font; short length; real x, y; char *text; } text; struct { short color; short style; } any; } kind; short individually_allocated; struct _SciPlotItem *next; } SciPlotItem; typedef struct { int LineStyle; int LineColor; int PointStyle; int PointColor; int number; int allocated; realpair *data; char *legend; real markersize; realpair min, max; Boolean draw, used; } SciPlotList; typedef struct { real Origin; real Size; real Center; real TitlePos; real AxisPos; real LabelPos; real LegendPos; real LegendSize; real DrawOrigin; real DrawSize; real DrawMax; real MajorInc; int MajorNum; int MinorNum; int Precision; } SciPlotAxis; typedef struct { int id; XFontStruct *font; } SciPlotFont; typedef struct { int flag; char *PostScript; char *X11; Boolean PSUsesOblique; Boolean PSUsesRoman; } SciPlotFontDesc; typedef struct { /* Public stuff ... */ char *TransientPlotTitle; char *TransientXLabel; char *TransientYLabel; int Margin; int TitleMargin; int LegendMargin; int LegendLineSize; int MajorTicSize; int DefaultMarkerSize; int ChartType; Boolean ScaleToFit; Boolean Degrees; Boolean XLog; Boolean YLog; Boolean XAutoScale; Boolean YAutoScale; Boolean XAxisNumbers; Boolean YAxisNumbers; Boolean XOrigin; Boolean YOrigin; Boolean DrawMajor; Boolean DrawMinor; Boolean DrawMajorTics; Boolean DrawMinorTics; Boolean ShowLegend; Boolean ShowTitle; Boolean ShowXLabel; Boolean ShowYLabel; Boolean YNumHorz; Boolean LegendThroughPlot; Boolean Monochrome; Font TitleFID; int TitleFont; int LabelFont; int AxisFont; int BackgroundColor; int ForegroundColor; /* Private stuff ... */ char *plotTitle; char *xlabel; char *ylabel; realpair Min, Max; realpair UserMin, UserMax; real PolarScale; SciPlotAxis x, y; int titleFont; int labelFont; int axisFont; GC defaultGC; GC dashGC; Colormap cmap; Pixel *colors; int num_colors; SciPlotFont *fonts; int num_fonts; int alloc_plotlist; int num_plotlist; SciPlotList *plotlist; int alloc_drawlist; int num_drawlist; SciPlotItem *drawlist; SciPlotDrawingEnum current_id; /* id of current item. Used for erasing */ Boolean update; } SciPlotPart; typedef struct _SciPlotRec { CorePart core; #ifdef MOTIF XmPrimitivePart primitive; #endif SciPlotPart plot; } SciPlotRec; #ifdef __cplusplus }; #endif #endif /* _SCIPLOTP_H */ SciPlot-1.36/SciPlotUtil.h100644 765 144 412 6213435732 13555 0ustar robusers#if __STDC__ || defined(__cplusplus) #define P_(s) s #else #define P_(s) () #endif /* SciPlotUtil.c */ Widget SciPlotDialog P_((Widget parent, char *title)); void SciPlotDialogPopup P_((Widget w)); void SciPlotReadDataFile P_((Widget parent, FILE *fd)); #undef P_ SciPlot-1.36/ANNOUNCE100644 765 144 3216 6213435732 12347 0ustar robusersAnnouncement for SciPlot Widget, version 1.3 Robert W. McMullen 20 Feb 1996 An update for SciPlot, my scientific cartesian and polar plotting widget, is now available at ftp://ftp.x.org/contrib/widgets/SciPlot-1.3.tar.gz Improvements in this version include two new demo programs, including one that plots arbitrary x/y data from text file input. Also new in this version are better realtime support, new convenience functions for adding data to existing lists, and available horizontal y axis numbers (to better conform to most scientific plot packages that I have seen). Bug fixes include changes for several log(0) errors on degenerate lists, better min/max determination, and fixes in my postscript generation code. For those who haven't seen the SciPlot widget before, check out my web site at http://www.ae.utexas.edu/~rwmcm/SciPlot.html Here's an overview from the README: The SciPlot Widget is a widget capable of plotting cartesian or polar graphs, including logarithmic axes in cartesian plots. The widget is subclassed directly from the Core widget class, which means that it does not depend upon any other widget set. It may be freely used with Athena, Motif, or the Open Look/Xview widget sets. (There is optional Motif support that causes the widget to be subclassed from XmPrimitive. See the man page.) Features provided in the widget include automatic scaling, legend drawing, axis labeling, PostScript output, multiple plotted lines, color support, user font specification, dashed lines, symbols drawn at points, logarithmic scales on one or both axes in cartesian plots, and degrees or radians as angles in polar plots. SciPlot-1.36/CHANGES100644 765 144 14733 6213435732 12237 0ustar robusersSciPlot Widget 1.36 5 Sep 96 Released to ftp.x.org 4 Sep 96 Color postscript support (Nicolas EERTMANS ) 16 Aug 96 Problems in realtime update mode should be fixed 10 Aug 96 Fixed setting background color (thanks to Carlos Baumann ) 8 Aug 95 Crashing problems in DrawCartesianAxes fixed 1 Aug 96 XtNmonochrome was accidently set to FALSE. Fixed 1.35 9 Jun 96 Released to ftp.x.org 6 Jun 96 Added SCIPLOT_SKIP_VAL to allow broken line segments (thanks to Santeri Paavolainen ) 30 May 96 Added XtNmonochrome 1.34 8 May 96 Released to ftp.x.org 7 May 96 Parameter to control drawing the axis numbers 7 May 96 User selectable marker sizes 1.33: 15 Apr 96 Released to ftp.x.org 15 Apr 96 Finally fixed GC problems that really showed up with LessTif 15 Apr 96 New color function to store a previously allocated color, (thanks to Derrick Bass ) 4 Apr 96 Minor changes to allow it work with LessTif, waiting to release until LessTif 0.5 is ready 1.32: 31 Mar 96 Released to ftp.x.org 31 Mar 96 Finally remembered to put extern "C" in the header files! 1.31: 28 Feb 96 Released to ftp.x.org 27 Feb 96 Removed the XtIsRealized() check in SciPlotUpdate() 26 Feb 96 Fixed a few little typos in documentation 1.30: 20 Feb 96 Released to ftp.x.org 20 Feb 96 Updating documentation 9 Feb 96 Converted demo programs to Motif 7 Feb 96 Horizontal numbers on y axis label 12 Jan 96 Fixed log(0) bug in axis calculations 17 Dec 95 New plot dialog convenience routines in plotutil.c 29 Nov 95 Realtime demo program 25 Nov 95 Quick update routines 11 Nov 95 List routines to add data to existing lists 9 Oct 95 Decided to use the GNU Library General Public Licence 1.21: 24 Sep 95 New demo program that plots data files 19 Sep 95 PS command "unclip" needs a newpath 23 Aug 95 Axis min/max: now check if min and max are equal, and add a bit to the range if necessary 9 Jun 95 Updated documentation--docs are now HTML 1.20: 11 May 95 Released to ftp.x.org 1.12: 23 Feb 95 Added public function to remove a List. (Oops, forgot that.) (thanks to Mike Kienenberger ) 13 Feb 95 Convenience functions now check for sciplotWidgetClass 1.11: 9 Feb 95 Text labels: wouldn't update Y label or plot title (thanks to John Moyer ) 7 Feb 95 Log Y axis: forgot to update the AdjustDimensions() 31 Jan 95 Added foreground/background color references & functions 27 Jan 95 Changed reference of XtNcartesian to XtNchartType in anticipation of adding other types of plots 26 Jan 95 Log axes: used incorrect precision when max was < 1 Log data: wouldn't draw lines when both axes were log Added a few "static void"s to function declarations 1.10: 20 Jan 95 Released to ftp.x.org 1.03: 16 Jan 95 Merged the files demo-athena.c and demo-motif.c into demo.c 10 Jan 95 User defined axis range added 9 Jan 95 Major axis labeling: occasionally too many decimal places showing 5 Jan 95 Axis drawing: printed extra minor axis lines when the major axis increment was small (<1) 1.02: 19 Dec 94 Fixed some malloc/free problems (thanks to Walter Underwood ) 17 Nov 94 Axis labeling: not enough decimal places showing when major axis increment was small (<1) 1.01: 17 Nov 94 Changed some ANSI string definitions to K&R C (thanks to Todd Smith ) 9 Nov 94 Vertical text: allocating an additional slot in drawlist. 3 Nov 94 Log min/max calculations: it wouldn't set the minimum if the first value was less than 0. 1.00: 26 Oct 94 Released to comp.sources.x and ftp.x.org 0.30: 26 Oct 94 Fixed the Destroy procedure Fixed the allocation problems for the drawitem structure 25 Oct 94 Final checks before release. 19 Oct 94 Version 1.00 documentation. 5 Oct 94 Fixed the major axis precision problem in the new axis labeling 4 Oct 94 Fixed log plots so that negative numbers don't bomb the plot-- 3 Oct 94 Changed the major/minor axis subdivision algorithm the negative numbers just aren't plotted. 30 Sep 94 Changed the way fonts are referenced. Again. The new method for selecting fonts involves logical or-ing of keywords, rather than standard X11 notation. 22 Sep 94 Added a "fancy" postscript option that adds border drawing and annotation at the top of the page (unsupported at the moment. Still work to do.) 0.20: 19 Sep 94 Demo release. 16 Sep 94 Added (Encapsulated) PostScript output 10 Sep 94 Fixed AdjustDimensions when origin was not at zero--axis numbers ran off of the screen 7 Sep 94 Fixed labels--local copies weren't saved 30 Aug 94 Removed the PaperWidget subclass; all the functionality is duplicated in the main Plot widget source now. This saves some space, since one fewer widget class is being initialized. Changed name to SciPlot. 26 Aug 94 Corrected some spacing problems, and added PlotAdjustDimensions to make sure that any text doesn't go off the page. 25 Aug 94 Added vertical text 23 Aug 94 Tic marks for major and minor axes 19 Aug 94 Added labeling for Y axis using vertical text Added axis labeling Changed fonts in Paper to be referenced by XFontStruct rather than Font, so metrics will be available for vtext. Fixed region problem in Paper.Redisplay Fixed problem in cartesian axis drawing 0.11: 18 Aug 94 Demo release. Fixed memory leak in PaperErase Fixed the XtLINE_NONE and XtMARKER_NONE problems First draft of documentation finished 0.10: 15 Aug 94 Demo release. 12 Aug 94 Added labeling of axes (polar only). Cartesian is still way behind polar. 10 Aug 94 Fixed problems with legend, does the spacing correctly now. 8 Aug 94 Added legend 5 Aug 94 Fixed problems with updating lines of data 2 Aug 94 Added color 15 Jul 94 Demo release. 11 Jul 94 Major and minor axis gridlines 8 Jul 94 Range calculations for borders and gridlines 6 Jul 94 Added log and polar plotting 28 Jun 94 PlotDrawAll & support functions. Finally plotted a graph! 23 Jun 94 Different PlotLine set routines depending on data types 22 Jun 94 dumb memory allocation scheme, but saves tons of little mallocs in place of less frequent, but larger, mallocs 20 Jun 94 Figured out resource definitions & how to use 'em 16 Jun 94 PlotLine structure 9 Jun 94 Still mostly waiting on Paper widget 7 Jun 94 test program PlotT.c 2 Jun 94 rewrote basic widget code (ended up removing most of it in favor of the superclass stuff from the Paper widget) 31 May 94 rwmcm Created SciPlot-1.36/LICENSE100600 765 144 61263 6213435732 12241 0ustar robusers GNU LIBRARY GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1991 Free Software Foundation, Inc. 675 Mass Ave, Cambridge, MA 02139, USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. [This is the first released version of the library GPL. It is numbered 2 because it goes with version 2 of the ordinary GPL.] Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public Licenses are intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This license, the Library General Public License, applies to some specially designated Free Software Foundation software, and to any other libraries whose authors decide to use it. You can use it for your libraries, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the library, or if you modify it. For example, if you distribute copies of the library, whether gratis or for a fee, you must give the recipients all the rights that we gave you. You must make sure that they, too, receive or can get the source code. If you link a program with the library, you must provide complete object files to the recipients so that they can relink them with the library, after making changes to the library and recompiling it. And you must show them these terms so they know their rights. Our method of protecting your rights has two steps: (1) copyright the library, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the library. Also, for each distributor's protection, we want to make certain that everyone understands that there is no warranty for this free library. If the library is modified by someone else and passed on, we want its recipients to know that what they have is not the original version, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that companies distributing free software will individually obtain patent licenses, thus in effect transforming the program into proprietary software. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. Most GNU software, including some libraries, is covered by the ordinary GNU General Public License, which was designed for utility programs. This license, the GNU Library General Public License, applies to certain designated libraries. This license is quite different from the ordinary one; be sure to read it in full, and don't assume that anything in it is the same as in the ordinary license. The reason we have a separate public license for some libraries is that they blur the distinction we usually make between modifying or adding to a program and simply using it. Linking a program with a library, without changing the library, is in some sense simply using the library, and is analogous to running a utility program or application program. However, in a textual and legal sense, the linked executable is a combined work, a derivative of the original library, and the ordinary General Public License treats it as such. Because of this blurred distinction, using the ordinary General Public License for libraries did not effectively promote software sharing, because most developers did not use the libraries. We concluded that weaker conditions might promote sharing better. However, unrestricted linking of non-free programs would deprive the users of those programs of all benefit from the free status of the libraries themselves. This Library General Public License is intended to permit developers of non-free programs to use free libraries, while preserving your freedom as a user of such programs to change the free libraries that are incorporated in them. (We have not seen how to achieve this as regards changes in header files, but we have achieved it as regards changes in the actual functions of the Library.) The hope is that this will lead to faster development of free libraries. The precise terms and conditions for copying, distribution and modification follow. Pay close attention to the difference between a "work based on the library" and a "work that uses the library". The former contains code derived from the library, while the latter only works together with the library. Note that it is possible for a library to be covered by the ordinary General Public License rather than by this special one. GNU LIBRARY GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License Agreement applies to any software library which contains a notice placed by the copyright holder or other authorized party saying it may be distributed under the terms of this Library General Public License (also called "this License"). Each licensee is addressed as "you". A "library" means a collection of software functions and/or data prepared so as to be conveniently linked with application programs (which use some of those functions and data) to form executables. The "Library", below, refers to any such software library or work which has been distributed under these terms. A "work based on the Library" means either the Library or any derivative work under copyright law: that is to say, a work containing the Library or a portion of it, either verbatim or with modifications and/or translated straightforwardly into another language. (Hereinafter, translation is included without limitation in the term "modification".) "Source code" for a work means the preferred form of the work for making modifications to it. For a library, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the library. Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running a program using the Library is not restricted, and output from such a program is covered only if its contents constitute a work based on the Library (independent of the use of the Library in a tool for writing it). Whether that is true depends on what the Library does and what the program that uses the Library does. 1. You may copy and distribute verbatim copies of the Library's complete source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and distribute a copy of this License along with the Library. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Library or any portion of it, thus forming a work based on the Library, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) The modified work must itself be a software library. b) You must cause the files modified to carry prominent notices stating that you changed the files and the date of any change. c) You must cause the whole of the work to be licensed at no charge to all third parties under the terms of this License. d) If a facility in the modified Library refers to a function or a table of data to be supplied by an application program that uses the facility, other than as an argument passed when the facility is invoked, then you must make a good faith effort to ensure that, in the event an application does not supply such function or table, the facility still operates, and performs whatever part of its purpose remains meaningful. (For example, a function in a library to compute square roots has a purpose that is entirely well-defined independent of the application. Therefore, Subsection 2d requires that any application-supplied function or table used by this function must be optional: if the application does not supply it, the square root function must still compute square roots.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Library, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Library, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Library. In addition, mere aggregation of another work not based on the Library with the Library (or with a work based on the Library) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may opt to apply the terms of the ordinary GNU General Public License instead of this License to a given copy of the Library. To do this, you must alter all the notices that refer to this License, so that they refer to the ordinary GNU General Public License, version 2, instead of to this License. (If a newer version than version 2 of the ordinary GNU General Public License has appeared, then you can specify that version instead if you wish.) Do not make any other change in these notices. Once this change is made in a given copy, it is irreversible for that copy, so the ordinary GNU General Public License applies to all subsequent copies and derivative works made from that copy. This option is useful when you wish to copy part of the code of the Library into a program that is not a library. 4. You may copy and distribute the Library (or a portion or derivative of it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange. If distribution of object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place satisfies the requirement to distribute the source code, even though third parties are not compelled to copy the source along with the object code. 5. A program that contains no derivative of any portion of the Library, but is designed to work with the Library by being compiled or linked with it, is called a "work that uses the Library". Such a work, in isolation, is not a derivative work of the Library, and therefore falls outside the scope of this License. However, linking a "work that uses the Library" with the Library creates an executable that is a derivative of the Library (because it contains portions of the Library), rather than a "work that uses the library". The executable is therefore covered by this License. Section 6 states terms for distribution of such executables. When a "work that uses the Library" uses material from a header file that is part of the Library, the object code for the work may be a derivative work of the Library even though the source code is not. Whether this is true is especially significant if the work can be linked without the Library, or if the work is itself a library. The threshold for this to be true is not precisely defined by law. If such an object file uses only numerical parameters, data structure layouts and accessors, and small macros and small inline functions (ten lines or less in length), then the use of the object file is unrestricted, regardless of whether it is legally a derivative work. (Executables containing this object code plus portions of the Library will still fall under Section 6.) Otherwise, if the work is a derivative of the Library, you may distribute the object code for the work under the terms of Section 6. Any executables containing that work also fall under Section 6, whether or not they are linked directly with the Library itself. 6. As an exception to the Sections above, you may also compile or link a "work that uses the Library" with the Library to produce a work containing portions of the Library, and distribute that work under terms of your choice, provided that the terms permit modification of the work for the customer's own use and reverse engineering for debugging such modifications. You must give prominent notice with each copy of the work that the Library is used in it and that the Library and its use are covered by this License. You must supply a copy of this License. If the work during execution displays copyright notices, you must include the copyright notice for the Library among them, as well as a reference directing the user to the copy of this License. Also, you must do one of these things: a) Accompany the work with the complete corresponding machine-readable source code for the Library including whatever changes were used in the work (which must be distributed under Sections 1 and 2 above); and, if the work is an executable linked with the Library, with the complete machine-readable "work that uses the Library", as object code and/or source code, so that the user can modify the Library and then relink to produce a modified executable containing the modified Library. (It is understood that the user who changes the contents of definitions files in the Library will not necessarily be able to recompile the application to use the modified definitions.) b) Accompany the work with a written offer, valid for at least three years, to give the same user the materials specified in Subsection 6a, above, for a charge no more than the cost of performing this distribution. c) If distribution of the work is made by offering access to copy from a designated place, offer equivalent access to copy the above specified materials from the same place. d) Verify that the user has already received a copy of these materials or that you have already sent this user a copy. For an executable, the required form of the "work that uses the Library" must include any data and utility programs needed for reproducing the executable from it. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. It may happen that this requirement contradicts the license restrictions of other proprietary libraries that do not normally accompany the operating system. Such a contradiction means you cannot use both them and the Library together in an executable that you distribute. 7. You may place library facilities that are a work based on the Library side-by-side in a single library together with other library facilities not covered by this License, and distribute such a combined library, provided that the separate distribution of the work based on the Library and of the other library facilities is otherwise permitted, and provided that you do these two things: a) Accompany the combined library with a copy of the same work based on the Library, uncombined with any other library facilities. This must be distributed under the terms of the Sections above. b) Give prominent notice with the combined library of the fact that part of it is a work based on the Library, and explaining where to find the accompanying uncombined form of the same work. 8. You may not copy, modify, sublicense, link with, or distribute the Library except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense, link with, or distribute the Library is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 9. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Library or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Library (or any work based on the Library), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Library or works based on it. 10. Each time you redistribute the Library (or any work based on the Library), the recipient automatically receives a license from the original licensor to copy, distribute, link with or modify the Library subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 11. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Library at all. For example, if a patent license would not permit royalty-free redistribution of the Library by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Library. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply, and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 12. If the distribution and/or use of the Library is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Library under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 13. The Free Software Foundation may publish revised and/or new versions of the Library General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Library specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Library does not specify a license version number, you may choose any version ever published by the Free Software Foundation. 14. If you wish to incorporate parts of the Library into other free programs whose distribution conditions are incompatible with these, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS Appendix: How to Apply These Terms to Your New Libraries If you develop a new library, and you want it to be of the greatest possible use to the public, we recommend making it free software that everyone can redistribute and change. You can do so by permitting redistribution under these terms (or, alternatively, under the terms of the ordinary General Public License). To apply these terms, attach the following notices to the library. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. Also add information on how to contact you by electronic and paper mail. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the library, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the library `Frob' (a library for tweaking knobs) written by James Random Hacker. , 1 April 1990 Ty Coon, President of Vice That's all there is to it! SciPlot-1.36/README100644 765 144 12127 6213435732 12117 0ustar robusersREADME for SciPlot Widget, version 1.3 Robert W. McMullen 20 Feb 1996 OVERVIEW The SciPlot Widget is a widget capable of plotting cartesian or polar graphs, including logarithmic axes in cartesian plots. The widget is subclassed directly from the Core widget class, which means that it does not depend upon any other widget set. It may be freely used with Athena, Motif, or the Open Look/Xview widget sets. (There is optional Motif support that causes the widget to be subclassed from XmPrimitive. See the man page.) Features provided in the widget include automatic scaling, legend drawing, axis labeling, PostScript output, multiple plotted lines, color support, user font specification, dashed lines, symbols drawn at points, logarithmic scales on one or both axes in cartesian plots, and degrees or radians as angles in polar plots. SOURCE LOCATION Source code for the SciPlot Widget is available via anonymous ftp on ftp.x.org in /contrib/widgets as SciPlot-?.?.tar.gz. I have also set up the Offical SciPlot Web Site (tm) at http://www.ae.utexas.edu/~rwmcm/SciPlot.html that should always include the latest patchlevel update. REQUIREMENTS The SciPlot code requires X11R4 or later and a C compiler. The code was designed using ANSI C, but compiles fine with a non-ANSI compiler as long as the compiler understands new-style function prototypes. DEMO PROGRAMS Shipped with the source code distribution are two demo programs that show some of the features of the SciPlot widget. NOTE! The demo programs require Motif, but the SciPlot widget itself does not. The demo programs will build with LessTif version 0.4 or later! The program "sciplot" uses x/y data from a text file and pops up a plot on the screen. The other program "realtime" shows the new quick updating feature of the widget, making the widget better suited for realtime display purposes. If you have the program imake installed, you may use the supplied Imakefile to generate a Makefile. Otherwise, copy the file Makefile.noImake to Makefile, and edit that to conform to your system. Actually, other than specifying the C compiler to use, the Makefile should require little customization. To generate the Makefile, type: xmkmf To compile both demo programs, type: make See the HTML documentation for more information on using the demo programs, but a quick start for each of the programs would be: sciplot data.txt realtime USING THE WIDGET Instructions on how to use the SciPlot widget in your own code is documented in the manual page (SciPlot.man) included with the source code. The documentation is now provided in HTML format, and the manual page is generated from the HTML code. IMPROVEMENTS/PATCHES/BUG REPORTS If you make improvements in this widget (or, YIKES!, if you find bugs) please let me know at rwmcm@orion.ae.utexas.edu, or through the SciPlot Widget home page at http://www.ae.utexas.edu/~rwmcm/SciPlot.html ADVERTISEMENT FOR THE LESSTIF PROJECT I decided to use the Motif toolkit for the demo programs for two reasons. First, most of the requests that I get (for all my widgets) are "how do you use this with Motif?", so I decided to help all the Motif users out by supplying these more complete demos. And second, (plug, plug) I am now a core team member of the LessTif project. Although Lesstif cannot quite deal with the complicated demo programs at the time of this writing, it is quickly developing. Check the site http://www.hungry.com/products/lesstif/ for more information. AUTHOR Robert W. McMullen See the copyright notice for licensing restrictions. Note that the GNU _LIBRARY_ General Public Licesce is not the same as the standard GPL. Patches, improvements, suggestions, and bug reports are welcome at the above e-mail address. I will periodically post patches and improvements to ftp.x.org and the SciPlot web page at http://www.ae.utexas.edu/~rwmcm/SciPlot.html THANKS Thanks to the following people for providing fixes and suggestions: Todd Smith Walter Underwood Michael Katzmann John Moyer Mike Kienenberger Glenn Golden COPYRIGHT Copyright (c) 1996 Robert W. McMullen Portions of the SciPlot Widget source code, as marked, are: Copyright (c) 1993 Alan Richardson (mppa3@syma.sussex.ac.uk) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. SciPlot-1.36/Makefile.noImake100644 765 144 3405 6213435732 14240 0ustar robusers# Makefile for widget demo programs MOTIFLIBS = -lXm -lXmu -lXt -lX11 -lm CFLAGS = $(DEFINES) $(CDEBUGFLAGS) CDEBUGFLAGS = DEFINES = RM = rm -f WIDGET = SciPlot PROGRAMS = sciplot realtime TARFILE = sciplot SRCS = SciPlot.c plotutil.c reader.c strutil.c xyplot.c realtime.c HDRS = SciPlot.h SciPlotP.h plotutil.h reader.h strutil.h OBJS = $(SRCS:.c=.o) PLOTSRCS = SciPlot.c plotutil.c reader.c strutil.c xyplot.c PLOTOBJS= $(PLOTSRCS:.c=.o) RTSRCS = SciPlot.c plotutil.c reader.c strutil.c realtime.c RTOBJS= $(RTSRCS:.c=.o) DOCS = SciPlot. SciPlotProg. SciPlotDemo. HOBJS = $(DOCS:.=.html) HSRCS = $(DOCS:.=.hdoc) INFOFILES = CHANGES LICENSE README Makefile.noImake Imakefile data.txt MANPAGES = $(INFOFILES) $(HOBJS) *.gif VERSION = $(SRCS) $(HDRS) $(MANPAGES) TARFILES = $(VERSION) $(HSRCS) ########################################################################## # Definitions for generating the documentation HDOC = /usr/local/bin/hdoc .SUFFIXES: .html .hdoc .hdoc.html: $(HDOC) $*.hdoc > $*.html ########################################################################## # Definitions for building the program all:: sciplot realtime sciplot: $(PLOTOBJS) $(RM) $@ $(CC) -o $@ $(PLOTOBJS) $(LDOPTIONS) $(MOTIFLIBS) realtime: $(RTOBJS) $(RM) $@ $(CC) -o $@ $(RTOBJS) $(LDOPTIONS) $(MOTIFLIBS) doc: $(HOBJS) $(HDOC) @echo "Updated html." clean:: $(RM) $(PROGRAMS) $(OBJS) version: -@STUFF=../$(WIDGET)-`fgrep _WIDGET_VERSION $(WIDGET).h|cut -f2`;\ echo Making version directory $$STUFF ;\ mkdir $$STUFF ;\ cp $(VERSION) $$STUFF ;\ ls -l $$STUFF tar: rm -f $(TARFILE).tar $(TARFILE).tar.gz tar cfv $(TARFILE).tar $(TARFILES) gzip $(TARFILE).tar taz: $(SRCS) rm -f $(TARFILE).tar $(TARFILE).tar.gz tar cfv $(TARFILE).tar $(TARFILES) compress $(TARFILE).tar SciPlot-1.36/Imakefile100644 765 144 4177 6213435732 13036 0ustar robusersXCOMM Imakefile for widget demo programs #ifdef LinuxArchitecture CC = gcc EXTRA_DEFINES = -g -Wall CDEBUGFLAGS = -m486 LESSTIF = -L/home/rob/src/lesstif/libXm HDOC = ~/public_html/hdoc #endif #ifdef AIXArchitecture CC = c89 EXTRA_DEFINES = -g CDEBUGFLAGS = HDOC = hdoc #endif #ifdef AlphaArchitecture CC = cc -std1 #endif MOTIF = $(LESSTIF) -lXm MOTIFDEPS = $(DEPXMLIB) $(DEPXMULIB) $(DEPXTOOLLIB) $(DEPXLIB) MOTIFLIBS = $(MOTIF) $(XMULIB) $(XTOOLLIB) $(XLIB) SYS_LIBRARIES = -lm CDEBUGFLAGS = WIDGET = SciPlot PROGRAMS = sciplot realtime TARFILE = sciplot SRCS = SciPlot.c SciPlotUtil.c xyplot.c realtime.c HDRS = SciPlot.h SciPlotP.h SciPlotUtil.h OBJS = $(SRCS:.c=.o) PLOTSRCS = SciPlot.c SciPlotUtil.c xyplot.c PLOTOBJS= $(PLOTSRCS:.c=.o) RTSRCS = SciPlot.c SciPlotUtil.c realtime.c RTOBJS= $(RTSRCS:.c=.o) DOCS = SciPlot. SciPlotProg. SciPlotDemo. gpl. HOBJS = $(DOCS:.=.html) HSRCS = $(DOCS:.=.hdoc) INFOFILES = ANNOUNCE CHANGES LICENSE README Makefile.noImake Imakefile data.txt MANPAGES = $(INFOFILES) $(HOBJS) *.gif VERSION = $(SRCS) $(HDRS) $(MANPAGES) TARFILES = $(VERSION) $(HSRCS) XCOMM ########################################################################## XCOMM Definitions for generating the documentation .SUFFIXES: .html .hdoc .hdoc.html: $(HDOC) $*.hdoc > $*.html AllTarget(sciplot realtime) NormalProgramTarget(sciplot,$(PLOTOBJS),$(MOTIFDEPS),$(MOTIFLIBS),$(SYS_LIBRARIES)) NormalProgramTarget(realtime,$(RTOBJS),$(MOTIFDEPS),$(MOTIFLIBS),$(SYS_LIBRARIES)) doc: $(HOBJS) $(HDOC) @echo "Updated html." version: -@STUFF=../$(WIDGET)-`fgrep _WIDGET_VERSION $(WIDGET).h|cut -f2`;\ echo Making version directory $$STUFF ;\ mkdir $$STUFF ;\ cp $(VERSION) $$STUFF ;\ ls -l $$STUFF tar: rm -f $(TARFILE).tar $(TARFILE).tar.gz tar cfv $(TARFILE).tar $(TARFILES) gzip $(TARFILE).tar taz: $(SRCS) rm -f $(TARFILE).tar $(TARFILE).tar.gz tar cfv $(TARFILE).tar $(TARFILES) compress $(TARFILE).tar # Dependencies: SciPlot.o: SciPlot.c SciPlotP.h SciPlot.h SciPlotUtil.o: SciPlotUtil.c SciPlotUtil.h xyplot.o: xyplot.c SciPlot.h SciPlotUtil.h realtime.o: realtime.c SciPlot.h SciPlotUtil.h SciPlot-1.36/data.txt100644 765 144 7541 6213435732 12675 0ustar robusersTitle="Crack Growth Comparison at 25% Strain" Xaxis="Number of Cycles (kc)" Yaxis="Crack Depth (mm)" Line="unsoftened" 3.000000e+00 2.000000e+00 Title="Crack Growth Comparison at 25% Strain" Xaxis="Number of Cycles (kc)" Yaxis="Crack Depth (mm)" Line="unsoftened" 0.000000e+00 2.000000e+00 1.373497e+02 2.500000e+00 2.403780e+02 3.000000e+00 skip 3.205736e+02 3.500000e+00 3.845680e+02 4.000000e+00 4.365218e+02 4.500000e+00 4.792050e+02 5.000000e+00 skip 5.145610e+02 5.500000e+00 5.440084e+02 6.000000e+00 5.678155e+02 6.482125e+00 5.686255e+02 6.500000e+00 skip 5.861321e+02 6.918559e+00 5.892577e+02 7.000000e+00 6.020328e+02 7.360654e+00 6.065587e+02 7.500000e+00 Line="softened" 0.000000e+00 2.000000e+00 1.873274e+02 2.500000e+00 3.278449e+02 3.000000e+00 4.372214e+02 3.500000e+00 5.245015e+02 4.000000e+00 5.953596e+02 4.500000e+00 6.535739e+02 5.000000e+00 7.017950e+02 5.500000e+00 7.419573e+02 6.000000e+00 7.744271e+02 6.482125e+00 7.755319e+02 6.500000e+00 7.994085e+02 6.918559e+00 8.036714e+02 7.000000e+00 8.210949e+02 7.360654e+00 8.272678e+02 7.500000e+00 Title="Crack Growth Comparison at 50% Strain" Xaxis="Number of Cycles (kc)" Yaxis="Crack Depth (mm)" Line="unsoftened" 0.000000e+00 2.000000e+00 3.480081e+01 2.500000e+00 6.082956e+01 3.000000e+00 8.105608e+01 3.500000e+00 9.719518e+01 4.000000e+00 1.079825e+02 4.500000e+00 1.144609e+02 5.000000e+00 1.184539e+02 5.500000e+00 1.209611e+02 6.000000e+00 1.225410e+02 6.494318e+00 1.225566e+02 6.500000e+00 1.236403e+02 6.938282e+00 1.237773e+02 7.000000e+00 1.245500e+02 7.384887e+00 1.247575e+02 7.500000e+00 Line="softened" 0.000000e+00 2.000000e+00 4.746434e+01 2.500000e+00 8.296438e+01 3.000000e+00 1.105509e+02 3.500000e+00 1.325626e+02 4.000000e+00 1.504614e+02 4.500000e+00 1.651466e+02 5.000000e+00 1.741982e+02 5.500000e+00 1.798813e+02 6.000000e+00 1.834628e+02 6.494318e+00 1.834960e+02 6.500000e+00 1.855860e+02 6.938282e+00 1.858238e+02 7.000000e+00 1.870383e+02 7.384887e+00 1.873521e+02 7.500000e+00 Title="Crack Growth Comparison at 100% Strain" Xaxis="Number of Cycles (kc)" Yaxis="Crack Depth (mm)" Line="unsoftened" 0.000000e+00 2.000000e+00 4.212263e+00 2.500000e+00 6.219232e+00 3.000000e+00 7.458972e+00 3.500000e+00 8.387889e+00 4.000000e+00 9.101457e+00 4.500000e+00 9.659459e+00 5.000000e+00 1.010172e+01 5.500000e+00 1.045566e+01 6.000000e+00 1.074067e+01 6.500000e+00 1.095434e+01 6.959177e+00 1.097151e+01 7.000000e+00 1.112607e+01 7.404449e+00 1.115906e+01 7.500000e+00 Line="softened" 0.000000e+00 2.000000e+00 9.549826e+00 2.500000e+00 1.409970e+01 3.000000e+00 1.649731e+01 3.500000e+00 1.790146e+01 4.000000e+00 1.898008e+01 4.500000e+00 1.982355e+01 5.000000e+00 2.049207e+01 5.500000e+00 2.102708e+01 6.000000e+00 2.145790e+01 6.500000e+00 2.178088e+01 6.959177e+00 2.180682e+01 7.000000e+00 2.204046e+01 7.404449e+00 2.209032e+01 7.500000e+00 Title="Crack Growth Comparison at 150% Strain" Xaxis="Number of Cycles (kc)" Yaxis="Crack Depth (mm)" Line="unsoftened" 0.000000e+00 2.000000e+00 7.620261e-01 2.500000e+00 1.290091e+00 3.000000e+00 1.674518e+00 3.500000e+00 1.964217e+00 4.000000e+00 2.188153e+00 4.500000e+00 2.364415e+00 5.000000e+00 2.505074e+00 5.500000e+00 2.618451e+00 6.000000e+00 2.710395e+00 6.500000e+00 Line="softened" 0.000000e+00 2.000000e+00 1.152451e+00 2.500000e+00 1.950908e+00 3.000000e+00 2.532138e+00 3.500000e+00 2.970129e+00 4.000000e+00 3.308686e+00 4.500000e+00 3.575165e+00 5.000000e+00 3.787814e+00 5.500000e+00 3.959218e+00 6.000000e+00 4.098217e+00 6.500000e+00 4.205807e+00 6.972220e+00 4.211545e+00 7.000000e+00 4.290039e+00 7.416742e+00 SciPlot-1.36/SciPlot.html100644 765 144 17566 6213435732 13516 0ustar robusersSciPlot Widget Web Page

SciPlot Widget

A full-featured Xt widget to display 2D data in a graph. It is intended to display scientific data, and can format the data in polar or cartesian plots (log axes available for cartesian plots).


Works with LessTif!

The SciPlot demo programs can now be built with LessTif


Current Version

The current version is 1.36. Source is available at ftp.x.org.

Note my new licencing policy -- the GNU Library General Public Licence. This is not the standard GPL; it is a less restrictive version. Read this for more info and background on why I moved to this licence.


Screen Shots

A few images showing the format and capabilities of the SciPlot widget.


Overview

The SciPlot Widget is a widget capable of plotting cartesian or polar graphs, including logarithmic axes in cartesian plots. The widget is subclassed directly from the Core widget class, which means that it does not depend upon any other widget set. It may be freely used with Athena, Motif, or the Open Look/Xview widget sets. (There is optional Motif support that causes the widget to be subclassed from XmPrimitive. See the Programmer's Reference for more information.)

Features provided in the widget include automatic scaling, legend drawing, axis labeling, PostScript output, multiple plotted lines, color support, user font specification, dashed lines, symbols drawn at points, logarithmic scales on one or both axes in cartesian plots, and degrees or radians as angles in polar plots.


Features

Features provided in the widget include the following:

  • Cartesian or Polar plots
  • Automatic or manual axis scales
  • Logarithmic scales for cartesian plot
  • Degrees or radians for polar angles
  • Axis labeling
  • Legend drawing
  • Multiple lines per plot
  • Noncontinuous (broken) line segments
  • Various symbols and line styles
  • Color support
  • User font selection
  • PostScript (EPS) output in color or black & white
  • Real time updates
  • Vertical or horizontal y axis label numbers

See the demo program information page for compilation instructions and sample programs.


Requirements

The SciPlot code requires X11R5 or later and a C compiler. The code was designed using ANSI C, but compiles fine with a non-ANSI compiler if the compiler can understand new-style function definitions. The demo programs also require Motif 1.2 or later.


History

This code was originally developed on an IBM RS/6000 running AIX 3.2.4 and X11R5. Currently, it is maintained on a Linux machine running kernel 1.3.* and XFree86 3.1.2 (X11R6). It is regularly tested by myself on an IBM RS/6000 running AIX 4.1 and a DEC Alpha/AXP running Digital UNIX (formarly OSF/1) 3.2 with X11R5. I have had reports of the widget running successfully on many machines, including SGI, HP, Sun, Dec Ultrix, and even a Dec OpenVMS machine.

The vertical text drawing routine is based on the "fill stippled" idea that I first saw in the code xvertext-5.0 by Alan Richardson <mppa3@syma.sussex.ac.uk>.

The first X11 plotting widget that I saw was the libXG package written by Sundar Narasimhan <sundar@ai.mit.edu>. The libXG plotting widget Graph is based on a much more general widget called Display, which provides device independent 2D (and 3D) graphics.

My attempts to change the Graph widget to do what I liked it to do led me to start from scratch and write this SciPlot widget. I didn't need (or want) to include the sort of functionality present in the Display widget, so I wrote the SciPlot widget as a self-contained widget that uses printer points as the basis of the graphics. Nevertheless, some of the techniques that I used are similar to those found in the Graph widget, so Sundar Narasimhan does deserve mention for the excellent libXG package.


Author's Note

This widget is supplied as freeware, in the hope that it will be useful for developers in the X community. If you do use this widget, I do request that you include mention of the SciPlot widget in the documentation. Also, remember to include a copy of the entire copyright and permission notice! Thanks.

Patches, improvements, suggestions, bug reports, job offers, volleyball games, and money you love donating to programmers who make your life so much easier are welcome at <rwmcm@orion.ae.utexas.edu>. I will periodically post patches and improvements to ftp.x.org and the SciPlot web page at http://www.ae.utexas.edu/~rwmcm/SciPlot.html


Thanks

Thanks to the following people for providing fixes and suggestions:

  • Todd Smith <mtsmith@vision1.engr.utk.edu>
  • Walter Underwood <wunder@msd.hpl.hp.com>
  • Michael Katzmann <michael%vk2bea@secondsource.com>
  • John Moyer <jrm@questconsult.com>
  • Mike Kienenberger <FXMLK@aurora.alaska.edu>
  • Glenn Golden <gdg@big.att.com>
  • <SATCHELL%CCF.dnet@hermes.dra.hmg.gb>
  • Derrick Bass <derrick@frank.harvard.edu>
  • Santeri Paavolainen <santtu@bank.cs.hut.fi>
  • Nicolas EERTMANS <ne@spirou.eatchip.eurocontrol.be>
  • Carlos Baumann <carlosb@ticam.utexas.edu>


Copyright

Copyright (c) 1996 Robert W. McMullen

Portions of the SciPlot Widget source code, as marked, are Copyright (c) 1993 Alan Richardson <mppa3@syma.sussex.ac.uk>

This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details.

You should have received a copy of the GNU Library General Public License along with this library; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


SciPlot : Programmer's Reference | Demo Programs
ListTree : Programmer's Reference

Web Page Design by Rob McMullen
E-mail: rwmcm@mail.ae.utexas.edu
Updated: 4 Sep 96
SciPlot-1.36/SciPlotProg.html100644 765 144 52474 6213435732 14343 0ustar robusersSciPlot Widget Man Page

SciPlot Widget Programmer's Reference


Viewing this document

This programmer's reference for the SciPlot widget uses HTML3 tables, support for which is becoming very common among WWW browsers. Both Netscape and Mosaic (the most common browsers) support tables, and support for tables in Chimera (my browser of choice) will be included in version 2.0.


Usage

To use the SciPlot widget in an application, include the three source code files SciPlot.c, SciPlot.h, and SciPlotP.h with the rest of the source code for the application. Include the object SciPlot.o in the Makefile rule that compiles the application.

If it is important for the widget to respond to Motif keyboard traversal or any events while in a Motif program, define the keyword "MOTIF" for the C compiler. In a Makefile, a commom place to put this definition is in a variable called "DEFINES". The line in the Makefile would look like this:

DEFINES=-DMOTIF

In source code that uses the SciPlot widget, include the following two header files before references to the plot widget:

#include <X11/Intrinsic.h>
#include "SciPlot.h"

To create the SciPlot widget, use the following code as an example:

plotWidget=XtVaCreateManagedWidget("plot2",
sciplotWidgetClass,parent,
XtNheight, 250,
XtNwidth, 250,
XtNplotTitle, "Demo of Plot Widget",
XtNxLabel, "X Axis (units)",
XtNyLabel, "Y Axis (units)",
XtNchartType, XtPOLAR,
XtNdegrees, True,
NULL);

This example creates a 250x250 polar plot widget as a child of parent, using degrees as the angle measurement unit.

Data is plotted on the graph in groups called lists. Each list consists of a group of coordinates that will be connected together by a drawn line, and share the same point style, point color, line style, line color and legend label. Data is added to the widget using convenience functions only. There is no current provision to add data via the argument list.

An example using one of the convenience functions is given below:

double rlist[]={14.,18.,22.,26.,SCIPLOT_SKIP_VAL,30.,34.,38.,42.};
double tlist[]={30.,60.,90.,120.,SCIPLOT_SKIP_VAL,150.,180.,270.,355.};
int line1;

line1=SciPlotListCreateFromDouble(plotWidget,
9,rlist,tlist,
"List 1");

The variable line1 is the identifier of the list that will be needed to modify the list by the other convenience functions that operate on lists.

This example adds a list to be plotted in plotWidget. If plotWidget was created using the call to XtVaCreateManagedWidget above, the line would be added to a polar plot, where the angles in tlist would be interpreted as degrees.

Note that this example includes the new feature of skipping over a blank space in the line. There will not be a line segment connecting the point (26,120) to (30,150).

There are other convenience functions to specify colors and styles of the points and lines drawn in the Plot widget, as well as functions to pick the colors used and others to update previously defined lists. See Public Functions below for descriptions of all of the convenience functions.


Color

The SciPlot widget fully supports color on displays which also support color. By default, two colors are allocated at creation time: black for the foreground, and white for the background. For the SciPlot widget to use any other color, one of the color convenience functions must be used to allocate a color in the global colormap.

Colors are indicated by an integer returned from the color allocation convenience functions. The two default colors occupy the first two spaces in the color table, where the default background (white) is number 0, and the default foreground (black) is number 1.


Fonts

Fonts used by the SciPlot widget are referenced using special notation. This non-standard notation was used to be able to easily convert between PostScript and X11 notation, and as a result, only a subset of the fonts that are available in both X11 and PostScript are available.

Fonts are referenced by using predefined keywords to indicate the typeface, style, and point size. Each keyword is an integer value defined in SciPlot.h, and a complete font definition is created by logically or-ing keywords together.

Supported fonts and styles are listed below:
Font NameDescription
XtFONT_TIMESTimes
XtFONT_COURIERCourier (monospaced font)
XtFONT_HELVETICAHelvetica
XtFONT_LUCIDALucida
XtFONT_LUCIDASANSLucida Sans Serif
XtFONT_NCSCHOOLBOOKNew Century Schoolbook
Style NameDescription
XtFONT_BOLDBold
XtFONT_ITALICItalic
XtFONT_BOLD_ITALICBold and Italic

A font is specified by logically or-ing together these keywords, plus the size in points.

Some examples follow:

12 point Times, bold:
XtFONT_TIMES|XtFONT_BOLD|12
10 point Courier:
XtFONT_COURIER|10
16 point Lucida, bold and italic:
XtFONT_LUCIDA|XtFONT_BOLD_ITALIC|16

Note that XtFONT_BOLD_ITALIC is simply shorthand for XtFONT_BOLD|XtFONT_ITALIC


Point Styles

The SciPlot widget is capable of drawing markers at each data point. There are 19 predefined point marker definitions:
Style NameDescription
XtMARKER_NONEno point marker drawn
XtMARKER_CIRCLEopen circle
XtMARKER_SQUAREsquare
XtMARKER_UTRIANGLEtriangle (pointing up)
XtMARKER_DTRIANGLEtriangle (pointing down)
XtMARKER_LTRIANGLEtriangle (pointing left)
XtMARKER_RTRIANGLEtriangle (pointing right)
XtMARKER_DIAMONDdiamond
XtMARKER_HOURGLASShourglass shape
XtMARKER_BOWTIEbowtie shape
XtMARKER_FCIRCLEfilled variants of the above...
XtMARKER_FSQUARE
XtMARKER_FUTRIANGLE
XtMARKER_FDTRIANGLE
XtMARKER_FLTRIANGLE
XtMARKER_FRTRIANGLE
XtMARKER_FDIAMOND
XtMARKER_FHOURGLASS
XtMARKER_FBOWTIE


Line Styles

For each list in the SciPlot widget, one of the following styles may be used to draw the lines that connect each point in the list:
Style NameDescription
XtLINE_NONEno line (only points drawn)
XtLINE_SOLIDsolid line (the default)
XtLINE_DOTTEDdotted line
XtLINE_WIDEDOTwidely spaced dotted line


Postscript Output

Encapsulated PostScript (EPS) files of the plot displayed in the SciPlot widget may be generated. These files are suitable for printing or importing into documents that can handle the EPS format. Color is ignored when creating the EPS files, however.


New Resources

Resources for the SciPlot widget are documented below, also showing the default values.
NameClassTypeDefault
XtNaxisFontXtCSciPlotFontintXtFONT_TIMES|10
XtNchartTypeXtCMarginintXtCARTESIAN
XtNdegreesXtCBooleanBooleanTrue
XtNdefaultMarkerSizeXtCIntint3
XtNdrawMajorXtCBooleanBooleanTrue
XtNdrawMajorTicsXtCBooleanBooleanTrue
XtNdrawMinorXtCBooleanBooleanTrue
XtNdrawMinorTicsXtCBooleanBooleanTrue
XtNlabelFontXtCSciPlotFontintXtFONT_TIMES|18
XtNlegendLineSizeXtCMarginint16
XtNlegendMarginXtCMarginint3
XtNmarginXtCMarginint5
XtNmonochromeXtCBooleanBooleanFalse
XtNplotTitleXtCStringString"Plot"
XtNshowLegendXtCBooleanBooleanTrue
XtNshowTitleXtCBooleanBooleanTrue
XtNshowXLabelXtCBooleanBooleanTrue
XtNshowYLabelXtCBooleanBooleanTrue
XtNtitleFontXtCSciPlotFontintXtFONT_HELVETICA|24
XtNtitleMarginXtCMarginint8
XtNxAxisNumbersXtCBooleanBooleanTrue
XtNyAxisNumbersXtCBooleanBooleanTrue
XtNxLabelXtCStringString"X Axis"
XtNyLabelXtCStringString"Y Axis"
XtNxLogXtCBooleanBooleanFalse
XtNyLogXtCBooleanBooleanFalse
XtNyNumbersHorizontalXtCBooleanBooleanTrue
XtNxOriginXtCBooleanBooleanFalse
XtNyOriginXtCBooleanBooleanFalse

XtNchartType
Specifies a the type of chart to be drawn. Currently, two types are available: XtCARTESIAN = cartesian (X-Y) plot, XtPOLAR = polar plot.

XtNdegrees
Sets the type of angular unit measurement: True=degrees, False=radians.

XtNdefaultMarkerSize
Size of the point style markers in pixels.

XtNdrawMajor
Controls the display of major gridlines.

XtNdrawMajorTics
Controls the display of major tic marks on the axes.

XtNdrawMinor
Controls the display of minor gridlines.

XtNdrawMinorTics
Controls the display of minor tic marks on the axes.

XtNlabelFont
Names the font for use on the axis labels, as well as the numbers that mark the scale for each axis.

XtNlegendLineSize
The length (in pixels) of the small lines used to show the line style and color in the legend box.

XtNlegendMargin
Sets the border margin (in pixels) between the legend box outline and anything contained in it. Also controls the spacing between the line sample and the text, and the vertical spacing between legend entries.

XtNmargin
The spacing (in pixels) of the plot with the border of the widget.

XtNmonochrome
Ignores any colors specified in any lists, and draws only in the foreground and background colors of the widget.

XtNplotTitle
This is the title of the plot that is drawn along the lower border of the widget.

XtNshowLegend
If True, the legend block is drawn.

XtNshowTitle
If True, the plot title is drawn.

XtNshowXLabel
If True, the X axis (or the polar axis) label is drawn.

XtNshowYLabel
If True, the Y axis label is drawn.

XtNtitleFont
This font is used for the title of the plot.

XtNtitleMargin
Spacing (in pixels) between the plot and the title.

XtNxLabel
XtNyLabel
(Cartesian only.)
Sets the label for each axis.

XtNxAxisNumbers
XtNyAxisNumbers
(Cartesian only.)
Controls whether the axis numbers are displayed for the corresponding axis. XtNxAxisNumbers also controls the display of the radial numbers in a polar plot.

XtNxLog
XtNyLog
(Cartesian only.)
Controls the logarithmic scales of the X and Y axes. If either of the resources is set to True, the corresponding axis will display in logarithmic units. Note that log axes cannot display numbers less than or equal to zero, so only points with values on that axis greater than zero will be plotted.

XtNyNumbersHorizontal
(Cartesian only.)
If True, then the y axis numbers will be drawn horizontally, somewhat decreasing the area available for showing the plot, but more like a standard scientific plot.


Public Functions

The SciPlot widget uses an abstracted type "real" for its internal representation of floating point values. By default, it is typedeffed to float. Some of the convenience functions may depend on this real data type, but in general, separate functions will be provided depending upon a data type of float or double.

Note that any changes to the widget are not reflected until a call to the public function SciPlotUpdate(). This includes any of the functions that add or remove lists, or change plot styles. Any changes accomplished through XtVaSetValues, however, automatically updates the widget.

  • Refresh Functions

    void SciPlotUpdate(w)
    Widget w;
    This function simply causes a recalculation of all internal parameters, and redraws the plot. Call this function after adding, deleting, or changing lists to force the Widget to redraw itself.

    Boolean SciPlotQuickUpdate(w)
    Widget w;
    This is an alternate function to redraw the widget. It is provided mainly as a tool to use the SciPlot as a realtime display, because it does not clear the entire widget. Some flicker may still appear, but only in the graph region. The static areas (labels and legend) will not flicker.

    This function does not adjust the axis ranges, unlike SciPlotUpdate(). It returns a boolean that indicates if all points are within the current axis ranges.

    
    
    
  • Color Functions

    int SciPlotAllocNamedColor(w,name)
    Widget w;
    char *name;
    Attempts to allocate a color in the widget's colormap by using the standard X color name database.

    Returns a unique integer color ID greater than 1 if successful in allocating the named color. If unsuccessful, it returns a 1, which is the default foreground color black.

    int SciPlotAllocRGBColor(w,r,g,b)
    Widget w;
    int r,g,b;
    Tries to allocate the color named by the r, g, and b parameters. Note that these are integers ranging from 0 to 255, not 0 to 65535 as in X functions.

    As the previous function, it returns a number greater than 1 indicating that it found and allocated the new color. If it returns 1, it could not allocate the color, and returned the value for the default foreground.

    int SciPlotStoreAllocatedColor(w,p)
    Widget w;
    Pixel p;
    Stores the previously allocated color p and returns the SciPlot color index corresponding to this color.

    void SciPlotSetBackgroundColor(w,color)
    Widget w;
    int color;
    Sets the background color of the widget to the color specified. Note that the color ID number is obtained from one of the two functions SciPlotAllocNamedColor or SciPlotAllocRGBColor.

    void SciPlotSetForegroundColor(w,color)
    Widget w;
    int color;
    Sets the default foreground color to the color specified. (See the note about color IDs above.) This color is used as the default for the axis and legend box lines, as well as all of the text that appears in the widget. PostScript output remains in monochrome, however.
    
    
    
  • Data Manipulation Functions

    Remember, you must call SciPlotUpdate() before your changes will be visible in the widget!

    int SciPlotListCreateDouble(w,num,xlist,ylist,legend)
    Widget w;
    int num;
    double *xlist,*ylist;
    char *legend;
    Creates a list from the data given in the arrays xlist and ylist. Both arrays must have num entries. The parameter legend is the name of this list, and is drawn in the legend box. The initial colors (for both the points and the line) are set to black, the initial point style is set to a square, and the initial line style is solid.

    Returns an ID number for the newly created list.

    int SciPlotListCreateFloat(w,num,xlist,ylist,legend)
    Widget w;
    int num;
    float *xlist,*ylist;
    char *legend;
    Same as SciPlotListCreateDouble, except takes arrays of type float.

    int SciPlotListAddDouble(w,list_id,num,xlist,ylist)
    Widget w;
    int list_id,num;
    double *xlist,*ylist;
    Appends the new data contained in the arrays xlist and ylist to the data in the list referenced by list_id. Both xlist and ylist must be arrays of type double, and have num parameters.

    Note that the list to be updated may have been originally created with any of the creation convenience functions, not only with the functions that require type double. It is the type of the new data that matters.

    int SciPlotListAddFloat(w,list_id,num,xlist,ylist)
    Widget w;
    int list_id,num;
    float *xlist,*ylist;
    char *legend;
    Same as SciPlotListAddDouble, but takes arrays of type float.

    void SciPlotListUpdateDouble(w,list_id,num,xlist,ylist)
    Widget w;
    int list_id,num;
    double *xlist,*ylist;
    Replaces the data in the list referenced by list_id with the new data contained in the arrays xlist and ylist. Both xlist and ylist must be arrays of type double, and have num parameters. Note that the list to be updated may have been originally created with any of the creation convenience functions, not only with the functions that require type double.

    void SciPlotListUpdateFloat(w,list_id,num,xlist,ylist)
    Widget w;
    int list_id,num;
    float *xlist,*ylist;
    Same as SciPlotListUpdateDouble, but takes arrays of type float.

    int SciPlotListDelete(w,list_id)
    Widget w;
    int list_id;
    Deletes the list referenced by the ID number list_id.

    void SciPlotListSetStyle(w,list_id,pcolor,pstyle,lcolor,lstyle)
    Widget w;
    int list_id;
    int pstyle,pcolor,lstyle,lcolor;
    Sets the styles of the list with an ID number of list_id. See the sections Color , Point Styles and Line Styles for descriptions of the available options.
    
    
    
  • Graph Control Functions

    Remember, you must call SciPlotUpdate() before your changes will be visible in the widget!

    void SciPlotSetXAutoScale(w)
    Widget w;

    (Cartesian only.)
    Forces the widget to automatically scale the X axis based on the minimum and maximum values determined from all of the lists.

    void SciPlotSetXUserScale(w,min,max)
    Widget w;
    double min,max;

    (Cartesian only, and not in logarithmic mode.)
    Forces the widget to display the X axis range based on the specified minimum and maximum values.

    void SciPlotSetYAutoScale(w)
    Widget w;

    (Cartesian only.)
    Forces the widget to automatically scale the Y axis based on the minimum and maximum values determined from all of the lists.

    void SciPlotSetYUserScale(w,min,max)
    Widget w;
    double min,max;

    (Cartesian only, and not in logarithmic mode.)
    Forces the widget to display the Y axis range based on the specified minimum and maximum values.
    
    
    
  • Hardcopy/Output Functions

    Boolean SciPlotPSCreate(w,filename)
    Widget w;
    char *filename;
    This function generates an Encapsulated PostScript file of the current contents of the plot widget, sized to fit on an entire page. Colors are ignored, producing a PostScript file that is black and white only.

    The filename parameter should include the pathname, if required.

    Returns True indicating that the file was successfully created. Any error in file creation or in the subsequent writes to the file will cause the subroutine to return False.

    Boolean SciPlotPSCreateColor(w,filename)
    Widget w;
    char *filename;
    Similar to SciPlotPSCreate, but creates a color Encapsulated PostScript file instead of black and white.

    void SciPlotExportData(w,fd)
    Widget w;
    FILE *fd;
    Writes to the file (must already by opened) referenced by fd a summary of the state of the SciPlot widget. The columns of data are separated by tab characters, so with minor editing, the file generated should be importable by many commercial graphing programs.


Bugs

The font selection algorithm isn't as robust as it should be when trying to choose a replacement for a font; specifically, when the user requests a font or a size that doesn't exist in the X server.

SciPlot : Programmer's Reference | Demo Programs
ListTree : Programmer's Reference

Web Page Design by Rob McMullen
E-mail: rwmcm@mail.ae.utexas.edu
Updated: 4 Sep 96
SciPlot-1.36/SciPlotDemo.html100644 765 144 11652 6213435732 14311 0ustar robusersSciPlot Widget Demo Program

SciPlot Demo Program


Compilation Instructions

Shipped with the source code distribution are two demo programs that show some of the features of the SciPlot widget. NOTE! The demo programs require Motif, but the SciPlot widget itself does not.

If you have the program imake installed, you may use the supplied Imakefile to generate a Makefile. Otherwise, copy the file Makefile.noImake to Makefile, and edit that to conform to your system. Actually, other than specifying the C compiler to use, the Makefile should require little customization.

To generate the Makefile, type:

xmkmf

To compile both demo programs, type:

make


x/y plotter

The SciPlot Demo program takes a text file (or standard input) as input and plots the data from that file as x/y or polar plots. More than one set of x/y (polar) line data may appear in a single plot frame, and more than one plot frame may be displayed on the screen. As shown in the plot frame controls , many features of the SciPlot widget are available for customization before generating a postscript copy.

Screen Shots

[Picture of demo frame]

Usage

The SciPlot Demo program is made automatically when compiling the SciPlot Widget source code, as shipped. It is called "sciplot" and is executed by typing:

sciplot data.txt

where data.txt is a sciplot input file, described below. Note that sciplot can also read multiple input files on the same command line, or read from standard input.

Input File Format

There are 5 commands that sciplot recognizes in the input file. Optional items are enclosed in [square brackets].

Title [title]
Signifies the start of a new plot, and optionally specifies the title for the plot.
Xaxis [x axis label]
Optional x axis label
Yaxis [y axis label]
Optional y axis label
Polar [rad]
Polar plot flag. If not present, the form is assumed to be a cartesian (x/y) plot.
Line legend-label
Begins a new line of data to be added to the current plot. The values to be added immediately follow this line in the input file; and the program will continue to add lines until another command is reached, or the file ends.

Data is free format, but must be separated by a comma, equal sign, or whitespace. Both the x and y (r and theta) coordinates must appear on the same line of text in the file.

In place of a line of x/y data, the keyword "skip" may be substituted. This causes a break in the current line, which allows lines to contain multiple disjointed line segments.

Any text labels in the file should be enclosed in quotation characters.

Sample Input File

Title="Crack Growth Comparison"
Xaxis="Number of Cycles (kc)"
Yaxis="Crack Depth (mm)"

Line="25% strain"
0.000000e+00    2.000000e+00
1.373497e+02    2.500000e+00
2.403780e+02    3.000000e+00
skip
3.205736e+02    3.500000e+00
3.845680e+02    4.000000e+00

Line="50% strain"
0.000000e+00    2.000000e+00
3.480081e+01    2.500000e+00
6.082956e+01    3.000000e+00
skip
8.105608e+01    3.500000e+00
9.719518e+01    4.000000e+00

Line="100% strain"
0.000000e+00    2.000000e+00
4.212263e+00    2.500000e+00
6.219232e+00    3.000000e+00
7.458972e+00    3.500000e+00
8.387889e+00    4.000000e+00


Realtime Demo

This is just a simple program that uses the realtime updating capabilities of the widget. Instituted in the program is a timed callback (XtAppAddTimeOut) that simply randomly increments one of the points every half second. The plot is redrawn after every update.

Usage

Just execute the program "realtime" to see this demo. It takes no arguments.



SciPlot : Programmer's Reference | Demo Programs
ListTree : Programmer's Reference

Web Page Design by Rob McMullen
E-mail: rwmcm@mail.ae.utexas.edu
Updated: 4 Sep 96
SciPlot-1.36/gpl.html100644 765 144 4352 6213435732 12670 0ustar robusersLicencing Policy

GNU Library General Public Licence

I believe in free software and the idea of not duplicating effort; that's why I have made all of my widgets freeware. In the past, I have used sort of the standard "I disclaim all warranties" copywrite because I have always felt that the GNU General public licence was too restrictive.

For example, a single GPL'd subroutine makes an entire program fall under the GPL. I am also a professional programmer, so the GPL rules out any uses of GPL'd subroutines in commercial applications. While I am obviously not opposed for people being compensated for their work, I don't believe that ancillary subroutines should require an entire (large) program to fall under the GPL.

That is where the GNU Library General Public Licence comes in. It is a less restrictive version of the GPL that among other things allows the use of the GPL'd software in non-free programs. I am changing all of my programs to use the Library GPL, because it also ensures that anyone who makes modifications to my software will also be required to share source code, and thereby give something back to the user community as I have tried to do.

Read the GNU file LICENCE for complete details, but the following is a summary of what I believe the Licence says (but, don't quote me on it):

(Here, "library" refers to the software under the GNU Library GPL.)

  • You can use the library in non-free programs as long as you include the source to the library
  • Source code that is your own, and contains no library code, may be licenced in any manner you wish (including commercial, but you must ship source to the library)
  • Any modifications to the library itself must remain under the Library GPL
  • If your program is a derivative of the library and cannot be separated from the library, than your program must fall under the Library GPL

For all the details, see the GNU Library General Public Licence included with the software distribution.


Web Page Design by Rob McMullen
E-mail: rwmcm@mail.ae.utexas.edu
Updated: 4 Sep 96
SciPlot-1.36/SciPlotDemo.gif100644 765 144 36643 6213435732 14121 0ustar robusersGIF87amr@} ~ QQes29A  GGG%8<+`ޣxwvککککŮsonmmllhhVSSNXwwv>Wkkiaٯxz>5⋙TTO+3HTD}tSTTӢTTISSyoSSSSFXUU=4%\&&x||fDP q0؅JRRު1DRR yNCX dIJfq i\ ijj9Z7dd~c([W[9#mm_,>\\WrWސH<՟nxMȉ?w۹zCT|B F}z; B|AvP:H{굧vw8a #rbyMb bPX5$|9ٞX3&$SubP_&Ia#2x<&lj Z6~9u,&U')df}98^‡gO()>*諉ƺ*uʺh6mĩvZPO#&*rnBZjH-ivXF/Rq⻢m +汷ok^16zB+Y_+w;![l(St-ܳ ks!Kx'#zrzNk"VY<3Xی씉:o܆wQ\Ó&]蕵ID 5CƘϹZ!4-4x~_[{Q:nN~-W`騋|*竳5izǮ[^<'oNW}}Z7fgw?Xއ/oO/o_? HL:'H Z16z .H(L W0" gH8ȡw@ H"HL&:9`g*ZX.z` HF@P6fq H:x̣> IB78#F:!'IJZ̤&7Dr(GIIL*WVғLKIZ6̥.w^r0YE\L2 LYRЌ%9eZ&! J5J.r&d>ϝi?z1':~R0d=)P t~ŧB9Oґh&Z R(FQz4eg;'τ&]JЍvԏ/K)10#N+ўT)AԨDPSҦ9#9*ՌjrN(ѭVէ`cHC>U4kQֵ.թpE)TqPU4+Ei:U 6ūEkؘT|`ջU d8VoԞM+IOzRh*`Kڼ 5E^5Z;_i][Zª6-bQ 6PYRrv<.h[ֹձvnn[iW{kѴW>sMkIw2c[ҷحfme+c[f5f.8pQZ/ov_#X V[ݪ p\Jb .s޷^qw4nRiV&OJcvUy"ۖ_2Ōcg^6G<6ϰ&,Ua9[9"Ƴkxrnc5teOCא6{E[-oHx҇:zRk1%/'UPҦ3ZڕJ[ט^=lc&㲙kgGf-&MrNvMoDwSf6~Npq:w ;wxP[ϸ>q{ wsCN\#?WR0m8_s2@Їs+%җ;70z\cgN}^X.{`AMv=i_Oq'[wtOzL&SY&^yw ycV eHἮ0zHOo^>V9ly9{į7Ju2q=^w%}SM:|ᾘoq?ck~]쏋U94xW09H_AЧ]ebeBZdgg efy\I^E{?7}v'|UfcDVg7v}LhY}+`ׁ4 YcPw`?&d+]A؂\1Wy6H?es{fbi)8d;f}~dcO>w&X }]]Yv؄]7KVwYQ6~i8?W~VV`([*h"Ǥ(MkXfQglz:Xwt8EdLxДy|,H8LXNxGw$_UMȋ.'dHK(ظMXHJטG؍xҶ0Hdu4H9TpxuaH8Yyُ}ِFn9yI?ّّ I$ِ#Y(ٍ't.01Ȓ!$8:\bh8 7xDdHyJɔRiG$S UiY[ɕCb?hDāhH^ɖ(w|i)hV||)S7uzt9Kv9OȕgQzgyUdX_GlNyVe\)UH[%}Yhc{\3XQx]hzzƚVWQ(9ٔ4ٌJ^셔8(bTiЉf׈guez~ hi\hi!6ZY Jhc'!蜆U[mK乛(ig9(s]Rx~:]y$H}.%`!I 3h wY]Eؤ@X(Ɇh8#:h:ekZap$hȦn([*yZh%6f8|V%٘iȧ6zaWzNZ ڧIʩIh~ŃܙivA:u[P 3i6ڧǗzg5h-RYJ(tʺӊ?d K) ?sy(>j^>ʮ-z×Z ;*?Y ۰vGks+YqSq۱ ";Lq(pu'.Kl+-4m[8 r1 3>;e;[=D^AkC?I[LEG!K&ڴT IOkQkJgZ\FWYkJa۵dP7h@dk[Tlm rkdt;x{zȷ{~;|k{uKkGjNgO*6\kD\OV@oDR{E{K Z +D&FOO?OkE-[7tRɛ?ƻ'N+z[O?kYLً5˻,iR0.FQ[p^%>mۿ+v|pȺ;˿l\}&~l|3F\|RyFYܾkCͫ[ /B+kA > \n.eID쇖羺kTվL|M\Nߜ,?[f e"P; c\hmPld>Lә,%XS+a9O= ]NV]pYmz,͆S1 _Me[P= M4@ٟ>KНo[΢yÚ\Ctsk-ՅFMڥm+K̋<ז]M؆+uɍmh!- ;}}^ ƺ<=N\M˳n۹۾l߱?}}3ݘ x߲m*3TE-^^!N֌$^'RJm 6h ێ>5:ⲻ*HP\9-:doY+{zy.{艻GO0o脛@>P) E!l d U~+YT (~OmN뷛ڝA5D~@N-=-;&~OYTԍ ZΊnؾA멮“}y4F.7> ^n?оٿ~jMm/g $/?LM (vMUˆVN @E]><6O/Woi:*,C>ՎQRVO+äcvꌝ[R/T_3+IM?Mho~NM҈: |!_K̄%%]Z_mWloM`_Kn/FoS?统I\FLI{Y=OiPߍ]!@@ DPA @p^XbF=~RH% 02e -]iÈ4)n#N<34N.<C.ȓŤ "jNX%֜Xc͞EvaS\7̉6Εlާ|/[S5h'Y-` WƜ.؈mhZj֥q>]Zvlکgۮnݰq wp(ߍ<7뷭7*\g&ܽooW2%~e cw=l+ۿr? ? 0AoAs0±6c $C2k TD"QCCW$ (r/s }4h{!B"cԈb:*E&_2˟,BR()@32Gb \ DK;$ 8=҄17$IN Dm3ζ}4?,6ՊIHIRt67SGTUSeum5VWeuSaV]suW_{=[EVPXBWguŵf<\ML8ܔIS2/A4mk e+@Lv VV׬|1B7GMWOMa/I/FrI8u+8d;cM>9Ƃ"`_Via[YγRgd֑/UAfCqe]\&.Ci JbEl(&δg^d:;:5ToO]ѳؼIǝu^C?s&[GۏoQy叟7_n{gW3/^Bϖr;u8|Ow#<_giJ=魯= 'x#maػieS]s4@0j'yc\ 'an7! -W`}+8!-&4G6aDlۘĄrT@53w]\c:Ae+`A(zo`xG#\;QLc(-&rAk< ݘ$_$P4E9vz#ɶ4R 5N,)?/V(lCJMc,ˬ2<]*˔Ld9KQ3)ʴLS;+YBp!&5i'18OySH\b>y|s 1=I{laؚKw r$CP5Q6!66 '*u~sAK:M فQ-N%U"әB1+ M5/Z$JҮTQfKt˪3R$1j.S[ /*#d_Z}'WJ*K{*֦[}P;WQ/aPt 'S#JKrp)ϸ$Vڬ_DBp9mYQf,ֳZiX5-hKXjs,fֶВis+Z^NdC3{ʾu%gn6s% e {Be@.f*"Z 1.Y7KiF? ֋Թ_浾5}ۋBK~,u?^u|o W}0Z <_1=VzҥRos%|kQu(FcBeq\ ?r6:X< *Ѐ.errd(re!_cfIw5S% #ٛyd0v oA L;cv=>H=LamaMzwN{ 0Y)a1T?=e^΀]i\}QֻbI\ }GƊQϜ0Eu4+V{{6R;|qo uA)Wu =_/bk3%|vB} Gh7l^!g7Ɯ8#.,a=5@?7$ѿ'C|ζKO.;6+@?Fb;4=jnSڭ2 <|т]A k*.S34;@ T@b@Ӄ8~*%o >#>$L.{@,T¸_>CC2\>74?0 /'4(: "YM)d);.<=%4C,ɐ=t&@+30Fl"4ʊíDC5zk@\1q -"UPOFCQ>$ͫFƂXLQTAv.R"=cRȵW-HѴM-'lL0ϼTt؈lj->UY]5PMX\X CYZ`p;`+XvXueDLZM(Kڨ5NXW2#)~]׽y[$:oZ͜ ds5e\(Wg|X֣ۙ1 A\ŞeC\>CdWK-uMĄVMK\+Dܒu]+\]]VMbImrǥX.p^[e=U\Tp^5E)ߖE5\y= [۸_55X[K45]\uSL]w}:I%`l_]U+Mݵ8>Y&_؃-ZVM@894A6-]M Vb`7~ wb+1.^.a}`"*!06b%UHA/^[ڕM8f*Hq>d:BDD^-FVG>dCv)AG4\2cMcXLvQ)E2-[&XO&[[Z'][FYaYfke>Sd]]rF]m|F茶$kh_g6i=gl V]ifZe;naV```1ݗҋ~E礦~gnggTdedO>g^F VK[~Tfjvk뎆hjݶ~V*jk4f~Ԝn׳nlJWfZ&j^fdj3.hΖfmjeEjm;{i> N1i_鄎뿦&ܔػlfU]inQ6 nil!Fn fbmhm/ΖjvŽmoƾmNgl%&l.6l@ p('uEp. n '7GWqjK«J㭦lkl켾qgi&VkVFGһ}xƟ-wH8,s ܙqSs 7gs7:Wݯ^ s9wP),??CvrxtC_JAtDtKtszt?_tZNIOtQUU ESCt[FTVtȌ'S>xp$̘2gҬ͎uO(Um(ҤJʴȳӊGRjJ,]^RH6$ ,ڏBY-ܸrҭ;rVn/4f5*0Ċ%v*Ȓ'S|c˚7sn:ճsKO<ӳo{=ßo~?9t ~9e`-t V5 =]9)ȗ~ VԅixSM#e"j A%8+e(W},M7ȓK=GL=8cnL(x7B>*dZMŸe]4`R)ߒFyQDi }I!)ՕyF`Tk|&nIh2riֆ"J#eiԦ?BX飚4呎Pt)v(GrJ㡝ʨ8U)u)ZEJekF)*o:㱎f[$z kRk+J쎲mFTϪ솤"k0 7 opӊ(;bְA[힦r^l-m4q:zso\'P}wW^ˬꨏ<锃3G5;8M:uzw\7't<: {fc/K?ߴ"NY'.ޣ{iIbVMKR`-;_3 h뉏sĢ 1ArQx} y68Biy3!VUO"\ ]m{+Lx60ʜ5Ɂ> g5 b1}" }ыAD#B+92-5xiaS'7Ynv#DžErs$ )ر: bJXE=tcߵ [:;މnzεIN\ ]y2cB* V}I`RhA\:$ژHRʻk,1 ; דb-k2 Oasa=|*tN=y 4K-hoЅ2TWm(D#ZJmE/ъ*t'r\$ґ&=)JSҕ.})Lc*әҴ6)NMT;)PӘԠF=*Rz2_i*TkԨ&uT*Vjլr[*W ֱUd=+Uֵ͊VUC Xm֦+q+SZUY:BU!,bjX$m,aV!6xTr٧fVmf RYvIizZvJkZĖeJh';zv],Sx 7!ĽL„^qU [NM/3)q?[" Ewk^#]yR-[nw ^6|;V$/j]OW C=ma"jm/(s%VS <`>qqn3lck sSoVXL_ nnKZŢ屄}?Ty!N1at9At8vS9ź͙k;9srKElCsY_RV@M^2yjY9әs VOyj'}3u@7K>PBi8ڮ/ϻ>q6[9z~6ot-wO8qNwK'/~C#~.O>u78Q.{]yA^z!O}*8Oɼu'S>&;~o'_힗]A<=Ot.͵|[.ũ|;|#z?A _ q1QQ_dxQ⭏[ݳ J9ҧm  i閝 vWD@YWXG8E lWW؇asDXOءxѡ >މ-! M6LoARHbr顱=$reѡ%bD)R)br!%W+V{!|+BR$ "!&D*"+b00&ʢLe-#36q9#4bR(c4BTU3^#6n#7V6v#87c8#9#:#:#7#;5j^9.9>U==#<=#;#@F@AA&dA&d?<DF$EDV$FEf$GOASH^IdH$KK$LƤL$M֤M$NN$Of|HbJUIQ&bR.%S6S>%T DbL`fJ2W~%XX%YY%ZZ%[[ LeOhep%%__%``e\R%'V/]*i`>&dFdNfZ\V'R]*چcR&hhZZfe11vfm|&i&lfd&e~Meel%0op'dئ&&nh&qep>tqJr^bDt=_QyDWN'zkVgd '!"_D`v]g~byetf' &{2{ާx>"Z&ZLyeZhXj.mvͱJ /Yp )-se~e:E_iiiFKpF՝(ۓ*Y[r\6]yJ|(pZz偘)醎鏦)[bD֩.i~EE Z( ^磒)XJB©&J) Y(jmI񒖥ދΪ.b(tVXnaj-'zI隢L$ުip+ofjj"J@C|2ޗJ>ܳB_*k 絖^k5jjzkRjb.,imb& ^*vRݖ:},",+iuK>KYЪg6K- QMΎZjʎi>m² k ~!sZfv$F癶ʦN-Vm`\-bWqt-A-Y-`-e%n-~mBޭޢ'ߚ"FbnFR˖⢫'ĦzƎf.f֥r.Zgfn.EJRnRn&/`._UkV/[2]%C.;no@Ad\///Ư/֯&2ր.y0'/0>dGF|lWw䏝fo0w00 0 0 0 ǰ 0 0+0011'/17?1GEgo1w1qc11DZ1ױ111  2!!q"+ 3 ?2$G$O2%W%_2&g ;r ;SciPlot-1.36/SciPlotExample.gif100644 765 144 13003 6213435732 14611 0ustar robusersGIF89a)q4VA !,)@0I8k[(di._lp-xn@C؂Ȥ9^Ϧt.W8,o#B4#,#01/~w5jul"\]8Q&Nu,f2JAsqZj UTQy(o-h3}wx.̸c°'Xs%oM6a6po+VUf/rD᭢=]tB )  D˗&3K9k* :Ζ'hQ =9F 7d%3օ "BjLbu<ȷp\u[sxmC@ Epݓh]mVinqٲ N=cP~HҮ4a@mٷ@:Vl;HKI9_U&-=0%s\yec#uB} !S8l' ]sf:]qf_Go,!#:b"O(Y: B@_?"U |f@ma@[Cux#!4|YQ^ψN&XXH!uŎ7h夑=Qw /M{5Ψ fVeH If(&g mfdY] PzI|lJ<(b(({ٴ)Fr9i:Fw&M'u7R*eL|DZKlq<})[4Ějpq*.9= a _X7]Xm7 t[IXmpeɋ)Ua-Xde,eYH腣a\"oRDNAYn,Y#"QJ"3IjJ3[6ujz&qD$8X3 PzʘRV3Pjs+Pz*l O I F`̨FG΍ HɑC\B4R .]Sm /r`t:QV7 M_IΝ2&qEl$6,T3LZ L~+ۜ@H1pgRJ!Zh}262 ,0yf):U5 \&7C&x d~]RlSex4n6 >-frUe1;(+üAW*Z$xHT"dI]ly۽Vng[`)օU+(oMmܘ*Vb-*p}[pPEX\/Ja[d'[y>%}6:kYxy FU˭EiG A(P} R\;ƈ'^SVBJRY67D㕋/98-_I(lc$bq{a-Y4V,yI`~*v 86xG:-4c/( GŸ$nGN%) "Ie\B#5]v.Mn>NyӐ!i*P93R X4/aBjDR3hmHTXPVXp^[',ew%yx6AZDv쪍>Һͬ2w|.pwwɏX%5Cg*h@+H483fg͛NޗJW<{d+2*0n#i+ A_Jb>5e#wXX(3<Cr=}:"BAp7kqz83v;:&V>vlOݾ`p]:eO3z% nKZ̀O|K[;GCNqx2=`_S΀fIu&ϖ뚿wΟ7~uKoؿ=!r;w3N҅z|VsM51Q#yRw?utL"iǚWS )oKv{uTw'G#8o0 j~K8$}rIz5$A'v8v!1}"}BA3(8'~yYXƒru~=H4 ׀ȄE]tW{;_X~Cxf}bfxhj~hpr8tXQ~ w~&Ȇ|؇~mp_|wGVDžڡ E+^ȁazBXhp-cyMD؈DŽW}mxwB(Fg|xE5$6Cnnwxt'8˜tQd4XeFPPHN,(Ig⌼X>g\ݘƎB>hEhRGQ!FN*[E'PrZD82Lt@eҏxw$Y븑9M !$my#S-a.a)+4x157Rpf&55L5'uPJ9k0|hU"]:@3 Nq &*fJ]IժvF]us@Ah5Zj1¦6b{Z*"'} ʯ Qf>16,m%_!.֊!DD +sq>H%+z# XJejPZjTD[1m?]{gtR$H\t3zS$kavZՒ;SP |Wi:,bl30ZZ钱;{&`֗eȀ3oA5HG;ltҭ׶f7f$h%Ե pOzV`a[sylCťƛ69kzyz,[E 0n,Hw!Py`"[l ˸M*Gyѵ4A[`3D ęyg3[#w;yJI̚"W9+UMzvI,q@ 3'nu)rR4*Bۿ謓+YWְ4:•ճriv%Ւ#"ed/W§w@PF ZOIArt1d-=Kl.2уS~@Ȱas&<`܇Ҫ+(6b)8\;Qu\st|%j+>3-ji+YyƶŶ*\/ =c={LR{,B~9вUD pv̲z˄,[(%h;*ie@*Og]>N͇^>b< n_./E.?L(*U~̔˴g)_ ;_iQ Ȯ/>O4kÓn %P 8dp0D1?,bU9Vn8K?RU?X/W^^]EI̴x#Bsv,2iO3,\4fAq73.$O'+p`6'ؘyTMa=1WD_!vl u>7lq.TP/_/.9j u-T;SciPlot-1.36/SciPlotTitle.gif100600 765 144 10434 6213435732 14274 0ustar robusersGIF87a\9xQQ@NX,\90I8ͻ`(dihlp,t8n|@C,d`*ШMجvzL.eyn{NCr`Ϸ'U9qBb|q U4y3|}13h>N)*.{&с>=7]cMLM)07dB~k\Z"Jp`Rrŏ C kNH#sa dJ(c&x˚)-$N^Uە PF'IQd-Vih.lGTR-w&$c p+~k7 fӱNZm=n-{7&C53nbTuW\~˹C-VC`ˣ),y7)xw.މF!&饩Rlr؏$506(Й[fNG٨3jyvI:)kAbΆ`#cJUi%h"ʬx m'?fVhXZrʸxR.螫.\"b+/& +,Q潈WIF-pgf bh0YEƆǀγ0 rǦ9 #Or@_ Vpe r6+!1ep.2Q:W1ԚSCͰ=\q#>KԎuq\6j( f3wR|s*yf-AZ.nڝo\b2g$:3]"ϝ vl_Lz1l:yOk#f4YtZ{bJMg X˴S873+w'~Ç:׬:4+㒧;9Gom3l#Rtn&3j"Aj»`pqm7FL_h *N^@|n B:A;] 8pS`>̉8b؀9ALYiHDPUw}J(yzH!`$#C*"pcS] Am}cG;Þ׆fk`d#%Er"IB|~)eT^ʕU$߹ϏaAFR-t E.qAԤI5J>ҫYp:mQԣYIę.p z?k=YD)RW˰t4W XT4-lXRLe]ͪYPrh7ӳP,1`5)g6ͮ @{zpΦ (W6(N:UOy9ѵ.ЪBj[\k*P U2.y_{6loD,UoxZ%@oaZ(!_=C~]K8")(VG8; ӼVv+D.S0F_zW*VN OdS(إ4K|J-ֵb1))'ahNA! k_NUf:ʶZ.SRi~~n/lᘺSR,^ʏom*&I^/6ߕM:k\pOPZd|Utk2 FGڛX. n+F0ff&מ!mAن:j1?fa-m&670̷l:n/kSdQ=7 }$UwT_c#a+%p)ǚ?V Q$5ީ>/4sX&1aJ% &0uIn72 8ZOΤ.Q0,Ǜ`Ϭ[[z#e(Arrɾ&+:ujGC hw٥ݡgυ`}ZA^ӳ:k!v>3!~wez1_y0’n}?~AkӚqUEpFOҧ)W/k~fw=,l~*5{žXw;_w||PhEˮԵGa4 ڨP*e1e*1)1z{TrI!9AuI0)QZ>? szʩB*!Jt2@#Шh/ୈ /(!@کj= ájxJ 9B4%aگcgZ(l*HVxfjOjLZ h6$$K&KXUW@)R.Zj><۳>@B;D[F{3 ۰Pz9SmާY[M MڵFz̹TQ'PJNn9!e@^c$swh=zVx[ȇ&B~L*l{y$Wµ~}[j{۹;[{ۺTrm ~}@0' D;|;$5Aㆤ[uʋQ*0!GQ#?n9*)Cx"d?lٛg* ݫrl+Ql 싑3s9#D>X l˾k ?t <;l%Km'.\ӽn.>+"d(h" bK^46b{W㱡+~;