home *** CD-ROM | disk | FTP | other *** search
/ NeXT Education Software Sampler 1992 Fall / NeXT Education Software Sampler 1992 Fall.iso / Programming / Source / plot3d / PControl.m < prev    next >
Encoding:
Text File  |  1992-08-18  |  7.1 KB  |  300 lines

  1. #import "PControl.h"
  2. #import "Plot3DView.h"
  3. #import <appkit/Control.h>
  4. #import <appkit/Matrix.h>
  5. #import <appkit/Application.h>
  6. #import <appkit/NXColorWell.h>
  7. #import <appkit/NXColorPanel.h>
  8. #import <appkit/ScrollView.h>
  9. #import <appkit/Text.h>
  10. #import <dpsclient/event.h>
  11. #import <dpsclient/psops.h>
  12. #import <appkit/color.h>
  13. #import <appkit/OpenPanel.h>
  14. #import <stdio.h>
  15. #import <math.h>
  16. #import <ctype.h>
  17. #include <libc.h>
  18. #import "Expression.h"
  19. #import "DensView.h"
  20.  
  21. @implementation PControl
  22. -init
  23. {
  24. [super init];
  25. return self;
  26. }
  27.  
  28. /* Called once by the Plot3DView to do initialization and pass pref pointer */
  29. -startup:(SetPref *)Pref
  30. {
  31.     pref=Pref;
  32. /* display initial preferences settings */
  33.     curPref=0;
  34.     [symsel selectCellWithTag:pref[0].sym+1];
  35.     [colorSel setColor:pref[0].color];
  36.     equation=[equation docView];
  37.     [equation setText:[pref[0].expr text]];
  38. /* make sure plot agrees with displayed min/max values */
  39.     [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]];
  40. return self;
  41. }
  42.  
  43. /* display preferences for a data set */
  44. -disPref:sender
  45. {
  46. curPref=[[sender selectedCell] tag];
  47. [symsel selectCellWithTag:pref[curPref].sym+1];
  48. [colorSel setColor:pref[curPref].color];
  49. if (pref[curPref].fileData==NULL) [ffSel selectCellWithTag:0];
  50. else [ffSel selectCellWithTag:1];
  51. [equation setText:[pref[curPref].expr text]];
  52. [d3View zoom:self];
  53. return self;
  54. }
  55.  
  56. /* put preferences from screen into SetPref for curPref set */
  57. -stoPref:sender
  58. {
  59. char *tmp;
  60. int i,j,k;
  61. pref[curPref].sym=[[symsel selectedCell] tag]-1;
  62. pref[curPref].color=[colorSel color];
  63. tmp=malloc([equation textLength]+50);
  64. [equation getSubstring:tmp start:0 length:[equation textLength]+1];
  65. /* Fix equation for parsing */
  66. k=strlen(tmp);
  67. for (i=0; i<k; i++) {
  68.     if (tmp[i]=='[') tmp[i]='(';
  69.     if (tmp[i]==']') tmp[i]=')';
  70.     if (isupper(tmp[i])) tmp[i]=tolower(tmp[i]);
  71.     if ((tmp[i]=='+'||tmp[i]=='-')&&(isdigit(tmp[i+1])||tmp[i+1]=='.')) {
  72.         for (j=k; j>i; j--) tmp[j+1]=tmp[j];
  73.         tmp[i+1]=' ';
  74.         k++;
  75.     }
  76. }
  77.  
  78. /* if the equation doesn't parse, set it to 0 */
  79. if (strlen(tmp)==0 ||
  80.      [pref[curPref].expr parse:tmp]==0) {
  81.     [equation setText:"0"];
  82.     [pref[curPref].expr parse:"0"];
  83.     }
  84. [d3View zoom:self];
  85. return self;
  86. }
  87.  
  88. /* Read 3d data from a file and put it into the current data set */
  89. /* does NOT wait for an "OK" press, like other prefs */
  90. -readFile:sender
  91. {
  92. id panel;
  93. int i,c,cc=0;
  94. char s[80],sc[20];
  95. FILE *in;
  96. float x0,x1,y0,y1,f;
  97. Point *p;
  98.  
  99. if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].
  100. fileData=NULL; }
  101.  
  102. /* get a filespec from the user */
  103. panel=[[OpenPanel new] allowMultipleFiles:NO];
  104. if (![panel runModalForTypes:NULL]) {
  105.     [ffSel selectCellWithTag:0];
  106.     [equation setText:"0"];
  107.     [pref[curPref].expr parse:"0"];
  108.     return self;
  109. }
  110.  
  111. /* if we can't open the file, go back to equation mode */
  112. in=fopen([panel filename],"r");
  113. if (fgets(s,80,in)==NULL) {
  114.     [ffSel selectCellWithTag:0];
  115.     [equation setText:"0"];
  116.     [pref[curPref].expr parse:"0"];
  117.         return self;
  118. }
  119.  
  120. /* ignore leading # lines */
  121. while (s[0]=='#') { fgets(s,80,in); cc++; }
  122.  
  123. /* accept either "x,y,z\n" or "x y z\n" files */
  124. strcpy(sc," %f , %f , %f");
  125. if (sscanf(s,sc,&x0,&y0,&f)!=3) {
  126.     strcpy(sc," %f %f %f");
  127.     if (sscanf(s,sc,&x0,&y0,&f)!=3) {
  128.         [ffSel selectCellWithTag:0];
  129.         [equation setText:"0"];
  130.         [pref[curPref].expr parse:"0"];
  131.             return self;
  132.     }
  133. }
  134.  
  135. /* count the number of points in the file */
  136. x1=x0; y1=y0;
  137. c=1;
  138. while (fscanf(in,sc,&f,&f,&f)==3) c++;
  139. rewind(in);
  140.  
  141. /* 2nd pass, allocate memory and read data into array */
  142. p=pref[curPref].fileData=malloc(sizeof(Point)*c);
  143. pref[curPref].nfdata=c;
  144.  
  145. for (i=0; i<cc; i++) fgets(s,80,in);
  146. for (i=0; i<c; i++) {
  147.     fscanf(in,sc,&p[i].x,&p[i].y,&p[i].z);
  148.     if (p[i].x>x1) x1=p[i].x;
  149.     if (p[i].x<x0) x0=p[i].x;
  150.     if (p[i].y>y1) y1=p[i].y;
  151.     if (p[i].y<y0) y0=p[i].y;
  152. }
  153. if (pref[curPref].data!=NULL) free(pref[curPref].data);
  154. pref[curPref].data=malloc(sizeof(Point)*pref[curPref].nfdata);
  155. /* x0-=fabs(x0)/500.0+fabs(x1)/500.0;
  156. x1+=fabs(x0)/500.0+fabs(x1)/500.0;
  157. y0-=fabs(y0)/500.0+fabs(y1)/500.0;
  158. y1+=fabs(y0)/500.0+fabs(y1)/500.0; */
  159. [minX setFloatValue:x0];
  160. [minY setFloatValue:y0];
  161. [maxX setFloatValue:x1];
  162. [maxY setFloatValue:y1];
  163.  
  164. /* equation is now used to modify data Z values, set initial formula for */
  165. /* z(x,y,z)=z. ie - for log plots you would enter "log(z)" */
  166. [equation setText:"z"];
  167. [pref[curPref].expr parse:"z"];
  168.  
  169. /* update the display */
  170. [self setMinMax:self];
  171. [d3View zoom:self];
  172. return self;
  173. }
  174.  
  175. /* return a data set to equation mode, free memory used by the file */
  176. -clearFile:sender
  177. {
  178. if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].fileData=NULL; }
  179. pref[curPref].nfdata=0;
  180.  
  181. [equation setText:"0"];
  182. [pref[curPref].expr parse:"0"];
  183. [d3View zoom:self];
  184. return(self);
  185. }
  186.  
  187. /* minz and maxz can be modified before returning, but currently aren't */
  188. -minmaxZ:(float *)minz :(float *)maxz
  189. {
  190. [minZ setFloatValue:*minz];
  191. [maxZ setFloatValue:*maxz];
  192. return self;
  193. }
  194.  
  195. /* display new min/max values (does not inform the views of the change) */
  196. -setMM:(float)minx :(float)maxx :(float)miny :(float)maxy
  197. {
  198. [minX setFloatValue:minx];
  199. [minY setFloatValue:miny];
  200. [maxX setFloatValue:maxx];
  201. [maxY setFloatValue:maxy];
  202. return self;
  203. }
  204.  
  205. /* Tell the Plot3DView and (indirectly) the DensView about new max/min vals */
  206. -setMinMax:sender
  207. {
  208. [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]];
  209. return self;
  210. }
  211.  
  212. /* zoom in by a fixed amount */
  213. -zoomIn:sender
  214. {
  215. float x,y,x1,y1;
  216. x1=[maxX floatValue];
  217. x=[minX floatValue];
  218. y1=[maxY floatValue];
  219. y=[minY floatValue];
  220.  
  221. [maxX setFloatValue:x1-(x1-x)/4.0];
  222. [minX setFloatValue:x+(x1-x)/4.0];
  223. [maxY setFloatValue:y1-(y1-y)/4.0];
  224. [minY setFloatValue:y+(y1-y)/4.0];
  225.  
  226. [self setMinMax:self];
  227. [d3View zoom:self];
  228. return self;
  229. }
  230.  
  231. /* zoom out by a fixed amount */
  232. -zoomOut:sender
  233. {
  234. float x,y,x1,y1;
  235. x1=[maxX floatValue];
  236. x=[minX floatValue];
  237. y1=[maxY floatValue];
  238. y=[minY floatValue];
  239.  
  240. [maxX setFloatValue:x1+(x1-x)/4.0];
  241. [minX setFloatValue:x-(x1-x)/4.0];
  242. [maxY setFloatValue:y1+(y1-y)/4.0];
  243. [minY setFloatValue:y-(y1-y)/4.0];
  244.  
  245. [self setMinMax:self];
  246. [d3View zoom:self];
  247. return self;
  248. }
  249.  
  250. /* sent by DensView, min/max are from 0.0 to 1.0, not real units */
  251. -zoomTo:(float)minx :(float)miny :(float)maxx :(float)maxy
  252. {
  253. float x0,x1,y0,y1;
  254.  
  255. x0=[minX floatValue];
  256. x1=[maxX floatValue];
  257. y0=[minY floatValue];
  258. y1=[maxY floatValue];
  259.  
  260. [minX setFloatValue:x0+(x1-x0)*minx];
  261. [minY setFloatValue:y0+(y1-y0)*miny];
  262. [maxX setFloatValue:x0+(x1-x0)*maxx];
  263. [maxY setFloatValue:y0+(y1-y0)*maxy];
  264. [self setMinMax:self];
  265. [d3View zoom:self];
  266. return self;
  267. }
  268.  
  269. /* update the density plot */
  270. -updDen
  271. {
  272. static float *densData=NULL;
  273. static int ndd=0;
  274. int k,n,i;
  275.  
  276. n=[grid intValue];
  277. if (ndd<(n*n)) {
  278.     if (densData!=NULL) free(densData);
  279.     densData=malloc(n*n*sizeof(float));
  280.     ndd=n*n;
  281. }
  282.  
  283. if (pref[curPref].fileData==NULL) {
  284.     for (k=0; k<pref[curPref].ndata; k++) densData[k]=pref[curPref].data[k].z;
  285. }
  286. else {
  287.     for (k=0; k<(n*n); k++) densData[k]= -.5;
  288.     for (k=0; k<pref[curPref].ndata; k++) {
  289.         i=floor((pref[curPref].data[k].x+.5)*(float)n)+floor((pref[curPref].data[k].y+.5)*(float)n)*n;
  290.         if (i>=0 && i<ndd) densData[i]=pref[curPref].data[k].z;
  291.     }
  292. }
  293.     
  294. if (pref[curPref].sym!= -1) [dView setData:n :n :densData :-.5 :.5];
  295. else [dView setData:0 :0 :NULL :-.5 :.5];
  296. return self;
  297. }
  298.  
  299. @end
  300.