home *** CD-ROM | disk | FTP | other *** search
-
- /* 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
-