home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Plotting / NXplot3d.3.2 / Source / DensView.m.old < prev    next >
Encoding:
Text File  |  1994-09-16  |  11.4 KB  |  444 lines

  1. /* DensView.m  Copyright 1992 Steve Ludtke */
  2.  
  3. /* This object works by taking passed data and rendering it into an NXImage */
  4. /* which is then composited to the screen as necessary. When the view is    */
  5. /* resized, the user coordinate system is reset to unit size. Areas can be  */ 
  6. /* selected by dragging with the mouse. A zoomTo:::: message will be sent to*/ 
  7. /* the delegate with the resulting area. This view now supports both density*/
  8. /* and simple contour plots (2/94) */
  9.  
  10. #import "Plot3DView.h"
  11. #import "DensView.h"
  12.  
  13. #import <stdio.h>
  14. #import <string.h>
  15. #import <libc.h>
  16. #import <math.h>
  17. #import <appkit/appkit.h>
  18. #import <dpsclient/psops.h>
  19.  
  20. char hex[] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
  21.  
  22. extern id NXApp;
  23.  
  24. float sgn(float x) { if (x>=0) return(1.0); return(0); }
  25.  
  26. void Strcat(String *s,char *s1)
  27. {
  28. int i;
  29.  
  30. i=strlen(s1);
  31. while (i+s->n>s->al) {
  32.     s->data=realloc(s->data,s->al+4096);
  33.     s->al+=4096;
  34. }
  35. strcat(s->data,s1);
  36. s->n+=i;
  37. return;
  38. }
  39.  
  40. void Strcpy(String *s,char *s1)
  41. {
  42. int i;
  43.  
  44. i=strlen(s1);
  45. while (i>s->al) {
  46.     s->data=realloc(s->data,s->al+4096);
  47.     s->al+=4096;
  48. }
  49. strcpy(s->data,s1);
  50. s->n=i;
  51. return;
  52. }
  53.  
  54. @implementation DensView
  55.  
  56. -initFrame:(NXRect *)myrect
  57. {
  58. [super initFrame:myrect];
  59. [self setDrawSize:1.0 :1.0];    /* set size and origin so view is a "unit" */
  60. [self setDrawOrigin:0.0 :0.0];    /* coordinate system */
  61. point.y=point.x=0.0;        /* origin of image when composited */
  62. buf.al=4096;
  63. buf.n=0;
  64. buf.data=malloc(4096);
  65. data=NULL;
  66. image=nil;            /* new image is created by -setData::::: */
  67. mode=0;
  68. dmode=DM_DENSITY;
  69. return self;
  70. }
  71.  
  72. -superviewSizeChanged:(const NXSize *)oldsize
  73. {
  74. [super superviewSizeChanged:oldsize];
  75. [self setDrawSize:1.0 :1.0];            /* fix drawing size */
  76. [self setData:nx :ny :data :Zlim :ticks :rec :rec2 :lev0 :lev1];    /* re-render NXImage */
  77. return self;
  78. }
  79.  
  80. /* essentially all this method has to do is composite the NXImage to the */
  81. /* screen. */
  82. -drawSelf:(NXRect *)rects :(int)rectCount
  83. {
  84.  
  85. if (buf.n==0||data==NULL||image==nil) {
  86.     PSsetgray(NX_WHITE);
  87.     NXRectFill(&bounds);
  88.     return(self);
  89. }
  90.  
  91. if (mode) {
  92.     DPSWritePostScript(DPSGetCurrentContext(), buf.data, buf.n);
  93. }
  94. else [image composite:NX_COPY toPoint:&point];
  95.  
  96. return self;
  97. }
  98.  
  99. /* This method receives data and generates the NXImage */
  100. -setData:(int)Nx :(int)Ny :(float *)Data :(float *)ZLim :(NXRect)Ticks :(NXRect)Rec :(NXRect)Rec2 :(float)Lev0 :(float)Lev1
  101. {
  102. NXStream *str;
  103. static char s[220];
  104. int i,j,k,n,d,sl;
  105. float lev,x[4],y[4],p[4],xx,yy;
  106.  
  107. data=Data;
  108. nx=Nx;
  109. ny=Ny;
  110. ticks=Ticks;
  111. if (Zlim!=ZLim) { Zlim[0]=ZLim[0]; Zlim[1]=ZLim[1]; Zlim[2]=ZLim[2]; Zlim[3]=ZLim[3]; }
  112. rec=Rec;
  113. rec2=Rec2;
  114. lev0=Lev0;
  115. lev1=Lev1;
  116.  
  117. if (nx<=0||ny<=0) { 
  118.     if (image!=nil) [image free]; 
  119.     image=nil;
  120.     [self display];
  121.     return self;
  122. }
  123.  
  124. /* Since everything conforms properly, it would be quite easy to */
  125. /* generate an EPS file from this data ... */
  126. 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);
  127. Strcpy(&buf,s);
  128. sprintf(s,"%f %f scale ",frame.size.width,frame.size.height);
  129. Strcat(&buf,s);
  130. Strcat(&buf,"1 setgray 0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto fill\n");
  131.  
  132. /* DENSITY PLOT */
  133. if (dmode&DM_DENSITY) {
  134.     sprintf(s,"gsave %f %f translate\n",-.5/(float)(nx-1),-.5/(float)(ny-1));
  135.     Strcat(&buf,s);
  136.     sprintf(s,"%f %f translate %f %f scale\n", 
  137.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  138.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  139.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  140.     Strcat(&buf,s);
  141.  
  142.     sprintf(s,"%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop} image\n",nx,ny,nx-1,ny-1);
  143.     Strcat(&buf,s);
  144.     i=0;
  145.     for (n=0; n<(nx*ny); n++) {
  146.         if (n%100==0) { s[i]='\n'; s[i+1]=0; Strcat(&buf,s); i=0; }
  147.         d=255*(data[n]-Zlim[0])/(Zlim[1]-Zlim[0]);
  148.         if (d>255) d=255;
  149.         if (d<0) d=0;
  150.         s[i++]=hex[d>>4];
  151.         s[i++]=hex[d&15];
  152.     }
  153.     s[i]=0;
  154.     Strcat(&buf,s);
  155.     Strcat(&buf," grestore\n");
  156. }
  157. /* TICK MESH */
  158. if (dmode&DM_MESH) {
  159.     sprintf(s,"gsave %f %f translate %f %f scale\n", 
  160.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  161.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  162.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  163.     Strcat(&buf,s);
  164.     Strcat(&buf,".002 setlinewidth 0 setgray\n");
  165.     for (xx=ticks.origin.x; xx<1.0; xx+=ticks.size.width) {
  166.         sprintf(s,"%f 0 moveto %f 1 lineto\n",xx,xx);
  167.         Strcat(&buf,s);
  168.     }
  169.     for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) {
  170.         sprintf(s,"0 %f moveto 1 %f lineto\n",yy,yy);
  171.         Strcat(&buf,s);
  172.     }
  173.     Strcat(&buf,"stroke grestore\n");
  174. }
  175. /* DATA MESH */
  176. if (dmode&DM_DMESH) {
  177.     sprintf(s,"gsave %f %f translate %f %f scale\n", 
  178.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  179.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  180.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  181.     Strcat(&buf,s);
  182.     Strcat(&buf,".002 setlinewidth 0 setgray\n");
  183.     for (xx=0.0; xx<=1.0; xx+=1.0/(float)(nx-1)) {
  184.         sprintf(s,"%f 0 moveto %f 1 lineto\n",xx,xx);
  185.         Strcat(&buf,s);
  186.     }
  187.     for (yy=0.0; yy<=1.0; yy+=1.0/(float)(ny-1)) {
  188.         sprintf(s,"0 %f moveto 1 %f lineto\n",yy,yy);
  189.         Strcat(&buf,s);
  190.     }
  191.     Strcat(&buf,"stroke grestore\n");
  192. }
  193. /* CONTOUR PLOT */
  194. if (dmode&DM_CONTOUR) {
  195.     sprintf(s,"%f %f translate %f %f scale\n", 
  196.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  197.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  198.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  199.     Strcat(&buf,s);
  200.     Strcat(&buf,".002 setlinewidth 0 setgray /m {moveto} def /d {lineto} def\n");
  201.     for (lev=lev0; lev<Zlim[1]; lev+=lev1) {
  202.     for (i=0; i<nx-1; i++) {
  203.         for (j=0; j<ny-1; j++) {
  204.             p[0]=data[i+j*nx]-lev;
  205.             p[1]=data[i+j*nx+1]-lev;
  206.             p[2]=data[i+j*nx+nx]-lev;
  207.             p[3]=data[i+j*nx+nx+1]-lev;
  208.             if ((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=4 
  209.                 &&((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=0)) {
  210.                 k=0;
  211.                 if ((p[0]>0&&p[1]<0)||(p[1]>0&&p[0]<0)) {
  212.                     x[k]=(p[0]/(p[0]-p[1])+(float)i)/(float)(nx-1);
  213.                     y[k]=(float)j/(float)(ny-1);
  214.                     k++;
  215.                 }
  216.                 if ((p[2]>0&&p[3]<0)||(p[3]>0&&p[2]<0)) {
  217.                     x[k]=(p[2]/(p[2]-p[3])+(float)i)/(float)(nx-1);
  218.                     y[k]=(float)(j+1)/(float)(ny-1);
  219.                     k++;
  220.                 }
  221.                 if ((p[0]>0&&p[2]<0)||(p[2]>0&&p[0]<0)) {
  222.                     x[k]=(float)i/(float)(nx-1);
  223.                     y[k]=(p[0]/(p[0]-p[2])+(float)j)/(float)(ny-1);
  224.                     k++;
  225.                 }
  226.                 if ((p[1]>0&&p[3]<0)||(p[3]>0&&p[1]<0)) {
  227.                     x[k]=(float)(i+1)/(float)(nx-1);
  228.                     y[k]=(p[1]/(p[1]-p[3])+(float)j)/(float)(ny-1);
  229.                     k++;
  230.                 }
  231.                 if (k==2) { 
  232.                     sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d\n", x[0],y[0],x[1],y[1]);
  233.                     Strcat(&buf,s);
  234.                 }
  235.                 else if (k==4) {
  236.                     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]);
  237.                     Strcat(&buf,s);
  238.                 }
  239.             }
  240.         }
  241.     }
  242.     }
  243.     Strcat(&buf,"stroke\n");
  244. }
  245. Strcat(&buf,"\ngrestore\n");
  246.  
  247. /* send the postscript we generated to an NXImage. */
  248. str=NXOpenMemory(buf.data,buf.n,NX_READONLY);
  249. if (image!=nil) [image free];
  250. image=[NXImage alloc];
  251. image=[image initFromStream:str];
  252. NXClose(str);
  253. [image setEPSUsedOnResolutionMismatch:YES];
  254. [image setDataRetained:YES];
  255. /*[image setCacheDepthBounded:NO];*/
  256.  
  257. /* This is how it used to work */
  258. /*DPSWritePostScript(DPSGetCurrentContext(), buf, i);*/
  259.  
  260. [self display];
  261. return self;
  262. }
  263.  
  264. -saveTiff:sender
  265. {
  266. NXStream *stream;
  267. id rep,rep2,im2;
  268. NXRect rect = { 0,0,240.0,240.0 };
  269. char home[60],s[80];
  270. float mx[6] = { 1.0,0,0,-1.0,0,240.0 };
  271. float f;
  272.  
  273. sprintf(home,"/tmp/%s",getenv("USER"));
  274. if (getenv("USER")==NULL) strcpy(home,"/tmp"); 
  275.  
  276. f=[tiffRes floatValue];
  277. if (f<50.0) { f=50.0; [tiffRes setFloatValue:f]; }
  278. if (f>400.0) { f=400.0; [tiffRes setFloatValue:f]; }
  279. rect.size.width=rect.size.height=mx[5]=f;
  280.  
  281. im2=[[NXImage alloc] initSize:&rect.size];
  282. [im2 setCacheDepthBounded:NO];
  283. [im2 useCacheWithDepth:NX_TwentyFourBitRGBDepth];
  284. rep=[im2 lastRepresentation];
  285. rep2=[image bestRepresentation];
  286. [rep setAlpha:NO];
  287. [rep setNumColors:3];
  288. [im2 lockFocus];
  289. PSsetrgbcolor(1.0,0.0,1.0);
  290. PSmoveto(0,0);
  291. PSlineto(100.0,100.0);
  292. PSstroke();
  293. PSconcat(mx);
  294. [rep2 drawIn:&rect];
  295. [im2 unlockFocus];
  296. /*printf("Alpha:%d bits:%d colors:%d\n",[rep hasAlpha],[rep bitsPerSample],[rep numColors]);*/
  297.  
  298. if (image==nil) return self;
  299. stream=NXOpenMemory(NULL,0,NX_WRITEONLY);
  300. [im2 writeTIFF:stream];
  301. sprintf(s,"%s/plot3d.tiff",home);
  302. NXSaveToFile(stream,s);
  303. NXClose(stream);
  304.  
  305. [im2 free];
  306. return self;
  307. }
  308.  
  309. -savePS:sender
  310. {
  311. FILE *out;
  312. static id savePanel=nil;
  313.  
  314. if (!savePanel) {
  315.   savePanel=[SavePanel new];
  316.   [savePanel setRequiredFileType:"eps"];
  317. }
  318.  
  319. if([savePanel runModal]) {
  320.     out=fopen([savePanel filename],"w");
  321.     if (out==NULL) return nil;
  322.     fwrite(buf.data,buf.n,1,out);
  323.     fclose(out);
  324. }
  325. return self;
  326. }
  327.  
  328. /* Allows the user to select an area of the plot to be passed to the */
  329. /* delegate via a zoomTo:::: message. */
  330. -mouseDown:(NXEvent *)oevent 
  331. {
  332. int oldMask,loop=1;
  333. NXEvent *event,evs;
  334. float f,dash[2] = { SS,SS };
  335. char s[80];
  336.  
  337. evs=*oevent;
  338. oevent=&evs;
  339. [self convertPoint:&oevent->location fromView:nil];
  340.  
  341. [self lockFocus];
  342. [image composite:NX_COPY toPoint:&point];
  343. sprintf(s,"(%5.3g,%5.3g)",oevent->location.x*rec2.size.width+rec2.origin.x,
  344.     oevent->location.y*rec2.size.height+rec2.origin.y);
  345. PSselectfont("Helvetica",.04);
  346. PSsetgray(0.0);
  347. PSmoveto(.05,.05);
  348. PSshow(s);
  349. PSstroke();
  350. [self unlockFocus];
  351. [window flushWindow];
  352.  
  353. oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  354.  
  355. while (loop) {
  356.     event = [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
  357.     [self convertPoint:&event->location fromView:nil];
  358.  
  359.         switch (event->type) {
  360.         case NX_LMOUSEUP:
  361.                 loop = 0;
  362.         if (event->location.x<oevent->location.x) {
  363.             f=event->location.x;
  364.             event->location.x=oevent->location.x; 
  365.             oevent->location.x=f; 
  366.         }
  367.         if (event->location.y<oevent->location.y) {
  368.             f=event->location.y;
  369.             event->location.y=oevent->location.y; 
  370.             oevent->location.y=f; 
  371.         }
  372.         if (event->location.x-oevent->location.x<.02) break;
  373.         if (event->location.y-oevent->location.y<.02) break;
  374.         [delegate zoomTo:oevent->location.x :oevent->location.y :event->location.x :event->location.y];
  375.             break;
  376.         case NX_LMOUSEDRAGGED:
  377.         [self lockFocus];
  378.         PSsetlinewidth(0.0);
  379.         [image composite:NX_COPY toPoint:&point];
  380.  
  381.         sprintf(s,"(%5.3g,%5.3g) (%5.3g %5.3g)",
  382.             oevent->location.x*rec2.size.width+rec2.origin.x,
  383.             oevent->location.y*rec2.size.height+rec2.origin.y,
  384.             event->location.x*rec2.size.width+rec2.origin.x,
  385.             event->location.y*rec2.size.height+rec2.origin.y);
  386.         PSselectfont("Helvetica",.04);
  387.         PSsetgray(0.0);
  388.         PSmoveto(.05,.05);
  389.         PSshow(s);
  390.         PSstroke();
  391.  
  392.         PSmoveto(oevent->location.x,oevent->location.y);
  393.         PSlineto(event->location.x,oevent->location.y);
  394.         PSlineto(event->location.x,event->location.y);
  395.         PSlineto(oevent->location.x,event->location.y);
  396.         PSlineto(oevent->location.x,oevent->location.y);
  397.  
  398.         PSsetgray(1.0);
  399.         PSsetdash(dash,2,0.0);
  400.         PSgsave();
  401.         PSstroke();
  402.         PSgrestore();
  403.  
  404.         PSsetgray(0.0);
  405.         PSsetdash(dash,2,SS);
  406.         PSstroke();
  407.  
  408.         [self unlockFocus];
  409.         [window flushWindow];
  410.         break;
  411.     }
  412.     
  413. }
  414. [window setEventMask:oldMask];
  415. return self;
  416. }
  417.  
  418. -setDenFlag:sender
  419. {
  420. dmode=0;
  421. if ([[sender cellAt:0 :0] intValue]) dmode+=DM_DENSITY;
  422. if ([[sender cellAt:1 :0] intValue]) dmode+=DM_CONTOUR;
  423. if ([[sender cellAt:2 :0] intValue]) dmode+=DM_MESH;
  424. if ([[sender cellAt:3 :0] intValue]) dmode+=DM_DMESH;
  425. [self setData:nx :ny :data :Zlim :ticks :rec :rec2 :lev0 :lev1];    /* re-render NXImage */
  426. return self;
  427. }
  428.  
  429. -(int)acceptsFirstMouse {
  430. return (YES);
  431. }
  432.  
  433. -printPSCode:sender
  434. {
  435. mode=1;
  436. [self setDrawSize:frame.size.width :frame.size.height];    
  437. [super printPSCode:sender];
  438. [self setDrawSize:1.0 :1.0];    /* set size and origin so view is a "unit" */
  439. mode=0;
  440. return self;
  441. }
  442.  
  443. @end
  444.