home *** CD-ROM | disk | FTP | other *** search
- /* 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
-