This is DensView.m in view mode; [Download] [Up]
/* DensView.m Copyright 1992 Steve Ludtke */ /* This object works by taking passed data and rendering it into an NXImage */ /* which is then composited to the screen as necessary. When the view is */ /* resized, the user coordinate system is reset to unit size. Areas can be */ /* selected by dragging with the mouse. A zoomTo:::: message will be sent to*/ /* the delegate with the resulting area. This view now supports both density*/ /* and simple contour plots (2/94) */ #import "Plot3DView.h" #import "DensView.h" #import <stdio.h> #import <string.h> #import <libc.h> #import <math.h> #import <appkit/appkit.h> #import <dpsclient/psops.h> char hex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' }; extern id NXApp; float sgn(float x) { if (x>=0) return(1.0); return(0); } void Strcat(String *s,char *s1) { int i; i=strlen(s1); while (i+s->n>s->al) { s->data=realloc(s->data,s->al+4096); s->al+=4096; } strcat(s->data,s1); s->n+=i; return; } void Strcpy(String *s,char *s1) { int i; i=strlen(s1); while (i>s->al) { s->data=realloc(s->data,s->al+4096); s->al+=4096; } strcpy(s->data,s1); s->n=i; return; } @implementation DensView -initFrame:(NXRect *)myrect { [super initFrame:myrect]; [self setDrawSize:1.0 :1.0]; /* set size and origin so view is a "unit" */ [self setDrawOrigin:0.0 :0.0]; /* coordinate system */ point.y=point.x=0.0; /* origin of image when composited */ buf.al=4096; buf.n=0; buf.data=malloc(4096); data=NULL; image=nil; /* new image is created by -setData::::: */ mode=0; dmode=DM_DENSITY; return self; } -superviewSizeChanged:(const NXSize *)oldsize { [super superviewSizeChanged:oldsize]; [self setDrawSize:1.0 :1.0]; /* fix drawing size */ [self setData:nx :ny :data :Zlim :ticks :rec :rec2 :lev0 :lev1 :color]; /* re-render NXImage */ return self; } /* essentially all this method has to do is composite the NXImage to the */ /* screen. */ -drawSelf:(NXRect *)rects :(int)rectCount { if (buf.n==0||data==NULL||image==nil) { PSsetgray(NX_WHITE); NXRectFill(&bounds); return(self); } if (mode) { DPSWritePostScript(DPSGetCurrentContext(), buf.data, buf.n); } else [image composite:NX_COPY toPoint:&point]; return self; } /* This method receives data and generates the NXImage */ -setData:(int)Nx :(int)Ny :(float *)Data :(float *)ZLim :(NXRect)Ticks :(NXRect)Rec :(NXRect)Rec2 :(float)Lev0 :(float)Lev1 :(RtColor *)Color { NXStream *str; static char s[420]; int i,j,k,n,d,sl; float lev,x[4],y[4],p[4],xx,yy,a; data=Data; nx=Nx; ny=Ny; ticks=Ticks; if (Zlim!=ZLim) { Zlim[0]=ZLim[0]; Zlim[1]=ZLim[1]; Zlim[2]=ZLim[2]; Zlim[3]=ZLim[3]; } rec=Rec; rec2=Rec2; lev0=Lev0; lev1=Lev1; color=Color; if (nx<=0||ny<=0) { if (image!=nil) [image free]; image=nil; [self display]; return self; } /* Since everything conforms properly, it would be quite easy to */ /* generate an EPS file from this data ... */ sprintf(s,"%%!PS-Adobe-2.0 EPSF-2.0\n%%%%Origin:0 0\n%%%%BoundingBox: 0 0 %f %f\n%%%%EndComments\n/picstr 1 string def\ngsave\n", frame.size.width,frame.size.height); Strcpy(&buf,s); if (dmode&DM_LABEL) sprintf(s,"%f %f scale .1 .1 translate /Helvetica .05 selectfont ",frame.size.width/1.1,frame.size.height/1.1); else sprintf(s,"%f %f scale ",frame.size.width,frame.size.height); Strcat(&buf,s); Strcat(&buf,"1 setgray 0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto fill\n"); Strcat(&buf,"/m {moveto} def /d {lineto} def\n"); /* DENSITY PLOT */ if (dmode&DM_DENSITY) { sprintf(s,"gsave %f %f translate\n",-.5/(float)(nx-1),-.5/(float)(ny-1)); Strcat(&buf,s); sprintf(s,"%f %f translate %f %f scale\n", (rec.origin.x-rec2.origin.x)/rec2.size.width, (rec.origin.y-rec2.origin.y)/rec2.size.height, rec.size.width/rec2.size.width,rec.size.height/rec2.size.height); Strcat(&buf,s); if (color!=NULL) { sprintf(s,"%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop} false 3 colorimage\n",nx,ny,nx-1,ny-1); Strcat(&buf,s); i=0; for (n=0; n<(nx*ny); n++) { if (n%40==0) { s[i]='\n'; s[i+1]=0; Strcat(&buf,s); i=0; } for (j=0; j<3; j++) { d=255*color[n][j]; if (d>255) d=255; if (d<0) d=0; s[i++]=hex[d>>4]; s[i++]=hex[d&15]; } } } else { sprintf(s,"%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop} image\n",nx,ny,nx-1,ny-1); Strcat(&buf,s); i=0; for (n=0; n<(nx*ny); n++) { if (n%100==0) { s[i]='\n'; s[i+1]=0; Strcat(&buf,s); i=0; } d=255*(data[n]-Zlim[0])/(Zlim[1]-Zlim[0]); if (d>255) d=255; if (d<0) d=0; s[i++]=hex[d>>4]; s[i++]=hex[d&15]; } } s[i]=0; Strcat(&buf,s); Strcat(&buf," grestore\n"); } /* TICK MESH */ if (dmode&DM_MESH) { sprintf(s,"gsave %f %f translate %f %f scale\n", (rec.origin.x-rec2.origin.x)/rec2.size.width, (rec.origin.y-rec2.origin.y)/rec2.size.height, rec.size.width/rec2.size.width,rec.size.height/rec2.size.height); Strcat(&buf,s); Strcat(&buf,".002 setlinewidth 0 setgray\n"); for (xx=ticks.origin.x; xx<1.0; xx+=ticks.size.width) { sprintf(s,"%f 0 m %f 1 d\n",xx,xx); Strcat(&buf,s); } for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) { sprintf(s,"0 %f m 1 %f d\n",yy,yy); Strcat(&buf,s); } Strcat(&buf,"stroke grestore\n"); } /* DATA MESH */ if (dmode&DM_DMESH) { sprintf(s,"gsave %f %f translate %f %f scale\n", (rec.origin.x-rec2.origin.x)/rec2.size.width, (rec.origin.y-rec2.origin.y)/rec2.size.height, rec.size.width/rec2.size.width,rec.size.height/rec2.size.height); Strcat(&buf,s); Strcat(&buf,".002 setlinewidth 0 setgray\n"); for (xx=0.0; xx<=1.0; xx+=1.0/(float)(nx-1)) { sprintf(s,"%f 0 m %f 1 d\n",xx,xx); Strcat(&buf,s); } for (yy=0.0; yy<=1.0; yy+=1.0/(float)(ny-1)) { sprintf(s,"0 %f m 1 %f d\n",yy,yy); Strcat(&buf,s); } Strcat(&buf,"stroke grestore\n"); } /* CONTOUR PLOT */ if (dmode&DM_CONTOUR) { Strcat(&buf,".002 setlinewidth 0 setgray\n"); sprintf(s,"gsave %f %f translate %f %f scale\n", (rec.origin.x-rec2.origin.x)/rec2.size.width, (rec.origin.y-rec2.origin.y)/rec2.size.height, rec.size.width/rec2.size.width,rec.size.height/rec2.size.height); Strcat(&buf,s); for (lev=lev0; lev<Zlim[1]; lev+=lev1) { for (i=0; i<nx-1; i++) { for (j=0; j<ny-1; j++) { p[0]=data[i+j*nx]-lev; p[1]=data[i+j*nx+1]-lev; p[2]=data[i+j*nx+nx]-lev; p[3]=data[i+j*nx+nx+1]-lev; if ((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=4 &&((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=0)) { k=0; if ((p[0]>0&&p[1]<0)||(p[1]>0&&p[0]<0)) { x[k]=(p[0]/(p[0]-p[1])+(float)i)/(float)(nx-1); y[k]=(float)j/(float)(ny-1); k++; } if ((p[2]>0&&p[3]<0)||(p[3]>0&&p[2]<0)) { x[k]=(p[2]/(p[2]-p[3])+(float)i)/(float)(nx-1); y[k]=(float)(j+1)/(float)(ny-1); k++; } if ((p[0]>0&&p[2]<0)||(p[2]>0&&p[0]<0)) { x[k]=(float)i/(float)(nx-1); y[k]=(p[0]/(p[0]-p[2])+(float)j)/(float)(ny-1); k++; } if ((p[1]>0&&p[3]<0)||(p[3]>0&&p[1]<0)) { x[k]=(float)(i+1)/(float)(nx-1); y[k]=(p[1]/(p[1]-p[3])+(float)j)/(float)(ny-1); k++; } if (k==2) { sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d\n", x[0],y[0],x[1],y[1]); Strcat(&buf,s); } else if (k==4) { sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d %5.3f %5.3f m %5.3f %5.3f d\n",x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[3]); Strcat(&buf,s); } } } } } Strcat(&buf,"stroke grestore\n"); } if (dmode&DM_LABEL) { /* clip & box */ Strcat(&buf,"1 setgray .005 setlinewidth -.1 -.1 m 1 -.1 d 1 0 d 0 0 d 0 1 d -.1 1 d fill\n"); Strcat(&buf,"0 setgray 0 0 m 1 0 d 1 1 d 0 1 d 0 0 d stroke\n"); /* ticks */ sprintf(s,"gsave %f 0 translate %f 1 scale\n", (rec.origin.x-rec2.origin.x)/rec2.size.width, rec.size.width/rec2.size.width); Strcat(&buf,s); for (xx=ticks.origin.x; xx<1.0; xx+=ticks.size.width) { sprintf(s,"%f 0 m %f .03 d\n",xx,xx); Strcat(&buf,s); sprintf(s,"%f .97 m %f 1 d\n",xx,xx); Strcat(&buf,s); a=xx*rec.size.width+rec.origin.x; if (fabs(a)<1.0e-6) a=0; sprintf(s,"(%4.3g) stringwidth pop -2.0 div %4.3f add -.05 m (%4.3g) show\n",a,xx-.02,a); Strcat(&buf,s); } Strcat(&buf,"stroke grestore\n"); sprintf(s,"gsave 0 %f translate 1 %f scale\n", (rec.origin.y-rec2.origin.y)/rec2.size.height, rec.size.height/rec2.size.height); Strcat(&buf,s); for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) { sprintf(s,"0 %f m .03 %f d\n",yy,yy); Strcat(&buf,s); sprintf(s,".97 %f m 1 %f d\n",yy,yy); Strcat(&buf,s); } Strcat(&buf,"90 rotate"); for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) { a=yy*rec.size.height+rec.origin.y; if (fabs(a)<1.0e-6) a=0; sprintf(s,"(%4.3g) stringwidth pop -2.0 div %4.3f add .02 m (%4.3g) show\n",a,yy-.02,a); Strcat(&buf,s); } Strcat(&buf,"stroke grestore\n"); } Strcat(&buf,"\ngrestore\n"); /* send the postscript we generated to an NXImage. */ str=NXOpenMemory(buf.data,buf.n,NX_READONLY); if (image!=nil) [image free]; image=[NXImage alloc]; image=[image initFromStream:str]; NXClose(str); [image setEPSUsedOnResolutionMismatch:YES]; [image setDataRetained:YES]; /*[image setCacheDepthBounded:NO];*/ /* This is how it used to work */ /*DPSWritePostScript(DPSGetCurrentContext(), buf, i);*/ [self display]; return self; } -saveTiff:sender { NXStream *stream; id rep,rep2,im2; NXRect rect = { 0,0,240.0,240.0 }; char home[60],s[80]; float mx[6] = { 1.0,0,0,-1.0,0,240.0 }; float f; sprintf(home,"/tmp/%s",getenv("USER")); if (getenv("USER")==NULL) strcpy(home,"/tmp"); f=[tiffRes floatValue]; if (f<50.0) { f=50.0; [tiffRes setFloatValue:f]; } if (f>400.0) { f=400.0; [tiffRes setFloatValue:f]; } rect.size.width=rect.size.height=mx[5]=f; im2=[[NXImage alloc] initSize:&rect.size]; [im2 setCacheDepthBounded:NO]; [im2 useCacheWithDepth:NX_TwentyFourBitRGBDepth]; rep=[im2 lastRepresentation]; rep2=[image bestRepresentation]; [rep setAlpha:NO]; [rep setNumColors:3]; [im2 lockFocus]; PSsetrgbcolor(1.0,0.0,1.0); PSmoveto(0,0); PSlineto(100.0,100.0); PSstroke(); PSconcat(mx); [rep2 drawIn:&rect]; [im2 unlockFocus]; /*printf("Alpha:%d bits:%d colors:%d\n",[rep hasAlpha],[rep bitsPerSample],[rep numColors]);*/ if (image==nil) return self; stream=NXOpenMemory(NULL,0,NX_WRITEONLY); [im2 writeTIFF:stream]; sprintf(s,"%s/plot3d.tiff",home); NXSaveToFile(stream,s); NXClose(stream); [im2 free]; return self; } -savePS:sender { FILE *out; static id savePanel=nil; if (!savePanel) { savePanel=[SavePanel new]; [savePanel setRequiredFileType:"eps"]; } if([savePanel runModal]) { out=fopen([savePanel filename],"w"); if (out==NULL) return nil; fwrite(buf.data,buf.n,1,out); fclose(out); } return self; } /* Allows the user to select an area of the plot to be passed to the */ /* delegate via a zoomTo:::: message. */ -mouseDown:(NXEvent *)oevent { int oldMask,loop=1; NXEvent *event,evs,e1,e2; float f,dash[2] = { SS,SS }; char s[80]; evs=*oevent; oevent=&evs; [self convertPoint:&oevent->location fromView:nil]; [self lockFocus]; [image composite:NX_COPY toPoint:&point]; e1=*oevent; if (dmode&DM_LABEL) { oevent->location.x=oevent->location.x*1.1-.1; oevent->location.y=oevent->location.y*1.1-.1; } sprintf(s,"(%5.3g,%5.3g)",oevent->location.x*rec2.size.width+rec2.origin.x, oevent->location.y*rec2.size.height+rec2.origin.y); PSselectfont("Helvetica",.04); PSsetgray(0.0); PSmoveto(.03,.01); PSshow(s); PSstroke(); [self unlockFocus]; [window flushWindow]; oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK]; while (loop) { event = [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)]; [self convertPoint:&event->location fromView:nil]; e2=*event; if (dmode&DM_LABEL) { event->location.x=event->location.x*1.1-.1; event->location.y=event->location.y*1.1-.1; } switch (event->type) { case NX_LMOUSEUP: loop = 0; if (event->location.x<oevent->location.x) { f=event->location.x; event->location.x=oevent->location.x; oevent->location.x=f; } if (event->location.y<oevent->location.y) { f=event->location.y; event->location.y=oevent->location.y; oevent->location.y=f; } if (event->location.x-oevent->location.x<.02) break; if (event->location.y-oevent->location.y<.02) break; [delegate zoomTo:oevent->location.x :oevent->location.y :event->location.x :event->location.y]; break; case NX_LMOUSEDRAGGED: [self lockFocus]; PSsetlinewidth(0.0); [image composite:NX_COPY toPoint:&point]; sprintf(s,"(%5.3g,%5.3g) (%5.3g %5.3g)", oevent->location.x*rec2.size.width+rec2.origin.x, oevent->location.y*rec2.size.height+rec2.origin.y, event->location.x*rec2.size.width+rec2.origin.x, event->location.y*rec2.size.height+rec2.origin.y); PSselectfont("Helvetica",.04); PSsetgray(0.0); PSmoveto(.03,.01); PSshow(s); PSstroke(); PSmoveto(e1.location.x,e1.location.y); PSlineto(e2.location.x,e1.location.y); PSlineto(e2.location.x,e2.location.y); PSlineto(e1.location.x,e2.location.y); PSlineto(e1.location.x,e1.location.y); PSsetgray(1.0); PSsetdash(dash,2,0.0); PSgsave(); PSstroke(); PSgrestore(); PSsetgray(0.0); PSsetdash(dash,2,SS); PSstroke(); [self unlockFocus]; [window flushWindow]; break; } } [window setEventMask:oldMask]; return self; } -setDenFlag:sender { dmode=0; if ([[sender cellAt:0 :0] intValue]) dmode+=DM_DENSITY; if ([[sender cellAt:1 :0] intValue]) dmode+=DM_CONTOUR; if ([[sender cellAt:2 :0] intValue]) dmode+=DM_MESH; if ([[sender cellAt:3 :0] intValue]) dmode+=DM_DMESH; if ([[sender cellAt:4 :0] intValue]) dmode+=DM_LABEL; [self setDrawSize:1.0 :1.0]; /* fix drawing size */ [self setData:nx :ny :data :Zlim :ticks :rec :rec2 :lev0 :lev1 :color]; /* re-render NXImage */ return self; } -(int)acceptsFirstMouse { return (YES); } -printPSCode:sender { mode=1; [self setDrawSize:frame.size.width :frame.size.height]; [super printPSCode:sender]; [self setDrawSize:1.0 :1.0]; /* set size and origin so view is a "unit" */ mode=0; return self; } @end
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.