This is Plot.m in view mode; [Download] [Up]
/* Program By Fred Richards, Copyright 1990. */ /* */ /* This software is provided free of charge */ /* and without warranty. The source code may */ /* be distributed freely provided this copyright */ /* notice remains in tact. */ #import "Plot.h" #import "PlotView.h" #import <stdlib.h> #import <string.h> @implementation Plot // These 'set***' methods attach this to the objects in the Window - setCanvas:anObject { canvas = anObject; return self; } - setXMin:anObject { xMin = anObject; return self; } - setYMax:anObject { yMax = anObject; return self; } - setYMin:anObject { yMin = anObject; return self; } - setXMax:anObject { xMax = anObject; return self; } - setPlotBox:anObject { plotBox = anObject; return self; } // These methods return the values of the instance variables - (BOOL )border:sender { return border; } - (BOOL )axes:sender { return axes; } - (BOOL )lines:sender { return lines; } - (int )style:sender { return style; } - (NXPoint *)data { return data; } - (int )dSize { return dCount; } - (NXCoord )xmin:sender { return min.x; } - (NXCoord )xmax:sender { return max.x; } - (NXCoord )ymin:sender { return min.y; } - (NXCoord )ymax:sender { return max.y; } - (char *)fileName:sender; { return fileName; } // These set*** methods set the instance variables from the control- // panel objects. - setLines:sender { lines = [sender state]; return self; } - setAxes:sender { axes = [sender state]; return self; } - setBorder:sender { border = [sender state]; return self; } - setStyle:sender { style = [sender selectedRow]; return self; } - setMinmax:sender { minmax = [sender selectedCol]; if (minmax) { [self getXmin:self]; [self getXmax:self]; [self getYmin:self]; [self getYmax:self]; } else { min.x = dMin.x; max.x = dMax.x; min.y = dMin.y; max.y = dMax.y; [self resetXmin:self]; [self resetXmax:self]; [self resetYmin:self]; [self resetYmax:self]; } return self; } // read the min or max value from the control panel - getXmin:sender { min.x = [xMin floatValueAt:0]; return self; } - getXmax:sender { max.x = [xMax floatValueAt:0]; return self; } - getYmin:sender { min.y = [yMin floatValueAt:0]; return self; } - getYmax:sender { max.y = [yMax floatValueAt:0]; return self; } // reset the data limits shown in the control panel - resetXmin:sender { [xMin setFloatValue:(float )min.x at:0]; return self; } - resetXmax:sender { [xMax setFloatValue:(float )max.x at:0]; return self; } - resetYmin:sender { [yMin setFloatValue:(float )min.y at:0]; return self; } - resetYmax:sender { [yMax setFloatValue:(float )max.y at:0]; return self; } // Change the Plot title in the window to reflect // the data-file name - setBoxTitle:(char *)aTitle { [plotBox setTitle:(const char *)aTitle]; return self; } // Get a fileName: this will be the PostScript file where the // PlotView will write its code if a 'Save' is requested from the main menu - setFileName:(char *)aPSfile { if (fileName) free(fileName); fileName = calloc(strlen(aPSfile)+1, sizeof(char)); strcpy(fileName, aPSfile); return self; } // This method sets things up so that PlotView:drawSelf // can do all the drawing work. - drawPlot:sender { if (!data) return self; if ([self setupBorder:self]) [plotBox display]; return self; } // Allocate enough memory and read the data points - (int )readDataFrom:(FILE *)aDataStream { double x, y; int i; /* First read through the file to see how big it is */ i = 0; while (fscanf(aDataStream, "%lf %lf\n", &x, &y) == 2) i++; /* If it was empty, then don't discard the old data */ if (i == 0) return 0; /* Now read the data into memory */ dCount = i; if (data) free(data); data = (NXPoint *)calloc(dCount, sizeof(NXPoint)); rewind(aDataStream); for (i = 0; i < dCount; i++) { fscanf(aDataStream, "%lf %lf\n", &x, &y); data[i].x = (float )x; data[i].y = (float )y; } return dCount; } // Go through the data set and find values for dMin.x, dMax.x, dMin.y, dMax.y - findMinAndMax { if (data) { int i; dMin.x = dMax.x = data[0].x; dMin.y = dMax.y = data[0].y; for (i = 1; i < dCount; i++) { if (data[i].x < dMin.x) dMin.x = data[i].x; else if (data[i].x > dMax.x) dMax.x = data[i].x; if (data[i].y < dMin.y) dMin.y = data[i].y; else if (data[i].y > dMax.y) dMax.y = data[i].y; } } return self; } // This message sends the appropriate min and max to the PlotView - (BOOL )setupBorder:sender { NXSize newSize; /* Start by setting up the right scale */ if (minmax) { [self getXmin:self]; [self getXmax:self]; [self getYmin:self]; [self getYmax:self]; } else { min.x = dMin.x; max.x = dMax.x; min.y = dMin.y; max.y = dMax.y; [self resetXmin:self]; [self resetXmax:self]; [self resetYmin:self]; [self resetYmax:self]; } newSize.width = max.x - min.x; newSize.height = max.y - min.y; if (newSize.width == 0 || newSize.height == 0) { NXRunAlertPanel("Plot", "The graph width and height must be > 0", "OK", NULL, NULL, NULL); return NO; } [canvas setDrawSize:(newSize.width + 0.2*newSize.width) :(newSize.height + 0.2*newSize.height)]; [canvas setDrawOrigin:(min.x - 0.1*newSize.width) :(min.y - 0.1*newSize.height)]; return YES; } // Use the OpenPanel object to get a fileName - open:sender { char const *fileTypes[2] = {0,0}; // this type is all ASCII files char fname[1024]; id openPanel = [OpenPanel new]; if ([openPanel runModalForTypes:fileTypes]) { strncpy(fname, [openPanel filename], 1024); [self openFile:fname]; } return self; } - openFile:(char *)aDataFile { FILE *dataStream; char psFile[1024]; if ((dataStream = fopen(aDataFile, "r")) == NULL) { NXRunAlertPanel("Open", "Cannot open %s", "OK", NULL, NULL, aDataFile); return self; } if ([self readDataFrom:dataStream] == 0) { NXRunAlertPanel("Read", "Couldn't read any data from %s", "OK", NULL, NULL, aDataFile); fclose(dataStream); return self; } fclose(dataStream); [self findMinAndMax]; [self setBoxTitle:aDataFile]; [self drawPlot:self] ; return self; } // Tell the PlotView to write its PostScript code to fileName - save:sender { if (fileName) [canvas savePSCode:fileName]; else [self saveAs:sender]; return self; } // Get a fileName and then tell the PlotView to save // its PostScript code there - saveAs:sender { id savePanel = [SavePanel new]; if (fileName) free(fileName); [savePanel setRequiredFileType:"ps"]; if ([savePanel runModal]) { fileName = calloc(strlen([savePanel filename])+1, sizeof(char)); strcpy(fileName, [savePanel filename]); [self save:sender]; } return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.