home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / Programming / Source / Car / DataView.m < prev    next >
Encoding:
Text File  |  1992-06-17  |  7.1 KB  |  384 lines

  1.  
  2. /* Generated by Interface Builder */
  3.  
  4. #import <math.h>
  5. #import <dpsclient/psops.h>
  6. #import <dpsclient/wraps.h>
  7. #import <objc/Storage.h>
  8. #import <appkit/NXImage.h>
  9. #import <appkit/TextField.h>
  10. #import "DataView.h"
  11. @implementation DataView
  12.  
  13. - initFrame:(const NXRect *)frameRect
  14. {
  15. NXSize cacheSize;
  16.  
  17.     [super initFrame:frameRect];
  18.     data = [[Storage alloc] initCount:0
  19.                 elementSize:sizeof(struct plotData)
  20.                             description:PLOTDATA_DESCRIPTION];
  21.     curve = [[Storage alloc] initCount:0
  22.                              elementSize:sizeof(float)
  23.                              description:"f"];
  24.     xscale = 1;
  25.     yscale = 1;
  26.     scaleOnTop = YES;
  27.     scaleOnBottom = YES;
  28.     scaleOnLeft = YES;
  29.     scaleOnRight = YES;
  30.  
  31. // Initialize an NXImage to draw in so we can flush it in drawself
  32.     cacheSize.width = frameRect->size.width;
  33.     cacheSize.height = frameRect->size.height;
  34.     cache = [[NXImage alloc] initSize:&cacheSize];
  35.     cacheUpToDate = NO;
  36.  
  37.     [self notifyAncestorWhenFrameChanged:YES];
  38.  
  39.     zeroLines = YES;  
  40.  
  41.     return self;
  42. }
  43.  
  44. - drawSelf:(NXRect *)rects :(int)rectCount
  45. {
  46.     if ( !cacheUpToDate && [self window] )
  47.         [self drawInCache];
  48.     [cache composite:NX_SOVER
  49.            toPoint:&bounds.origin];
  50.  
  51.     return self;
  52. }
  53.  
  54. - free
  55. {
  56.     [data free];
  57.     return [super free];
  58. }
  59.  
  60. - setFrame:(NXRect *)frameRect
  61. {
  62.     [super setFrame:frameRect];
  63.     cacheUpToDate = NO;
  64.     return self;
  65. }
  66.  
  67. - moveTo:(NXCoord)x :(NXCoord)y
  68. {
  69.     [super moveTo:x :y];
  70.     [topScale moveTo:x :0];
  71.     [bottomScale moveTo:x :0];
  72.     [leftScale moveTo:0 :y];
  73.     [rightScale moveTo:0 :y];
  74.     return self;
  75. }
  76.  
  77. - sizeTo:(NXCoord)width :(NXCoord)height
  78. {
  79.     [super sizeTo:width :height];
  80.     cacheUpToDate = NO;
  81.     return self;
  82. }
  83.  
  84. - addData:(struct plotData *)datum
  85. {
  86. // If there has been no previous data, initialize the min and max values
  87.     if ( ![data count] )
  88.         {
  89.         xmax = datum->x;
  90.         xmin = datum->x;
  91.         ymax = datum->y;
  92.         ymin = datum->y;
  93.         }
  94. // If the min and max values have been initialized then adjust them accordingly.
  95.     else
  96.         {
  97.         if ( datum->x > xmax )
  98.             xmax = datum->x;
  99.         else if (datum->x < xmin )
  100.             xmin = datum->x;
  101.         if ( datum->y > ymax )
  102.             ymax = datum->y;
  103.         else if (datum->y < ymin )
  104.             ymin = datum->y;
  105.         }
  106.     [data addElement:datum];
  107.  
  108.     return self;
  109. }
  110.  
  111. - drawInCache
  112. {
  113. struct plotData *datum;
  114. int count;
  115. int i;
  116. float x;
  117. float interval;
  118.  
  119. // We have to resize the cache first.
  120.     [cache setSize:&(bounds.size)];
  121.  
  122.     [cache lockFocus];
  123. // Wipe out the background
  124.     PSsetgray(NX_WHITE);
  125.     PSsetalpha(0.0);
  126.     NXRectFill(&bounds);
  127.  
  128. // Calculate the x and y scales so that the plot fills up the view.
  129.     if ( xmax - xmin != 0 )
  130.         xscale = bounds.size.width/(xmax - xmin);
  131.     if ( ymax - ymin != 0 )
  132.         yscale = bounds.size.height/(ymax - ymin);
  133.   
  134.  
  135. // Try to plot the data only if there is any
  136.     
  137.     count = [data count];
  138.     if ( !count && ![curve count] )
  139.         {
  140.         [cache unlockFocus];
  141.         return self;
  142.         }
  143.  
  144.     PSsetgray(NX_BLACK);
  145.     PSsetalpha(1.0);
  146.     PSsetlinewidth(1/50);
  147.     PSscale(xscale,yscale);
  148.     PStranslate(-xmin,-ymin);
  149.     if ( plotMode == DATA_ONLY || plotMode == DATA_AND_CURVE )
  150.         {
  151.         datum = [data elementAt:0];
  152.         PSmoveto(datum->x,datum->y);
  153.         for ( i = 1 ; i < count ; i++ )
  154.             {
  155.             datum = [data elementAt:i];
  156.             PSlineto(datum->x,datum->y);
  157.             }
  158.         }
  159.     if ( plotMode == CURVE_ONLY || plotMode == DATA_AND_CURVE )
  160.         {
  161.         PSmoveto(xmin,evaluatePolynomial(curve->dataPtr,[curve count],xmin));
  162.         interval = ( xmax - xmin ) / ( frame.size.width );
  163.         if ( interval <= 0 )
  164.             {
  165.             [cache unlockFocus];
  166.             return self;
  167.             }
  168.         for ( x  = xmin ; x <= xmax ; x+= interval )
  169.             PSlineto(x,evaluatePolynomial(curve->dataPtr,[curve count],x)); 
  170.         }
  171.     if ( zeroLines )
  172.         {
  173.         PSmoveto(xmin,0);
  174.         PSlineto(xmax,0);
  175.         PSmoveto(0,ymin);
  176.         PSlineto(0,ymax);
  177.         }
  178.     PSstroke();
  179.  
  180.     [cache unlockFocus];
  181.  
  182.     return self;
  183. }
  184.  
  185. - setPlotMode:(int)mode
  186. {
  187.     plotMode = mode;
  188.     return self;
  189. }
  190.  
  191. - setZeroLines:(BOOL)mode
  192. {
  193.     zeroLines = mode;
  194.     return self;
  195. }
  196.  
  197. - (float)xscale
  198. {
  199.     return xscale;
  200. }
  201.  
  202. - (float)yscale
  203. {
  204.     return yscale;
  205. }
  206.  
  207. - (float)xmin
  208. {
  209.     return xmin;
  210. }
  211.  
  212. - setxmin:(float)aNumber
  213. {
  214.     xmin = aNumber;
  215.     return self;
  216. }
  217.  
  218. - (float)xmax
  219. {
  220.     return xmax;
  221. }
  222.  
  223. - setxmax:(float)aNumber
  224. {
  225.     xmax = aNumber;
  226.     return self;
  227. }
  228.  
  229. - (float)ymin
  230. {
  231.     return ymin;
  232. }
  233.  
  234. - setymin:(float)aNumber
  235. {
  236.     ymin = aNumber;
  237.     return self;
  238. }
  239.  
  240. - (float)ymax
  241. {
  242.     return ymax;
  243. }
  244.  
  245. - setymax:(float)aNumber
  246. {
  247.     ymax = aNumber;
  248.     return self;
  249. }
  250.  
  251. - data
  252. {
  253.     return data;
  254. }
  255.  
  256. - setData:anObject
  257. {
  258. int count;
  259. int i;
  260. struct plotData *datum;
  261.  
  262.     if ( data != anObject )
  263.         [data free];
  264.     data = anObject;
  265.         count = [data count];
  266.     datum = [data elementAt:0];
  267.     xmax = datum->x;
  268.     xmin = datum->x;
  269.     ymax = datum->y;
  270.     ymin = datum->y;
  271.   
  272.     for ( i = 1 ; i < count ; i++ )
  273.         {
  274.         datum = [data elementAt:i];
  275.         if ( datum->x > xmax )
  276.             xmax = datum->x;
  277.         else if (datum->x < xmin )
  278.             xmin = datum->x;
  279.         if ( datum->y > ymax )
  280.             ymax = datum->y;
  281.         else if (datum->y < ymin )
  282.             ymin = datum->y;
  283.         }
  284.     return self;
  285. }
  286.  
  287. - setCurve:anObject
  288. {
  289.     curve = anObject;
  290.     return self;
  291. }
  292.  
  293. - setCurveFromArray:(float *)coefficients count:(int)anInt
  294. {
  295. int i;
  296.  
  297.     [curve empty];
  298.     for ( i = 0 ; i < anInt ; i++ )
  299.         [curve addElement:&coefficients[i]];
  300.     cacheUpToDate = NO;
  301.     return self;
  302. }
  303.  
  304. - rescaleForCurveWithRange:(float)newxmin :(float)newxmax checkInterval:(float)interval;
  305. {
  306. float i;
  307. float y;
  308.  
  309.     if ( interval <= 0 || newxmin >= newxmax )
  310.         return self;
  311.  
  312.     xmin = newxmin;
  313.     xmax = newxmax;
  314.     ymin = evaluatePolynomial(curve->dataPtr,[curve count],xmin);
  315.     ymax = ymin;
  316.     for ( i = newxmin ; i <= newxmax ; i+= interval )
  317.         {
  318.         y = evaluatePolynomial(curve->dataPtr,[curve count],i);
  319.         if ( y < ymin )
  320.             ymin = y;
  321.         if ( y > ymax )
  322.             ymax = y;
  323.         }
  324.     cacheUpToDate = NO;
  325.     return self;
  326. }
  327.  
  328. - drawLimits
  329. {
  330.     [xmintext setFloatValue:xmin];
  331.     [xmaxtext setFloatValue:xmax];
  332.     [ymintext setFloatValue:ymin];
  333.     [ymaxtext setFloatValue:ymax];
  334.     return self;
  335. }
  336.  
  337. - (float)integral  // for now, this does a simple trapezoidal integration.  it will change later.
  338. {
  339. float integral;
  340. int i;
  341. int count;
  342. struct plotData *points;
  343.  
  344.     count = [data count];
  345.     points = data->dataPtr;
  346.     integral = 0;
  347.  
  348.     for ( i = 1 ; i < count ; i++ )
  349.         integral += ( points[i-1].y + points[i].y ) / 2 * ( points[i].x - points[i-1].x );
  350.  
  351.     return integral;
  352. }
  353.  
  354. - (float)integrateWithLimits:(float)start :(float)end
  355. {
  356. float integral;
  357.  
  358.     return integral;
  359. }
  360.  
  361. @end
  362.  
  363.  
  364. float evaluatePolynomial(float *coefficients,int number,float x)
  365. {
  366. int i;
  367. float y;    
  368.  
  369.     y = coefficients[0];
  370.     for ( i = 1 ; i < number ; i++ )
  371.         y += coefficients[i] * pow(x,i);
  372.     return y;
  373. }
  374.  
  375.  
  376.  
  377.  
  378.  
  379.  
  380.  
  381.  
  382.  
  383.  
  384.