home *** CD-ROM | disk | FTP | other *** search
/ Nebula 1 / Nebula One.iso / Graphics / Plotting / NXplot3d.3.2 / Source / DensView.m < prev    next >
Encoding:
Text File  |  1994-09-16  |  13.7 KB  |  518 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 :color];    /* 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 :(RtColor *)Color
  101. {
  102. NXStream *str;
  103. static char s[420];
  104. int i,j,k,n,d,sl;
  105. float lev,x[4],y[4],p[4],xx,yy,a;
  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. color=Color;
  117.  
  118. if (nx<=0||ny<=0) { 
  119.     if (image!=nil) [image free]; 
  120.     image=nil;
  121.     [self display];
  122.     return self;
  123. }
  124.  
  125. /* Since everything conforms properly, it would be quite easy to */
  126. /* generate an EPS file from this data ... */
  127. 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);
  128. Strcpy(&buf,s);
  129. 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);
  130. else sprintf(s,"%f %f scale ",frame.size.width,frame.size.height);
  131. Strcat(&buf,s);
  132. Strcat(&buf,"1 setgray 0 0 moveto 1 0 lineto 1 1 lineto 0 1 lineto fill\n");
  133. Strcat(&buf,"/m {moveto} def /d {lineto} def\n");
  134.  
  135. /* DENSITY PLOT */
  136. if (dmode&DM_DENSITY) {
  137.     sprintf(s,"gsave %f %f translate\n",-.5/(float)(nx-1),-.5/(float)(ny-1));
  138.     Strcat(&buf,s);
  139.     sprintf(s,"%f %f translate %f %f scale\n", 
  140.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  141.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  142.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  143.     Strcat(&buf,s);
  144.  
  145.     if (color!=NULL) {
  146.         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);
  147.         Strcat(&buf,s);
  148.         i=0;
  149.         for (n=0; n<(nx*ny); n++) {
  150.             if (n%40==0) { s[i]='\n'; s[i+1]=0; Strcat(&buf,s); i=0; }
  151.             for (j=0; j<3; j++) {
  152.                    d=255*color[n][j];
  153.                   if (d>255) d=255;
  154.                   if (d<0) d=0;
  155.                   s[i++]=hex[d>>4];
  156.                   s[i++]=hex[d&15];
  157.             }
  158.         }
  159.     }
  160.     else {
  161.         sprintf(s,"%d %d 8 [%d 0 0 %d 0 0] {currentfile picstr readhexstring pop} image\n",nx,ny,nx-1,ny-1);
  162.         Strcat(&buf,s);
  163.         i=0;
  164.         for (n=0; n<(nx*ny); n++) {
  165.             if (n%100==0) { s[i]='\n'; s[i+1]=0; Strcat(&buf,s); i=0; }
  166.               d=255*(data[n]-Zlim[0])/(Zlim[1]-Zlim[0]);
  167.               if (d>255) d=255;
  168.               if (d<0) d=0;
  169.               s[i++]=hex[d>>4];
  170.               s[i++]=hex[d&15];
  171.         }
  172.     }
  173.  
  174.     s[i]=0;
  175.     Strcat(&buf,s);
  176.     Strcat(&buf," grestore\n");
  177. }
  178. /* TICK MESH */
  179. if (dmode&DM_MESH) {
  180.     sprintf(s,"gsave %f %f translate %f %f scale\n", 
  181.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  182.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  183.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  184.     Strcat(&buf,s);
  185.     Strcat(&buf,".002 setlinewidth 0 setgray\n");
  186.     for (xx=ticks.origin.x; xx<1.0; xx+=ticks.size.width) {
  187.         sprintf(s,"%f 0 m %f 1 d\n",xx,xx);
  188.         Strcat(&buf,s);
  189.     }
  190.     for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) {
  191.         sprintf(s,"0 %f m 1 %f d\n",yy,yy);
  192.         Strcat(&buf,s);
  193.     }
  194.     Strcat(&buf,"stroke grestore\n");
  195. }
  196. /* DATA MESH */
  197. if (dmode&DM_DMESH) {
  198.     sprintf(s,"gsave %f %f translate %f %f scale\n", 
  199.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  200.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  201.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  202.     Strcat(&buf,s);
  203.     Strcat(&buf,".002 setlinewidth 0 setgray\n");
  204.     for (xx=0.0; xx<=1.0; xx+=1.0/(float)(nx-1)) {
  205.         sprintf(s,"%f 0 m %f 1 d\n",xx,xx);
  206.         Strcat(&buf,s);
  207.     }
  208.     for (yy=0.0; yy<=1.0; yy+=1.0/(float)(ny-1)) {
  209.         sprintf(s,"0 %f m 1 %f d\n",yy,yy);
  210.         Strcat(&buf,s);
  211.     }
  212.     Strcat(&buf,"stroke grestore\n");
  213. }
  214. /* CONTOUR PLOT */
  215. if (dmode&DM_CONTOUR) {
  216.     Strcat(&buf,".002 setlinewidth 0 setgray\n");
  217.     sprintf(s,"gsave %f %f translate %f %f scale\n", 
  218.         (rec.origin.x-rec2.origin.x)/rec2.size.width, 
  219.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  220.         rec.size.width/rec2.size.width,rec.size.height/rec2.size.height);
  221.     Strcat(&buf,s);
  222.     for (lev=lev0; lev<Zlim[1]; lev+=lev1) {
  223.     for (i=0; i<nx-1; i++) {
  224.         for (j=0; j<ny-1; j++) {
  225.             p[0]=data[i+j*nx]-lev;
  226.             p[1]=data[i+j*nx+1]-lev;
  227.             p[2]=data[i+j*nx+nx]-lev;
  228.             p[3]=data[i+j*nx+nx+1]-lev;
  229.             if ((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=4 
  230.                 &&((sgn(p[0])+sgn(p[1])+sgn(p[2])+sgn(p[3]))!=0)) {
  231.                 k=0;
  232.                 if ((p[0]>0&&p[1]<0)||(p[1]>0&&p[0]<0)) {
  233.                     x[k]=(p[0]/(p[0]-p[1])+(float)i)/(float)(nx-1);
  234.                     y[k]=(float)j/(float)(ny-1);
  235.                     k++;
  236.                 }
  237.                 if ((p[2]>0&&p[3]<0)||(p[3]>0&&p[2]<0)) {
  238.                     x[k]=(p[2]/(p[2]-p[3])+(float)i)/(float)(nx-1);
  239.                     y[k]=(float)(j+1)/(float)(ny-1);
  240.                     k++;
  241.                 }
  242.                 if ((p[0]>0&&p[2]<0)||(p[2]>0&&p[0]<0)) {
  243.                     x[k]=(float)i/(float)(nx-1);
  244.                     y[k]=(p[0]/(p[0]-p[2])+(float)j)/(float)(ny-1);
  245.                     k++;
  246.                 }
  247.                 if ((p[1]>0&&p[3]<0)||(p[3]>0&&p[1]<0)) {
  248.                     x[k]=(float)(i+1)/(float)(nx-1);
  249.                     y[k]=(p[1]/(p[1]-p[3])+(float)j)/(float)(ny-1);
  250.                     k++;
  251.                 }
  252.                 if (k==2) { 
  253.                     sprintf(s,"%5.3f %5.3f m %5.3f %5.3f d\n", x[0],y[0],x[1],y[1]);
  254.                     Strcat(&buf,s);
  255.                 }
  256.                 else if (k==4) {
  257.                     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]);
  258.                     Strcat(&buf,s);
  259.                 }
  260.             }
  261.         }
  262.     }
  263.     }
  264.     Strcat(&buf,"stroke grestore\n");
  265. }
  266. if (dmode&DM_LABEL) {
  267.     /* clip & box */
  268.     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"); 
  269.     Strcat(&buf,"0 setgray 0 0 m 1 0 d 1 1 d 0 1 d 0 0 d stroke\n");
  270.  
  271.     /* ticks */
  272.     sprintf(s,"gsave %f 0 translate %f 1 scale\n", 
  273.         (rec.origin.x-rec2.origin.x)/rec2.size.width,
  274.         rec.size.width/rec2.size.width);
  275.     Strcat(&buf,s);
  276.     for (xx=ticks.origin.x; xx<1.0; xx+=ticks.size.width) {
  277.         sprintf(s,"%f 0 m %f .03 d\n",xx,xx);
  278.         Strcat(&buf,s);
  279.         sprintf(s,"%f .97 m %f 1 d\n",xx,xx);
  280.         Strcat(&buf,s);
  281.         a=xx*rec.size.width+rec.origin.x;
  282.         if (fabs(a)<1.0e-6) a=0;
  283.         sprintf(s,"(%4.3g) stringwidth pop -2.0 div %4.3f add -.05 m (%4.3g) show\n",a,xx-.02,a);
  284.         Strcat(&buf,s);
  285.     }
  286.     Strcat(&buf,"stroke grestore\n");
  287.     sprintf(s,"gsave 0 %f translate 1 %f scale\n", 
  288.         (rec.origin.y-rec2.origin.y)/rec2.size.height,
  289.         rec.size.height/rec2.size.height);
  290.     Strcat(&buf,s);
  291.     for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) {
  292.         sprintf(s,"0 %f m .03 %f d\n",yy,yy);
  293.         Strcat(&buf,s);
  294.         sprintf(s,".97 %f m 1 %f d\n",yy,yy);
  295.         Strcat(&buf,s);
  296.     }
  297.     Strcat(&buf,"90 rotate");
  298.     for (yy=ticks.origin.y; yy<1.0; yy+=ticks.size.height) {
  299.         a=yy*rec.size.height+rec.origin.y;
  300.         if (fabs(a)<1.0e-6) a=0;
  301.         sprintf(s,"(%4.3g) stringwidth pop -2.0 div %4.3f add .02 m (%4.3g) show\n",a,yy-.02,a);
  302.         Strcat(&buf,s);
  303.     }
  304.     Strcat(&buf,"stroke grestore\n");
  305.  
  306. }
  307. Strcat(&buf,"\ngrestore\n");
  308.  
  309. /* send the postscript we generated to an NXImage. */
  310. str=NXOpenMemory(buf.data,buf.n,NX_READONLY);
  311. if (image!=nil) [image free];
  312. image=[NXImage alloc];
  313. image=[image initFromStream:str];
  314. NXClose(str);
  315. [image setEPSUsedOnResolutionMismatch:YES];
  316. [image setDataRetained:YES];
  317. /*[image setCacheDepthBounded:NO];*/
  318.  
  319. /* This is how it used to work */
  320. /*DPSWritePostScript(DPSGetCurrentContext(), buf, i);*/
  321.  
  322. [self display];
  323. return self;
  324. }
  325.  
  326. -saveTiff:sender
  327. {
  328. NXStream *stream;
  329. id rep,rep2,im2;
  330. NXRect rect = { 0,0,240.0,240.0 };
  331. char home[60],s[80];
  332. float mx[6] = { 1.0,0,0,-1.0,0,240.0 };
  333. float f;
  334.  
  335. sprintf(home,"/tmp/%s",getenv("USER"));
  336. if (getenv("USER")==NULL) strcpy(home,"/tmp"); 
  337.  
  338. f=[tiffRes floatValue];
  339. if (f<50.0) { f=50.0; [tiffRes setFloatValue:f]; }
  340. if (f>400.0) { f=400.0; [tiffRes setFloatValue:f]; }
  341. rect.size.width=rect.size.height=mx[5]=f;
  342.  
  343. im2=[[NXImage alloc] initSize:&rect.size];
  344. [im2 setCacheDepthBounded:NO];
  345. [im2 useCacheWithDepth:NX_TwentyFourBitRGBDepth];
  346. rep=[im2 lastRepresentation];
  347. rep2=[image bestRepresentation];
  348. [rep setAlpha:NO];
  349. [rep setNumColors:3];
  350. [im2 lockFocus];
  351. PSsetrgbcolor(1.0,0.0,1.0);
  352. PSmoveto(0,0);
  353. PSlineto(100.0,100.0);
  354. PSstroke();
  355. PSconcat(mx);
  356. [rep2 drawIn:&rect];
  357. [im2 unlockFocus];
  358. /*printf("Alpha:%d bits:%d colors:%d\n",[rep hasAlpha],[rep bitsPerSample],[rep numColors]);*/
  359.  
  360. if (image==nil) return self;
  361. stream=NXOpenMemory(NULL,0,NX_WRITEONLY);
  362. [im2 writeTIFF:stream];
  363. sprintf(s,"%s/plot3d.tiff",home);
  364. NXSaveToFile(stream,s);
  365. NXClose(stream);
  366.  
  367. [im2 free];
  368. return self;
  369. }
  370.  
  371. -savePS:sender
  372. {
  373. FILE *out;
  374. static id savePanel=nil;
  375.  
  376. if (!savePanel) {
  377.   savePanel=[SavePanel new];
  378.   [savePanel setRequiredFileType:"eps"];
  379. }
  380.  
  381. if([savePanel runModal]) {
  382.     out=fopen([savePanel filename],"w");
  383.     if (out==NULL) return nil;
  384.     fwrite(buf.data,buf.n,1,out);
  385.     fclose(out);
  386. }
  387. return self;
  388. }
  389.  
  390. /* Allows the user to select an area of the plot to be passed to the */
  391. /* delegate via a zoomTo:::: message. */
  392. -mouseDown:(NXEvent *)oevent 
  393. {
  394. int oldMask,loop=1;
  395. NXEvent *event,evs,e1,e2;
  396. float f,dash[2] = { SS,SS };
  397. char s[80];
  398.  
  399. evs=*oevent;
  400. oevent=&evs;
  401. [self convertPoint:&oevent->location fromView:nil];
  402.  
  403. [self lockFocus];
  404. [image composite:NX_COPY toPoint:&point];
  405. e1=*oevent;
  406. if (dmode&DM_LABEL) {
  407.         oevent->location.x=oevent->location.x*1.1-.1;
  408.         oevent->location.y=oevent->location.y*1.1-.1;
  409. }
  410. sprintf(s,"(%5.3g,%5.3g)",oevent->location.x*rec2.size.width+rec2.origin.x,
  411.     oevent->location.y*rec2.size.height+rec2.origin.y);
  412. PSselectfont("Helvetica",.04);
  413. PSsetgray(0.0);
  414. PSmoveto(.03,.01);
  415. PSshow(s);
  416. PSstroke();
  417. [self unlockFocus];
  418. [window flushWindow];
  419.  
  420. oldMask = [window addToEventMask:NX_LMOUSEDRAGGEDMASK];
  421.  
  422. while (loop) {
  423.     event = [NXApp getNextEvent:(NX_LMOUSEUPMASK | NX_LMOUSEDRAGGEDMASK)];
  424.     [self convertPoint:&event->location fromView:nil];
  425.     e2=*event;
  426.     if (dmode&DM_LABEL) {
  427.         event->location.x=event->location.x*1.1-.1;
  428.         event->location.y=event->location.y*1.1-.1;
  429.     }
  430.  
  431.         switch (event->type) {
  432.         case NX_LMOUSEUP:
  433.                 loop = 0;
  434.         if (event->location.x<oevent->location.x) {
  435.             f=event->location.x;
  436.             event->location.x=oevent->location.x; 
  437.             oevent->location.x=f; 
  438.         }
  439.         if (event->location.y<oevent->location.y) {
  440.             f=event->location.y;
  441.             event->location.y=oevent->location.y; 
  442.             oevent->location.y=f; 
  443.         }
  444.         if (event->location.x-oevent->location.x<.02) break;
  445.         if (event->location.y-oevent->location.y<.02) break;
  446.         [delegate zoomTo:oevent->location.x :oevent->location.y :event->location.x :event->location.y];
  447.             break;
  448.         case NX_LMOUSEDRAGGED:
  449.         [self lockFocus];
  450.         PSsetlinewidth(0.0);
  451.         [image composite:NX_COPY toPoint:&point];
  452.  
  453.         sprintf(s,"(%5.3g,%5.3g) (%5.3g %5.3g)",
  454.             oevent->location.x*rec2.size.width+rec2.origin.x,
  455.             oevent->location.y*rec2.size.height+rec2.origin.y,
  456.             event->location.x*rec2.size.width+rec2.origin.x,
  457.             event->location.y*rec2.size.height+rec2.origin.y);
  458.         PSselectfont("Helvetica",.04);
  459.         PSsetgray(0.0);
  460.         PSmoveto(.03,.01);
  461.         PSshow(s);
  462.         PSstroke();
  463.  
  464.         PSmoveto(e1.location.x,e1.location.y);
  465.         PSlineto(e2.location.x,e1.location.y);
  466.         PSlineto(e2.location.x,e2.location.y);
  467.         PSlineto(e1.location.x,e2.location.y);
  468.         PSlineto(e1.location.x,e1.location.y);
  469.  
  470.         PSsetgray(1.0);
  471.         PSsetdash(dash,2,0.0);
  472.         PSgsave();
  473.         PSstroke();
  474.         PSgrestore();
  475.  
  476.         PSsetgray(0.0);
  477.         PSsetdash(dash,2,SS);
  478.         PSstroke();
  479.  
  480.         [self unlockFocus];
  481.         [window flushWindow];
  482.         break;
  483.     }
  484.     
  485. }
  486. [window setEventMask:oldMask];
  487. return self;
  488. }
  489.  
  490. -setDenFlag:sender
  491. {
  492. dmode=0;
  493. if ([[sender cellAt:0 :0] intValue]) dmode+=DM_DENSITY;
  494. if ([[sender cellAt:1 :0] intValue]) dmode+=DM_CONTOUR;
  495. if ([[sender cellAt:2 :0] intValue]) dmode+=DM_MESH;
  496. if ([[sender cellAt:3 :0] intValue]) dmode+=DM_DMESH;
  497. if ([[sender cellAt:4 :0] intValue]) dmode+=DM_LABEL;
  498. [self setDrawSize:1.0 :1.0];            /* fix drawing size */
  499. [self setData:nx :ny :data :Zlim :ticks :rec :rec2 :lev0 :lev1 :color];    /* re-render NXImage */
  500. return self;
  501. }
  502.  
  503. -(int)acceptsFirstMouse {
  504. return (YES);
  505. }
  506.  
  507. -printPSCode:sender
  508. {
  509. mode=1;
  510. [self setDrawSize:frame.size.width :frame.size.height];    
  511. [super printPSCode:sender];
  512. [self setDrawSize:1.0 :1.0];    /* set size and origin so view is a "unit" */
  513. mode=0;
  514. return self;
  515. }
  516.  
  517. @end
  518.