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.