This is PControl.m in view mode; [Download] [Up]
#import "PControl.h" #import "Plot3DView.h" #import "PlotShape.h" #import <appkit/appkit.h> #import <dpsclient/event.h> #import <dpsclient/psops.h> #import <appkit/color.h> #import <stdio.h> #import <math.h> #import <ctype.h> #include <libc.h> #import "Expression.h" #import "DensView.h" int comp(float *x,float *y); @implementation PControl -init { [super init]; return self; } /* Called once by the Plot3DView to do initialization and pass pref pointer */ -startup:(SetPref *)Pref { pref=Pref; /* display initial preferences settings */ curPref=0; bpath=(char *)[[NXBundle mainBundle] directory]; [symsel selectCellWithTag:pref[0].sym+1]; equation=[equation docView]; [equation setText:[pref[0].expr text]]; /* make sure plot agrees with displayed min/max values */ [gridx setIntValue:pref[curPref].nx]; [gridy setIntValue:pref[curPref].ny]; [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]]; [d3View setDelegate:self]; /*[self readFile:self];*/ I_lim=[I_lim contentView]; I_dis=[I_dis contentView]; I_pho=[I_pho contentView]; return self; } /* display preferences for a data set */ -disPref:sender { int i; curPref=[[sender selectedCell] tag]; [symsel selectCellWithTag:pref[curPref].sym+1]; [color1 setColor:NXConvertRGBToColor(pref[curPref].mapcol[0][0], pref[curPref].mapcol[0][1],pref[curPref].mapcol[0][2])]; [color2 setColor:NXConvertRGBToColor(pref[curPref].mapcol[1][0], pref[curPref].mapcol[1][1],pref[curPref].mapcol[1][2])]; [color3 setColor:NXConvertRGBToColor(pref[curPref].mapcol[2][0], pref[curPref].mapcol[2][1],pref[curPref].mapcol[2][2])]; [color4 setColor:NXConvertRGBToColor(pref[curPref].mapcol[3][0], pref[curPref].mapcol[3][1],pref[curPref].mapcol[3][2])]; [color5 setColor:NXConvertRGBToColor(pref[curPref].mapcol[4][0], pref[curPref].mapcol[4][1],pref[curPref].mapcol[4][2])]; [alpha setFloatValue:pref[curPref].alpha]; [colortype selectCellWithTag:pref[curPref].mapmode]; if (curPref!=0) [[colortype cellAt:1 :1] setEnabled:NO]; else [[colortype cellAt:1 :1] setEnabled:YES]; for (i=0; i<5; i++) [[colorsel cellAt:0 :i] setIntValue:pref[curPref].mapsel[i]]; if ((pref[curPref].flag&7)==F_EQN) [ffSel selectCellWithTag:0]; else if ((pref[curPref].flag&7)==F_DATA) [ffSel selectCellWithTag:1]; else if ((pref[curPref].flag&7)==F_SDATA) [ffSel selectCellWithTag:2]; else if ((pref[curPref].flag&7)==F_DEM) [ffSel selectCellWithTag:3]; [equation setText:[pref[curPref].expr text]]; [gridx setIntValue:pref[curPref].nx]; [gridy setIntValue:pref[curPref].ny]; [d3View zoom:self]; return self; } /* put preferences from screen into SetPref for curPref set */ -stoPref:sender { char *tmp; int i,j,k; pref[curPref].sym=[[symsel selectedCell] tag]-1; pref[curPref].nx=[gridx intValue]; if (pref[curPref].nx>MAXGRID||pref[curPref].nx<4) [gridx setIntValue:pref[curPref].nx=10]; pref[curPref].ny=[gridy intValue]; if (pref[curPref].ny>MAXGRID||pref[curPref].ny<4) [gridy setIntValue:pref[curPref].ny=10]; tmp=malloc([equation textLength]+50); [equation getSubstring:tmp start:0 length:[equation textLength]+1]; /* Fix equation for parsing */ k=strlen(tmp); for (i=0; i<k; i++) { if (tmp[i]=='[') tmp[i]='('; if (tmp[i]==']') tmp[i]=')'; if (isupper(tmp[i])) tmp[i]=tolower(tmp[i]); if ((tmp[i]=='+'||tmp[i]=='-')&&(isdigit(tmp[i+1])||tmp[i+1]=='.')) { for (j=k; j>i; j--) tmp[j+1]=tmp[j]; tmp[i+1]=' '; k++; } } /* if the equation doesn't parse, set it to 0 */ if (strlen(tmp)==0 || [pref[curPref].expr parse:tmp]==0) { [self error:"Cannot parse equation!"]; [pref[curPref].expr parse:"0"]; } /* Colors */ NXConvertColorToRGB([color1 color],&pref[curPref].mapcol[0][0], &pref[curPref].mapcol[0][1],&pref[curPref].mapcol[0][2]); NXConvertColorToRGB([color2 color],&pref[curPref].mapcol[1][0], &pref[curPref].mapcol[1][1],&pref[curPref].mapcol[1][2]); NXConvertColorToRGB([color3 color],&pref[curPref].mapcol[2][0], &pref[curPref].mapcol[2][1],&pref[curPref].mapcol[2][2]); NXConvertColorToRGB([color4 color],&pref[curPref].mapcol[3][0], &pref[curPref].mapcol[3][1],&pref[curPref].mapcol[3][2]); NXConvertColorToRGB([color5 color],&pref[curPref].mapcol[4][0], &pref[curPref].mapcol[4][1],&pref[curPref].mapcol[4][2]); pref[curPref].alpha=[alpha floatValue]; for (i=0; i<5; i++) pref[curPref].mapsel[i]=[[colorsel cellAt:0 :i] intValue]; pref[curPref].mapmode=[[colortype selectedCell] tag]; if ([[ffSel selectedCell] tag]==0) pref[curPref].flag=F_EQN; else if ([[ffSel selectedCell] tag]==1) pref[curPref].flag=F_DATA; else if ([[ffSel selectedCell] tag]==2) pref[curPref].flag=F_SDATA; else if ([[ffSel selectedCell] tag]==3) pref[curPref].flag=F_DEM; /* if spherical plot, set proper limits */ if (pref[curPref].sym==6) { [minX setFloatValue:0]; [maxX setFloatValue:M_PI]; [minY setFloatValue:0]; [maxY setFloatValue:M_PI*2.0]; [self setMinMax:self]; } [d3View zoom:self]; return self; } /* Read 3d data from a file and put it into the current data set */ /* does NOT wait for an "OK" press, like other prefs */ -readFile:sender { id panel; int i,j,k,cc=0,nx,ny; char s[201],sc[20]; FILE *in; float x0,y0,z0,z1,f,x[MAXGRID+1],y[MAXGRID+1]; Point *p; if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].fileData=NULL; } if (sender!=self) { /* get a filespec from the user */ panel=[[OpenPanel new] allowMultipleFiles:NO]; if (![panel runModalForTypes:NULL]) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; return self; } /* if we can't open the file, go back to equation mode */ in=fopen([panel filename],"r"); } else { [ffSel selectCellWithTag:1]; sprintf(s,"%s/title.3d",bpath); in=fopen(s,"r"); } if (fgets(s,200,in)==NULL) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"Can't open file."]; return self; } /* ignore leading # lines */ while (s[0]=='#') { fgets(s,80,in); cc++; } /* accept either "x,y,z\n" or "x y z\n" files */ strcpy(sc," %f , %f , %f"); if (sscanf(s,sc,&x[0],&y[0],&z0)!=3) { strcpy(sc," %f %f %f"); if (sscanf(s,sc,&x[0],&y[0],&z0)!=3) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"File not in 'x y z' or 'x,y,z' format."]; return self; } } z1=z0; /* count the number of points in the file */ nx=ny=1; while (fscanf(in,sc,&x[nx],&y[ny],&f)==3) { if (f<z0) z0=f; for (i=0; i<nx; i++) if (x[nx]==x[i]) break; if (i==nx) nx++; for (i=0; i<ny; i++) if (y[ny]==y[i]) break; if (i==ny) ny++; if (nx==MAXGRID+1||ny==MAXGRID+1) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"More than MAXGRID points in x or y."]; fclose(in); return self; } } qsort(x,nx,sizeof(float),comp); qsort(y,ny,sizeof(float),comp); rewind(in); /* 2nd pass, allocate memory,initialize and read data into array */ p=pref[curPref].fileData=malloc(sizeof(Point)*nx*ny); pref[curPref].nfdata=nx*ny; for (i=0; i<nx; i++) { for (j=0; j<ny; j++) { p[i+nx*j].x=x[i]; p[i+nx*j].y=y[j]; p[i+nx*j].z=z0; } } for (i=0; i<cc; i++) fgets(s,240,in); while (fscanf(in,sc,&x0,&y0,&f)==3) { for (j=0; j<nx; j++) if (x0==x[j]) break; for (k=0; k<ny; k++) if (y0==y[k]) break; if (k==ny||j==nx) [self error:"Unusual error, notify author."]; p[j+nx*k].z=f; } if (pref[curPref].data!=NULL) free(pref[curPref].data); pref[curPref].data=malloc(sizeof(Point)*pref[curPref].nfdata); pref[curPref].color=malloc(sizeof(RtColor)*pref[curPref].nfdata); [minX setFloatValue:x[0]]; [minY setFloatValue:y[0]]; [maxX setFloatValue:x[nx-1]]; [maxY setFloatValue:y[ny-1]]; /* equation is now used to modify data Z values, set initial formula for */ /* z(x,y,z)=z. ie - for log plots you would enter "log(z)" */ [equation setText:"z"]; [pref[curPref].expr parse:"z"]; pref[curPref].flag=F_DATA; /* update the display */ [self setMinMax:self]; [d3View zoom:self]; return self; } /* Read processed DEM data from a file and put it into the DEM data set */ /* does NOT wait for an "OK" press, like other prefs */ -readDEM:sender { id panel; int nx,ny; FILE *in; if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].fileData=NULL; } if (pref[curPref].demData!=NULL) { free(pref[curPref].demData); pref[curPref].demData=NULL; } /* get a filespec from the user */ panel=[[OpenPanel new] allowMultipleFiles:NO]; /* if we can't open the file, go back to equation mode */ if (![panel runModalForTypes:NULL]) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; return self; } in=fopen([panel filename],"r"); /* read the processed DEM header */ fread(&pref[curPref].demnx,sizeof(int),1,in); fread(&pref[curPref].demny,sizeof(int),1,in); fread(pref[curPref].demx,sizeof(float),2,in); fread(pref[curPref].demy,sizeof(float),2,in); if (fread(pref[curPref].demz,sizeof(float),2,in)!=2|| pref[curPref].demnx<10||pref[curPref].demnx>5000||pref[curPref].demny<10||pref[curPref].demny>5000) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"Can't open file."]; return self; } pref[curPref].demx[2]=(pref[curPref].demx[1]-pref[curPref].demx[0])/(float)(pref[curPref].demnx-1); pref[curPref].demy[2]=(pref[curPref].demy[1]-pref[curPref].demy[0])/(float)(pref[curPref].demny-1); /* allocate a big chunk of memory */ nx=pref[curPref].demnx; ny=pref[curPref].demny; pref[curPref].demData=malloc(sizeof(short)*nx*ny); /* read the data */ if (fread(pref[curPref].demData,nx*sizeof(short),ny,in)!=ny) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"More than MAXGRID points in x or y."]; fclose(in); return self; } [minX setFloatValue:pref[curPref].demx[0]]; [minY setFloatValue:pref[curPref].demy[0]]; [maxX setFloatValue:pref[curPref].demx[1]]; [maxY setFloatValue:pref[curPref].demy[1]]; /* equation is now used to modify data Z values, set initial formula for */ /* z(x,y,z)=z. ie - for log plots you would enter "log(z)" */ [equation setText:"z"]; [pref[curPref].expr parse:"z"]; pref[curPref].flag=F_DEM; /* update the display */ [self setMinMax:self]; [d3View zoom:self]; return self; } /* Read 3d scatter data from a file and put it into the current data set */ /* does NOT wait for an "OK" press, like other prefs */ -readSFile:sender { id panel; int i,j,k,cc=0,n; char s[201],sc[20]; FILE *in; float x0,y0,x1,y1,z0,z1,f; Point *p; if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref]. fileData=NULL; } if (sender!=self) { /* get a filespec from the user */ panel=[[OpenPanel new] allowMultipleFiles:NO]; if (![panel runModalForTypes:NULL]) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; return self; } /* if we can't open the file, go back to equation mode */ in=fopen([panel filename],"r"); } else { [ffSel selectCellWithTag:1]; sprintf(s,"%s/title.3d",bpath); in=fopen(s,"r"); } if (fgets(s,200,in)==NULL) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"Can't open file."]; return self; } /* ignore leading # lines */ while (s[0]=='#') { fgets(s,80,in); cc++; } /* accept either "x,y,z\n" or "x y z\n" files */ strcpy(sc," %f , %f , %f"); if (sscanf(s,sc,&x0,&y0,&z0)!=3) { strcpy(sc," %f %f %f"); if (sscanf(s,sc,&x0,&y0,&z0)!=3) { [ffSel selectCellWithTag:0]; pref[curPref].flag=F_EQN; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [self error:"File not in 'x y z' or 'x,y,z' format."]; return self; } x1=x0; y1=y0; } /* count the number of points in the file */ n=1; while (fscanf(in,sc,&f,&f,&f)==3) n++; rewind(in); /* 2nd pass, allocate memory,initialize and read data into array */ p=pref[curPref].fileData=malloc(sizeof(Point)*n); pref[curPref].nfdata=n; for (i=0; i<cc; i++) fgets(s,240,in); n=0; while (fscanf(in,sc,&p[n].x,&p[n].y,&p[n].z)==3) { if (p[n].x<x0) x0=p[n].x; if (p[n].x>x1) x1=p[n].x; if (p[n].y<y0) y0=p[n].y; if (p[n].y>y1) y1=p[n].y; n++; } if (pref[curPref].data!=NULL) free(pref[curPref].data); pref[curPref].data=malloc(sizeof(Point)*pref[curPref].nfdata); pref[curPref].color=malloc(sizeof(RtColor)*pref[curPref].nfdata); [minX setFloatValue:x0]; [minY setFloatValue:y0]; [maxX setFloatValue:x1]; [maxY setFloatValue:y1]; /* equation is now used to modify data Z values, set initial formula for */ /* z(x,y,z)=z. ie - for log plots you would enter "log(z)" */ [equation setText:"z"]; [pref[curPref].expr parse:"z"]; pref[curPref].flag=F_SDATA; /* update the display */ [self setMinMax:self]; [d3View zoom:self]; return self; } /* return a data set to equation mode, free memory used by the file */ -clearFile:sender { if (pref[curPref].fileData!=NULL) { free(pref[curPref].fileData); pref[curPref].fileData=NULL; } pref[curPref].nfdata=0; [equation setText:"0"]; [pref[curPref].expr parse:"0"]; [d3View zoom:self]; return(self); } /* minz and maxz can be modified before returning, but currently aren't */ -minmaxZ:(float *)minz :(float *)maxz { [dminZ setFloatValue:*minz]; [dmaxZ setFloatValue:*maxz]; if ([dzSwitch intValue]) { [minZ setFloatValue:*minz]; [maxZ setFloatValue:*maxz]; } *minz=[minZ floatValue]; *maxz=[maxZ floatValue]; return self; } /* display new min/max values (does not inform the views of the change) */ -setMM:(float)minx :(float)maxx :(float)miny :(float)maxy { [minX setFloatValue:minx]; [minY setFloatValue:miny]; [maxX setFloatValue:maxx]; [maxY setFloatValue:maxy]; return self; } /* Tell the Plot3DView and (indirectly) the DensView about new max/min vals */ -setMinMax:sender { int aspect; aspect=[demAsp intValue]; if (aspect) [maxY setFloatValue:[maxX floatValue]-[minX floatValue]+[minY floatValue]]; [d3View zoomTo:[minX floatValue] :[minY floatValue] :[maxX floatValue] :[maxY floatValue]]; if (aspect) [maxZ setFloatValue:[minZ floatValue]+([maxX floatValue]-[minX floatValue])*83000.0]; [d3View zoom:self]; return self; } -stoMM:sender { sMM[0]=[minX floatValue]; sMM[1]=[minY floatValue]; sMM[2]=[maxX floatValue]; sMM[3]=[maxY floatValue]; return self; } -rclMM:sender { [minX setFloatValue:sMM[0]]; [minY setFloatValue:sMM[1]]; [maxX setFloatValue:sMM[2]]; [maxY setFloatValue:sMM[3]]; [self setMinMax:sender]; return self; } /* zoom in by a fixed amount */ -zoomIn:sender { float x,y,x1,y1; x1=[maxX floatValue]; x=[minX floatValue]; y1=[maxY floatValue]; y=[minY floatValue]; [maxX setFloatValue:x1-(x1-x)/4.0]; [minX setFloatValue:x+(x1-x)/4.0]; [maxY setFloatValue:y1-(y1-y)/4.0]; [minY setFloatValue:y+(y1-y)/4.0]; [self setMinMax:self]; [d3View zoom:self]; return self; } /* zoom out by a fixed amount */ -zoomOut:sender { float x,y,x1,y1; x1=[maxX floatValue]; x=[minX floatValue]; y1=[maxY floatValue]; y=[minY floatValue]; [maxX setFloatValue:x1+(x1-x)/4.0]; [minX setFloatValue:x-(x1-x)/4.0]; [maxY setFloatValue:y1+(y1-y)/4.0]; [minY setFloatValue:y-(y1-y)/4.0]; [self setMinMax:self]; [d3View zoom:self]; return self; } /* sent by DensView, min/max are from 0.0 to 1.0, not real units */ -zoomTo:(float)minx :(float)miny :(float)maxx :(float)maxy { float x0,x1,y0,y1; x0=[minX floatValue]; x1=[maxX floatValue]; y0=[minY floatValue]; y1=[maxY floatValue]; [minX setFloatValue:x0+(x1-x0)*minx]; [minY setFloatValue:y0+(y1-y0)*miny]; [maxX setFloatValue:x0+(x1-x0)*maxx]; [maxY setFloatValue:y0+(y1-y0)*maxy]; [self setMinMax:self]; [d3View zoom:self]; return self; } -dumpContour { [dView saveTiff:self]; return self; } /* update the density plot */ -updDen:(RtPoint)TickO :(RtPoint)TickS { static float *densData=NULL; static int ndd=0; int k,i,nx,ny; NXRect rec,rec2,tick; float x0=0,x1=0,y0=0,y1=0,zlim[4] = { -1.0,1.0,0,0}; char s[80]; float lev0,lev1; zlim[2]=[minZ floatValue]; zlim[3]=[maxZ floatValue]; if ([autoCont intValue]) { i=[[levels cellAt:2 :0] intValue]; lev1=2.0/(float)i; lev0= -1.0+lev1/2.0; [[levels cellAt:0 :0] setFloatValue:(lev0+1.0)/2.0* (zlim[3]-zlim[2])+zlim[2]]; [[levels cellAt:1 :0] setFloatValue:lev1/2.0* (zlim[3]-zlim[2])]; } else { lev0=[[levels cellAt:0 :0] floatValue]; lev1=[[levels cellAt:1 :0] floatValue]; lev0=(lev0-zlim[2])/(zlim[3]-zlim[2])*2.0-1.0; lev1=lev1/(zlim[3]-zlim[2])*2.0; } if (lev1<=0) lev1=.2; [[d3View worldShape] setContour:lev0/2.0+.5 :lev1/2.0]; tick.origin.x=(TickO[0]+1.0)/2.0; tick.origin.y=(TickO[1]+1.0)/2.0; tick.size.width=TickS[0]/2.0; tick.size.height=TickS[1]/2.0; rec2.origin.x=[minX floatValue]; rec2.origin.y=[minY floatValue]; rec2.size.width=[maxX floatValue]-[minX floatValue]; rec2.size.height=[maxY floatValue]-[minY floatValue]; rec=rec2; if (pref[curPref].ndata==0||(pref[curPref].flag&3)==F_SDATA) { [dView setData:0 :0 :NULL :zlim :tick :rec :rec2 :lev0 :lev1 :NULL]; return self; } nx=pref[curPref].nx; ny=pref[curPref].ny; if (ndd<(nx*ny)) { if (densData!=NULL) free(densData); densData=malloc(nx*ny*sizeof(float)); ndd=nx*ny; } if (pref[curPref].fileData==NULL||nx*ny==pref[curPref].ndata) { for (k=0; k<pref[curPref].ndata; k++) densData[k]=pref[curPref].data[k].z; } else { sprintf(s,"Error nx*ny=%d ndata=%d\n",nx*ny,pref[curPref].ndata); [self error:s]; /* for (k=0; k<(nx*ny); k++) densData[k]= -.5; for (k=0; k<pref[curPref].ndata; k++) { i=floor((pref[curPref].data[k].x+.5)*(float)nx)+ floor((pref[curPref].data[k].y+.5)*(float)ny)*nx; if (i>=0 && i<ndd) densData[i]=pref[curPref].data[k].z; }*/ } if (pref[curPref].fileData!=NULL) { for (i=0; i<pref[curPref].nfdata; i++) { x0=pref[curPref].fileData[i].x; y0=pref[curPref].fileData[i].y; if (x0>=rec2.origin.x && y0>=rec2.origin.y) break; } for (i=pref[curPref].nfdata-1; i>=0; i--) { x1=pref[curPref].fileData[i].x; y1=pref[curPref].fileData[i].y; if (x1<=rec2.origin.x+rec2.size.width && y1<=rec2.origin.y+rec2.size.height) break; } rec.size.width=x1-x0; rec.origin.x=x0; rec.size.height=y1-y0; rec.origin.y=y0; } if (pref[curPref].sym!= -1) { if (pref[curPref].mapmode!=0) [dView setData:nx :ny :densData :zlim :tick :rec :rec2 :lev0 :lev1 :pref[curPref].color]; else [dView setData:nx :ny :densData :zlim :tick :rec :rec2 :lev0 :lev1 :NULL]; } else [dView setData:0 :0 :NULL :zlim :tick :rec :rec2 :lev0 :lev1 :NULL]; return self; } int comp(float *x,float *y) { if (x<y) return(-1); if (y>x) return(1); return (0); } -newInsp:sender { int i; i=[[sender selectedCell] tag]; switch(i) { case 0: [I_BOX setContentView:I_lim]; break; case 1: [I_BOX setContentView:I_dis]; break; case 2: [I_BOX setContentView:I_pho]; break; } [I_BOX display]; return self; } /* variable slider changed */ -setVarS:sender { int i; for (i=0; i<5; i++) [[varText cellAt:i :0] setFloatValue:[[varSli cellAt:i :0] floatValue]]; [d3View zoom:self]; return self; } /* variable text changed */ -setVarT:sender { int i; for (i=0; i<5; i++) [[varSli cellAt:i :0] setFloatValue:[[varText cellAt:i :0] floatValue]]; [d3View zoom:self]; return self; } /* new var min/max */ -setVarMinMax:sender { int i; for (i=0; i<5; i++) [[[varSli cellAt:i :0] setMaxValue:[[varMax cellAt:i :0] floatValue]] setMinValue:[[varMin cellAt:i :0] floatValue]]; return self; } -saveData:sender { id pan; FILE *out; int i; float x0,x1,y0,y1,z0,z1; x0=[minX floatValue]; x1=[maxX floatValue]-x0; y0=[minY floatValue]; y1=[maxY floatValue]-y0; z0=[minZ floatValue]; z1=[maxZ floatValue]-z0; pan=[SavePanel new]; if ([pan runModal]) { out=fopen([pan filename],"w"); fprintf(out,"# Created by Plot3D\n"); for (i=0; i<pref[curPref].ndata; i++) fprintf(out,"%f\t%f\t%f\n",(pref[curPref].data[i].x/2.0+.5)*x1+x0, (pref[curPref].data[i].y/2.0+.5)*y1+y0, (pref[curPref].data[i].z/2.0+.5)*z1+z0); fclose(out); } return self; } /* Start rendering an animation */ -makeAnim:sender { int afl=0,n=16,cf; static id savePanel=nil; float chi,chistp,theta,t,tstp; char animFile[100]; /* animation directory */ char animName[30]; /* animation name */ char fsp[MAXPATHLEN]; int i,j=0; if (!savePanel) { savePanel=[SavePanel new]; [savePanel setRequiredFileType:"anim"]; } if(![savePanel runModal]) return self; if (strlen([savePanel filename])>78) { [self error:"Filespec too long. Please notify author."]; return self; } strcpy(animFile, [savePanel filename]); mkdir(animFile,0777); for (i=strlen(animFile)-1; i>=0; i--) if (animFile[i]=='/') break; i++; while (i<strlen(animFile)-5) animName[j++]=animFile[i++]; animName[j]=0; afl=[[animFlag cellAt:0 :0] intValue]*ANIM_spin+ [[animFlag cellAt:1 :0] intValue]*ANIM_t; if (afl==0) { [self error:"Animation doesn't do anything!"]; return self; } n=[animFrames intValue]; chistp=M_PI*2.0/(float)n; chi=[d3View getChi]; theta=[d3View getTheta]; t=[[varMin cellAt:0 :0] floatValue]; tstp=([[varMax cellAt:0 :0] floatValue]-t)/(float)(n-1); for (cf=0; cf<n; cf++) { [[varText cellAt:0 :0] setFloatValue:t]; [[varSli cellAt:0 :0] setFloatValue:t]; [d3View setAng:theta :chi]; [d3View zoom:self]; sprintf(fsp,"%s/%s.%d.tiff",animFile,animName,cf+1); [self message:"Rendering animation. This will take a while ..." :fsp]; [d3View renderTIFF:fsp]; if (afl&ANIM_t) t+=tstp; if (afl&ANIM_spin) chi+=chistp; } [self message:"Rendering complete !!!" :"(use Movie.app or a similar program to view)"]; return self; } -error:(char *)msg { [errTitle setStringValue:"ERROR"]; [errMsg setStringValue:msg]; [errPan makeKeyAndOrderFront:self]; return self; } -message:(char *)s1 :(char *)s2 { [errTitle setStringValue:s1]; [errMsg setStringValue:s2]; [errPan makeKeyAndOrderFront:self]; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.