This is Plot.m in view mode; [Download] [Up]
/* Plot.m by Jonas Karlsson, July 1990 * * Copyright (C) 1991 The Board of Trustees of * The Leland Stanford Junior University. All Rights Reserved. */ #import "Draw.subproj/draw.h" #import "Plot.h" const char Plot_h_rcsid[] = PLOT_H_ID; const char Plot_m_rcsid[] = "$Id: Plot.m,v 2.54.2.5 1994/02/08 20:30:15 rensing Exp $"; #import "HGraphicView.h" #import "HTuple.h" #import <float.h> #define INDEX_VERSION 2 #define INVERTCUT_VERSION 3 #define FUNCLIST_VERSION 4 #define CURRENT_VERSION FUNCLIST_VERSION @implementation Plot static unsigned int plotNum = 0; static NXAtom namePlot() { char buffer[256]; sprintf( buffer, "HippoPlot.%u", plotNum++); return NXUniqueString(buffer); } static void setMarginRect( NXRect *margins, NXRect *bounds, int grid, int topFlag, int leftFlag) { float xOffset=0.0, yOffset=0.0; switch (topFlag) { case 0: /* Top */ yOffset = 0.11 * bounds->size.height; break; case 1: /* Middle */ yOffset = 0.07 * bounds->size.height; break; case 2: /* Bottom */ yOffset = 0.04 * bounds->size.height; break; } switch (leftFlag) { case 0: /* Left */ xOffset = 0.18 * bounds->size.width; break; case 1: /* Middle */ xOffset = 0.11 * bounds->size.width; break; case 2: /* Right */ xOffset = 0.04 * bounds->size.width; break; } NXSetRect (margins, xOffset, yOffset, bounds->size.width * 0.80, bounds->size.height * 0.82); if ( margins->size.width/grid > 3.001 ) { margins->origin.x = bounds->origin.x + MAX( grid*floor( margins->origin.x/grid ), grid ); margins->size.width = grid*floor( margins->size.width/grid ); } else { margins->origin.x += bounds->origin.x; } if ( margins->size.height/grid > 3.001) { margins->origin.y = bounds->origin.y + MAX( grid*floor( margins->origin.y/grid ), grid ); margins->size.height = grid*floor( margins->size.height/grid ); } else { margins->origin.y += bounds->origin.y; } } + initialize { [self setVersion:CURRENT_VERSION]; return self; } - init { NXColor color = NX_COLORCLEAR; [super init ]; uniqueName = namePlot(); graphicView = NULL; hTuple = NULL; disp = NULL; [self setFillColor:&color]; cutHistFlag = NO; return self; } - initPlotWithTuple: (HTuple*)ht Type: (graphtype_t)type { [self init]; disp = h_newDisp(type); [self replaceTupleWith: ht]; return self; } - (const char *)name { return uniqueName; } - setDispType:(graphtype_t *) type { graphtype_t oldtype; oldtype = h_getDispType(disp); if (oldtype == *type) return self; h_setDispType(disp, *type); if ((oldtype == HISTOGRAM) && (*type != HISTOGRAM)) { int i = h_getBinding(disp, XAXIS); int dim = h_getNtDim(h_getNtuple(disp)); i = MIN(i+1, dim-1); if (h_getBinding(disp, YAXIS) < 0) { h_bind(disp, YAXIS, i); } i = MIN(i+1, dim-1); if (h_getBinding(disp, ZAXIS) < 0) { h_bind(disp, ZAXIS, i); } [self NameAxisY:"%y"]; [self NameAxisZ:"%z"]; } switch (*type) { case SCATTERPLOT: h_setDrawType(disp, POINT); break; case LEGOPLOT: disp->doMesh = 1; break; case XYPLOT: case STRIPCHART: h_setDrawType(disp, POINT); break; case HISTOGRAM: h_setDrawType(disp, BOX); [self NameAxisY:"Entries / %dx bin"]; default: break; } return self; } - setGraphicView:anObject { graphicView = anObject; return self; } - graphicView { return graphicView; } - setInspector:(id)anInspector { inspector = anInspector; return self; } - inspector { return inspector; } - setHTuple: ht withDisplay:(display) d1 { NXRect bbox; disp = d1; [self replaceTupleWith:ht]; h_getDrawRect(disp, (rectangle *) &bbox); [self setBounds: &bbox]; return self; } - setRefFlag:(BOOL) flag { h_setNtByRef( disp, flag, NULL ); return self; } - setFitted:(BOOL) flag { isFitted = flag; return self; } - (BOOL)isFitted { return isFitted; } - setFixBinsFlag:(BOOL)flag { fixBinsFlag = flag; h_setFixedBins( disp, fixBinsFlag ); return self; } - setRefFilename:(const char *)filename { if (!filename) return self; /* if filename is not legal, return */ if ( !reffilename ) { NX_ZONEMALLOC( [self zone], reffilename, char, strlen(filename)+1 ); } else { NX_ZONEREALLOC( [self zone], reffilename, char, strlen(filename)+1 ); } strcpy( reffilename, filename ); return self; } - changeRefFileNameIfValid:(const char *)filename { if ( !hTuple ) { return self; } if ( [hTuple isFakeFilename] ) { if ( !reffilename ) { NX_ZONEMALLOC( [self zone], reffilename, char, strlen(filename)+1 ); } else { NX_ZONEREALLOC( [self zone], reffilename, char, strlen(filename)+1 ); } strcpy( reffilename, filename ); [hTuple setFilename:filename]; } return self; } - replaceTupleWith: ht { ntuple tuple; hTuple = ht; tuple = (hTuple != nil) ? [hTuple ntuple] : NULL ; h_bindNtuple(disp, tuple ); if ( !tuple ) return self; [self setRefFilename:[hTuple filename]]; [self setRefFlag:[hTuple isRef]]; ntindex = [hTuple index]; isFitted = NO; return self; } - replace:oldTuple with:newTuple { if ( oldTuple == hTuple ) { [self replaceTupleWith:newTuple]; } return self; } - closeTuple { ntuple tuple; refFlag = [hTuple isRef]; fixBinsFlag = h_getFixedBins(disp); h_setFixedBins(disp, YES); hTuple = nil; tuple = NULL; h_bindNtuple(disp, tuple ); return self; } - bindReference { if ( reffilename == NULL ) return self; if ( !hTuple ) { hTuple = [ graphicView hTupleForFile:reffilename index:ntindex]; } if ( disp == NULL ) return self; [self replaceTupleWith:hTuple]; if ( !hTuple ) return self; h_setFixedBins( disp, fixBinsFlag ); return self; } - hTuple { return hTuple; } - (ntuple) ntuple { return [hTuple ntuple]; } - addHTupleToList:tlist { if ( hTuple ) { [tlist addObjectIfAbsent:hTuple]; } return self; } - addPlotToList:list { [list addObjectIfAbsent:self]; return self; } - (display) histDisplay { return disp; } - setTitle:(char *) title { h_setTitle(disp, title); return self; } - (const char *) title { return h_getTitle( disp ); } - NameAxisX:(const char *)AxisName { h_setAxisLabel(disp, XAXIS, AxisName); return self; } - (const char *) axisLabelX { return h_getAxisLabel(disp, XAXIS ); } - NameAxisY:(const char *)AxisName { h_setAxisLabel(disp, YAXIS, AxisName); return self; } - (const char *) axisLabelY { return h_getAxisLabel(disp, YAXIS ); } - NameAxisZ:(const char *)AxisName { h_setAxisLabel(disp, ZAXIS, AxisName); return self; } - (const char *) axisLabelZ { return h_getAxisLabel(disp, YAXIS ); } - NameAxisW:(const char *)AxisName { h_setAxisLabel(disp, WEIGHT, AxisName); return self; } - NameAxisXE:(const char *)AxisName { h_setAxisLabel(disp, XERROR, AxisName); return self; } - NameAxisYE:(const char *)AxisName { h_setAxisLabel(disp, YERROR, AxisName); return self; } - bindAxisX:(int *)dataDim { if ( [self isCutPlot] ) return self; h_bind(disp, XAXIS, *dataDim ); isFitted = NO; return self; } - bindAxisY:(int *)dataDim { h_bind(disp, YAXIS, *dataDim ); isFitted = NO; return self; } - bindAxisZ:(int *)dataDim { h_bind(disp, ZAXIS, *dataDim ); isFitted = NO; return self; } - bindAxisW:(int *)dataDim { h_bind(disp, WEIGHT, *dataDim ); isFitted = NO; return self; } - bindAxisXE:(int *)dataDim { h_bind(disp, XERROR, *dataDim ); isFitted = NO; return self; } - bindAxisYE:(int *)dataDim { h_bind(disp, YERROR, *dataDim ); isFitted = NO; return self; } - setLogScale:(binding_t *)axis to:(int *)yesOrNo { h_setLogAxis( disp, *axis, *yesOrNo ); return self; } - (BOOL) isLogScaleX { BOOL val; val = h_getLogAxis(disp, XAXIS); return val; } - (BOOL) isLogScaleY { BOOL val; val = h_getLogAxis(disp, YAXIS); return val; } - (BOOL) isLogScaleZ { BOOL val; val = h_getLogAxis(disp, ZAXIS); return val; } - setTitlesFlag:(const int *)yesOrNo { h_setDrawTitles( disp, *yesOrNo); return self; } - (int) titlesFlag { return h_getDrawTitles(disp); } - setAxesFlag:(int *)yesOrNo { h_setDrawAxes( disp, *yesOrNo ); return self; } - (int) axesFlag { return h_getDrawAxes( disp ); } - setAutoScale:(binding_t *)axis to:(const int *)yesOrNo { h_setAutoScale(disp, *axis, *yesOrNo); return self; } - getRangeForAxisX:(NXPoint *)p { h_getRange(disp, XAXIS, &p->x, &p->y ); return self; } - getRangeForAxisY:(NXPoint *)p { h_getRange(disp, YAXIS, &p->x, &p->y ); return self; } - setRange:(binding_t *)axis to:(const NXPoint *)p { h_setRange(disp, *axis, p->x, p->y ); isFitted = NO; return self; } - setRangeAndNbins:(binding_t *)axis to:(const NXPoint *)p { float low, high, width; int nbins; width = h_getBinWidth(disp, *axis); nbins = (p->y - p->x) / width; low = p->x; high = low + nbins * width; h_setRange(disp, *axis, low, high); h_setBinNum(disp, *axis, nbins); isFitted = NO; return self; } - getRangeForAxisZ:(NXPoint *)p { h_getRange(disp, ZAXIS, &p->x, &p->y ); return self; } - getRangeForAxis:(binding_t) axis low:(float *) xl high:(float *) xh { h_getRange(disp, axis, xl, xh ); return self; } - setRangesFrom:plot { display plotdisp; float low, high; graphtype_t plot_t; float plot_w, my_w; if ( plot == self ) return self; plotdisp = [plot histDisplay]; h_getRange(plotdisp, XAXIS, &low, &high ); h_setRange(disp, XAXIS, low, high ); h_getRange(plotdisp, YAXIS, &low, &high ); /* * normalize for histograms only */ plot_t = h_getDispType( plotdisp); if ( h_getDispType(disp) == HISTOGRAM && plot_t == HISTOGRAM ) { plot_w = h_getBinWidth( plotdisp, XAXIS ); my_w = h_getBinWidth(disp, XAXIS); low *= (my_w/plot_w); high *= (my_w/plot_w); } h_setRange(disp, YAXIS, low, high ); isFitted = NO; return self; } - setRangesAndBinsFrom:plot { display plotdisp; float low, high, width; int nbins; graphtype_t plot_t; float plot_w, my_w; if ( plot == self ) return self; plotdisp = [plot histDisplay]; h_getRange(plotdisp, XAXIS, &low, &high ); if ( h_getDispType(disp) == HISTOGRAM) { width = h_getBinWidth(disp, XAXIS); nbins = (high - low) / width; high = low + nbins * width; h_setBinNum(disp, XAXIS, nbins); } h_setRange(disp, XAXIS, low, high); h_getRange(plotdisp, YAXIS, &low, &high ); /* * normalize for histograms only */ plot_t = h_getDispType( plotdisp); if ( h_getDispType(disp) == HISTOGRAM && plot_t == HISTOGRAM ) { plot_w = h_getBinWidth( plotdisp, XAXIS ); my_w = h_getBinWidth(disp, XAXIS); low *= (my_w/plot_w); high *= (my_w/plot_w); } h_setRange(disp, YAXIS, low, high ); isFitted = NO; return self; } - getRangeForAxisY:(NXPoint *)range normalizedTo:plot { display plotdisp; float scale; h_getRange(disp, YAXIS, &range->x, &range->y ); plotdisp = [plot histDisplay]; if ( h_getDispType(disp) != HISTOGRAM || h_getDispType(plotdisp) != HISTOGRAM ) { return self; } scale = h_getBinWidth(plotdisp, XAXIS) / h_getBinWidth(disp, XAXIS); range->x *= scale; range->y *= scale; return self; } - (float)widthForAxis:(binding_t) axis { return h_getBinWidth(disp, axis); } - setNumBins:(binding_t *) axis to:(const int *)n { h_setBinNum( disp, *axis, *n ); h_setAutoScale( disp, *axis, 0 ); isFitted = NO; return self; } - (int)numBinsForAxis:(binding_t) axis { return h_getBinNum(disp, axis); } - setLineStyle:(linestyle_t *) style { h_setLineStyle(disp, *style); return self; } - getLineStyle:(linestyle_t *) style { *style=h_getLineStyle(disp); return self; } - setPlotSym:(plotsymbol_t *) plotsymbol { h_setPlotSym(disp, *plotsymbol); return self; } - getPlotSym:(plotsymbol_t *) plotsymbol { *plotsymbol=h_getPlotSym(disp); return self; } - setSymSize:(float *) plotsymsize { h_setSymSize(disp, *plotsymsize); return self; } - getSymSize:(float *) plotsymsize { *plotsymsize=h_getSymSize(disp); return self; } - setDrawType:(drawtype_t *) type { h_setDrawType(disp, *type); return self; } - getDrawType:(drawtype_t *) type { *type = h_getDrawType(disp); return self; } - setColorType:(const int *)onOff { int i; if ( *onOff ) h_orDrawType(disp, COLOR); else { i = h_getDrawType(disp); i = i & (~COLOR); h_setDrawType(disp, i); } return self; } - setTickLocation: (binding_t *) axis to:(plotloc_t *) loc { h_setTickLocation(disp, *axis, *loc ); return self; } - setScaleLocation: (binding_t *) axis to:(plotloc_t *) loc { h_setScaleLocation(disp, *axis, *loc ); return self; } - setLabelLocation: (binding_t *) axis to:(plotloc_t *) loc { h_setLabelLocation(disp, *axis, *loc ); return self; } - setScaleFontSize: (binding_t *) axis to:(float *) fontSize { h_setScaleFontSize( disp, *axis, *fontSize ); return self; } - setTickLength: (binding_t *) axis to:(float *) len { h_setTickLength( disp, *axis, *len ); return self; } - draw { NXRect margins; int grid, topFlag=0, leftFlag=0; if (bounds.size.width < 1.0 || bounds.size.height < 1.0) return self; if ([self fill]) { PSgsave(); [self setFillColor]; NXRectFill(&bounds); PSgrestore(); } if (!gFlags.nooutline) { [self setLineColor]; } if ( (NXDrawingStatus == NX_PRINTING) && (linewidth < 0.15) ) { PSsetlinewidth(0.15); /* in case going to Linotronic (R) */ } h_setDrawRect (disp, (rectangle *) &bounds ); if ( graphicView && [graphicView gridIsEnabled] ) { grid = [graphicView gridSpacing]; } else { grid = 1; } if (disp->xAxis.flags.labelLocation & PLOTTOP) topFlag += 1; if (disp->xAxis.flags.scaleLocation & PLOTTOP) topFlag += 1; if (disp->yAxis.flags.labelLocation & PLOTRIGHT) leftFlag += 1; if (disp->yAxis.flags.scaleLocation & PLOTRIGHT) leftFlag += 1; setMarginRect(&margins, &bounds, grid, topFlag, leftFlag); h_setMarginRect (disp, (rectangle *) &margins); /* * do shading in case of cut plot. Must do after plotting, since h_plot * sets up margins, autoscales, etc. * h_shade will keep shading inside bounds of plot. */ if ( cutHistFlag && (disp != NULL) && (cutParms.cutFunc != NULL) ) { switch (cutParms.cutCode) { case 0: h_shade(disp, -FLT_MAX, cutParms.cutValue1); break; case 1: h_shade(disp, cutParms.cutValue1, FLT_MAX); break; case 2: h_shade(disp, cutParms.cutValue1, cutParms.cutValue2); break; case 3: h_shade(disp, -FLT_MAX, cutParms.cutValue1); h_shade(disp, cutParms.cutValue2, FLT_MAX); break; } } /* * draw plot last, so shading doesn't cover it. */ h_plot(disp); return self; } - print { h_print(disp); return self; } - setBounds:(const NXRect *)aRect { NXRect margins; int grid, topFlag = 0, leftFlag=0; bounds = *aRect; h_setDrawRect(disp, (rectangle *) &bounds); grid = [graphicView gridSpacing]; if (disp->xAxis.flags.labelLocation & PLOTTOP) topFlag += 1; if (disp->xAxis.flags.scaleLocation & PLOTTOP) topFlag += 1; if (disp->yAxis.flags.labelLocation & PLOTRIGHT) leftFlag += 1; if (disp->yAxis.flags.scaleLocation & PLOTRIGHT) leftFlag += 1; setMarginRect(&margins, &bounds, grid, topFlag, leftFlag); h_setMarginRect (disp, (rectangle *) &margins); return self; } - sizeToNaturalAspectRatio { NXRect defaultBox; [graphicView calcDefaultPlotSize:&defaultBox]; bounds.origin.y += ( NX_HEIGHT(&bounds) - NX_HEIGHT(&defaultBox) ); bounds.size.height = NX_HEIGHT(&defaultBox); bounds.size.width = NX_WIDTH(&defaultBox); [self setBounds:&bounds]; return self; } /* Methods supporting Archiving and de-Archiving */ - write:(NXTypedStream *) ts { cutStorElem *cut; dependStorElem *old; display dlist[] = {NULL, NULL}; char *data; int len, lenref; int i; [super write:ts]; /* change some flags for storage to stream */ if ( hTuple) { refFlag = [hTuple isRef]; } fixBinsFlag = h_getFixedBins(disp); h_setFixedBins(disp, YES); h_setNtByRef(disp, YES, reffilename ); lenref = strlen(reffilename); /* write display to buffer */ len = h_dispSize( disp ); NX_ZONEMALLOC( [self zone], data, char, len ); dlist[0] = disp; if ( h_writeMem( data, len, dlist, NULL ) ) { printf( "Could not write buffer\n" ); return self; } /* restore display in case we are doing copy */ h_setNtByRef( disp, refFlag, NULL ); h_setFixedBins( disp, fixBinsFlag ); /* Now archive Plot object to typed stream */ NXWriteTypes( ts, "ccii", &refFlag, &fixBinsFlag, &len, &lenref ); NXWriteType( ts, "*", &reffilename ); if ( [Plot version] >= INDEX_VERSION ) { NXWriteType( ts, "i", &ntindex ); NXWriteObjectReference(ts, hTuple); } NXWriteArray( ts, "c", len, data ); NXWriteType( ts, "c", &cutHistFlag); if ( cutHistFlag ) { len = strlen( cutParms.cutFunc ); NXWriteType( ts, "i", &len ); NXWriteType( ts, "{*iffi}", &cutParms ); NXWriteType( ts, "i", &cutNumber); } i = [cutPlotStor count]; NXWriteType( ts, "i", &i ); while ( i-- ) { cut = [cutPlotStor elementAt:i]; NXWriteObjectReference(ts, cut->plot ); if ( [Plot version] >= INDEX_VERSION ) { cut->name = [cut->plot name]; NXWriteType( ts, "%", &cut->name ); if ( [Plot version] >= INVERTCUT_VERSION ) { NXWriteType( ts, "c", &cut->invertFlag ); } } } if ( dependStor ) { i = [dependStor count]; } else { i = 0; } NXWriteType( ts, "i", &i); while ( i-- ) { old = [dependStor elementAt:i]; NXWriteObjectReference( ts, old->plot); if ( [Plot version] >= INDEX_VERSION ) { old->name = [old->plot name]; NXWriteType( ts, "%", &old->name ); } } free( data ); if ( [Plot version] >= FUNCLIST_VERSION ) { NXWriteObject( ts, funcList ); } return self; } - read:(NXTypedStream *) ts { cutStorElem cut; dependStorElem new; ntuple *ntlist; display *dlist; char *data; int len, lenref; int i, count; [super read:ts]; uniqueName = namePlot(); NXReadTypes( ts, "ccii", &refFlag, &fixBinsFlag, &len, &lenref); NX_ZONEMALLOC( [self zone], data, char, len ); NXReadType( ts, "*", &reffilename); if ( NXTypedStreamClassVersion(ts, "Plot") >= INDEX_VERSION ) { NXReadType( ts, "i", &ntindex ); hTuple = NXReadObject( ts ); hTuple = nil; /* will bind by reference later */ } else { ntindex = 0; hTuple = nil; } NXReadArray( ts, "c", len, data ); h_readMem( data, len, &dlist, &ntlist ); NX_FREE( data ); disp = dlist[0]; if ( !hTuple ) disp->tuple = NULL; /* shouldn't happen */ NXReadType( ts, "c", &cutHistFlag ); if ( cutHistFlag ) { NXReadType( ts, "i", &len ); NX_ZONEMALLOC( [self zone], cutParms.cutFunc, char, len+1 ); NXReadType( ts, "{*iffi}", &cutParms ); NXReadType( ts, "i", &cutNumber); } NXReadType( ts, "i", &count ); if ( count ) { cutPlotStor = [[Storage allocFromZone:[self zone]] initCount:0 elementSize:sizeof(cutStorElem) description:"@%*"]; } for ( i = 0; i < count; i++ ) { cut.plot = NXReadObject( ts ); if ( NXTypedStreamClassVersion(ts, "Plot") >= INDEX_VERSION ) { NXReadType( ts, "%", &cut.name ); if ( NXTypedStreamClassVersion(ts, "Plot") >= INVERTCUT_VERSION ) { NXReadType( ts, "c", &cut.invertFlag ); } } else { cut.name = NXUniqueString("HippoPlot.NULL" ); cut.invertFlag = FALSE; } if ( cut.plot ) { cut.name = [cut.plot name]; } [cutPlotStor addElement:&cut.plot]; } NXReadType( ts, "i", &count ); if ( count ) { dependStor = [[Storage allocFromZone:[self zone]] initCount:0 elementSize:sizeof(dependStorElem) description:"@%"]; } for ( i = 0; i < count; i++ ) { new.plot = NXReadObject( ts ); if ( NXTypedStreamClassVersion(ts, "Plot") >= INDEX_VERSION ) { NXReadType( ts, "%", &new.name ); } else { new.name = NXUniqueString("HippoPlot.NULL" ); } if ( new.plot ) { new.name = [new.plot name]; } [dependStor addElement:&new]; } if ( NXTypedStreamClassVersion(ts, "Plot") >= FUNCLIST_VERSION ) { funcList = NXReadObject( ts ); } return self; } - free { [self removeAllCuts]; NX_FREE(reffilename); [cutPlotStor free]; NX_FREE(cutParms.cutFunc); /* disp should be attached, but it may not be */ if ( disp != NULL ) h_freeDisp(disp); return [super free]; } - wasRemovedFrom: gv { if (cutHistFlag && [gv isKindOf:[HGraphicView class]]) { [[gv cutList] removeObject: self]; } return [super wasRemovedFrom: gv]; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.