home *** CD-ROM | disk | FTP | other *** search
-
- /* Generated by Interface Builder */
-
- #import <math.h>
- #import <dpsclient/psops.h>
- #import <dpsclient/wraps.h>
- #import <objc/Storage.h>
- #import <appkit/NXImage.h>
- #import <appkit/TextField.h>
- #import "DataView.h"
- @implementation DataView
-
- - initFrame:(const NXRect *)frameRect
- {
- NXSize cacheSize;
-
- [super initFrame:frameRect];
- data = [[Storage alloc] initCount:0
- elementSize:sizeof(struct plotData)
- description:PLOTDATA_DESCRIPTION];
- curve = [[Storage alloc] initCount:0
- elementSize:sizeof(float)
- description:"f"];
- xscale = 1;
- yscale = 1;
- scaleOnTop = YES;
- scaleOnBottom = YES;
- scaleOnLeft = YES;
- scaleOnRight = YES;
-
- // Initialize an NXImage to draw in so we can flush it in drawself
- cacheSize.width = frameRect->size.width;
- cacheSize.height = frameRect->size.height;
- cache = [[NXImage alloc] initSize:&cacheSize];
- cacheUpToDate = NO;
-
- [self notifyAncestorWhenFrameChanged:YES];
-
- zeroLines = YES;
-
- return self;
- }
-
- - drawSelf:(NXRect *)rects :(int)rectCount
- {
- if ( !cacheUpToDate && [self window] )
- [self drawInCache];
- [cache composite:NX_SOVER
- toPoint:&bounds.origin];
-
- return self;
- }
-
- - free
- {
- [data free];
- return [super free];
- }
-
- - setFrame:(NXRect *)frameRect
- {
- [super setFrame:frameRect];
- cacheUpToDate = NO;
- return self;
- }
-
- - moveTo:(NXCoord)x :(NXCoord)y
- {
- [super moveTo:x :y];
- [topScale moveTo:x :0];
- [bottomScale moveTo:x :0];
- [leftScale moveTo:0 :y];
- [rightScale moveTo:0 :y];
- return self;
- }
-
- - sizeTo:(NXCoord)width :(NXCoord)height
- {
- [super sizeTo:width :height];
- cacheUpToDate = NO;
- return self;
- }
-
- - addData:(struct plotData *)datum
- {
- // If there has been no previous data, initialize the min and max values
- if ( ![data count] )
- {
- xmax = datum->x;
- xmin = datum->x;
- ymax = datum->y;
- ymin = datum->y;
- }
- // If the min and max values have been initialized then adjust them accordingly.
- else
- {
- if ( datum->x > xmax )
- xmax = datum->x;
- else if (datum->x < xmin )
- xmin = datum->x;
- if ( datum->y > ymax )
- ymax = datum->y;
- else if (datum->y < ymin )
- ymin = datum->y;
- }
- [data addElement:datum];
-
- return self;
- }
-
- - drawInCache
- {
- struct plotData *datum;
- int count;
- int i;
- float x;
- float interval;
-
- // We have to resize the cache first.
- [cache setSize:&(bounds.size)];
-
- [cache lockFocus];
- // Wipe out the background
- PSsetgray(NX_WHITE);
- PSsetalpha(0.0);
- NXRectFill(&bounds);
-
- // Calculate the x and y scales so that the plot fills up the view.
- if ( xmax - xmin != 0 )
- xscale = bounds.size.width/(xmax - xmin);
- if ( ymax - ymin != 0 )
- yscale = bounds.size.height/(ymax - ymin);
-
-
- // Try to plot the data only if there is any
-
- count = [data count];
- if ( !count && ![curve count] )
- {
- [cache unlockFocus];
- return self;
- }
-
- PSsetgray(NX_BLACK);
- PSsetalpha(1.0);
- PSsetlinewidth(1/50);
- PSscale(xscale,yscale);
- PStranslate(-xmin,-ymin);
- if ( plotMode == DATA_ONLY || plotMode == DATA_AND_CURVE )
- {
- datum = [data elementAt:0];
- PSmoveto(datum->x,datum->y);
- for ( i = 1 ; i < count ; i++ )
- {
- datum = [data elementAt:i];
- PSlineto(datum->x,datum->y);
- }
- }
- if ( plotMode == CURVE_ONLY || plotMode == DATA_AND_CURVE )
- {
- PSmoveto(xmin,evaluatePolynomial(curve->dataPtr,[curve count],xmin));
- interval = ( xmax - xmin ) / ( frame.size.width );
- if ( interval <= 0 )
- {
- [cache unlockFocus];
- return self;
- }
- for ( x = xmin ; x <= xmax ; x+= interval )
- PSlineto(x,evaluatePolynomial(curve->dataPtr,[curve count],x));
- }
- if ( zeroLines )
- {
- PSmoveto(xmin,0);
- PSlineto(xmax,0);
- PSmoveto(0,ymin);
- PSlineto(0,ymax);
- }
- PSstroke();
-
- [cache unlockFocus];
-
- return self;
- }
-
- - setPlotMode:(int)mode
- {
- plotMode = mode;
- return self;
- }
-
- - setZeroLines:(BOOL)mode
- {
- zeroLines = mode;
- return self;
- }
-
- - (float)xscale
- {
- return xscale;
- }
-
- - (float)yscale
- {
- return yscale;
- }
-
- - (float)xmin
- {
- return xmin;
- }
-
- - setxmin:(float)aNumber
- {
- xmin = aNumber;
- return self;
- }
-
- - (float)xmax
- {
- return xmax;
- }
-
- - setxmax:(float)aNumber
- {
- xmax = aNumber;
- return self;
- }
-
- - (float)ymin
- {
- return ymin;
- }
-
- - setymin:(float)aNumber
- {
- ymin = aNumber;
- return self;
- }
-
- - (float)ymax
- {
- return ymax;
- }
-
- - setymax:(float)aNumber
- {
- ymax = aNumber;
- return self;
- }
-
- - data
- {
- return data;
- }
-
- - setData:anObject
- {
- int count;
- int i;
- struct plotData *datum;
-
- if ( data != anObject )
- [data free];
- data = anObject;
- count = [data count];
- datum = [data elementAt:0];
- xmax = datum->x;
- xmin = datum->x;
- ymax = datum->y;
- ymin = datum->y;
-
- for ( i = 1 ; i < count ; i++ )
- {
- datum = [data elementAt:i];
- if ( datum->x > xmax )
- xmax = datum->x;
- else if (datum->x < xmin )
- xmin = datum->x;
- if ( datum->y > ymax )
- ymax = datum->y;
- else if (datum->y < ymin )
- ymin = datum->y;
- }
- return self;
- }
-
- - setCurve:anObject
- {
- curve = anObject;
- return self;
- }
-
- - setCurveFromArray:(float *)coefficients count:(int)anInt
- {
- int i;
-
- [curve empty];
- for ( i = 0 ; i < anInt ; i++ )
- [curve addElement:&coefficients[i]];
- cacheUpToDate = NO;
- return self;
- }
-
- - rescaleForCurveWithRange:(float)newxmin :(float)newxmax checkInterval:(float)interval;
- {
- float i;
- float y;
-
- if ( interval <= 0 || newxmin >= newxmax )
- return self;
-
- xmin = newxmin;
- xmax = newxmax;
- ymin = evaluatePolynomial(curve->dataPtr,[curve count],xmin);
- ymax = ymin;
- for ( i = newxmin ; i <= newxmax ; i+= interval )
- {
- y = evaluatePolynomial(curve->dataPtr,[curve count],i);
- if ( y < ymin )
- ymin = y;
- if ( y > ymax )
- ymax = y;
- }
- cacheUpToDate = NO;
- return self;
- }
-
- - drawLimits
- {
- [xmintext setFloatValue:xmin];
- [xmaxtext setFloatValue:xmax];
- [ymintext setFloatValue:ymin];
- [ymaxtext setFloatValue:ymax];
- return self;
- }
-
- - (float)integral // for now, this does a simple trapezoidal integration. it will change later.
- {
- float integral;
- int i;
- int count;
- struct plotData *points;
-
- count = [data count];
- points = data->dataPtr;
- integral = 0;
-
- for ( i = 1 ; i < count ; i++ )
- integral += ( points[i-1].y + points[i].y ) / 2 * ( points[i].x - points[i-1].x );
-
- return integral;
- }
-
- - (float)integrateWithLimits:(float)start :(float)end
- {
- float integral;
-
- return integral;
- }
-
- @end
-
-
- float evaluatePolynomial(float *coefficients,int number,float x)
- {
- int i;
- float y;
-
- y = coefficients[0];
- for ( i = 1 ; i < number ; i++ )
- y += coefficients[i] * pow(x,i);
- return y;
- }
-
-
-
-
-
-
-
-
-
-
-