/* Steven Andrews, 8/25/02 */ /* See documentation called Plot3D doc */ /* Copyright 2003 by Steven Andrews. Permission is granted for non-commercial use of and modifications to the code. */ #include #include #include #include "DiskIO.h" #include "Plot.h" #include "Plot3D.h" #include "Rn.h" float *p2o3D,*p2s3D,*work3D1,*work3D2; int stereo3D; float *penpos3Ds; float dist3D,sep3D; int Init3DPlot(int stereo,float dist,float sep) { float alpha; p2o3D=allocM(3,3); p2s3D=allocM(3,3); work3D1=allocM(3,3); work3D2=allocM(3,3); penpos3Ds=allocV(2); if(!p2o3D||!p2s3D||!work3D1||!work3D2||!penpos3Ds) return 1; InitPlot(); stereo3D=stereo; dist3D=dist; sep3D=sep; if(stereo) SetScales(-1,3,-1,1); else SetScales(-1,1,-1,1); setstdM(p2o3D,3,3,1); setstdM(p2s3D,3,3,1); if(stereo) { alpha=atan(sep/(2*dist)); Rotate3D(29,2*alpha); setstdM(p2s3D,3,3,1); Rotate3D(28,alpha); } setstdV(penpos3Ds,2,0); return 0; } Pt3Dptr Pt3DAlloc() { Pt3Dptr pt; pt=(Pt3Dptr) malloc(sizeof(struct Point3D)); if(!pt) return NULL; pt->r[0]=pt->r[1]=pt->r[2]=0; pt->p[0]=pt->p[1]=pt->p[2]=0; pt->o[0]=pt->o[1]=pt->o[2]=0; pt->s[0]=pt->s[1]=pt->s[2]=0; pt->r2p=NULL; return pt; } void Pt3DFree(Pt3Dptr pt) { if(pt) free(pt); return; } void PlotPt3D(Pt3Dptr pt) { PlotPt(pt->o[0],pt->o[1]); if(stereo3D) { PlotPt(pt->s[0]+2,pt->s[1]); penpos3Ds[0]=pt->s[0]+2; penpos3Ds[1]=pt->s[1]; PlotMove(pt->o[0],pt->o[1]); } return; } void PlotLine3D(Pt3Dptr pt) { PlotLine(pt->o[0],pt->o[1]); if(stereo3D) { PlotMove(penpos3Ds[0],penpos3Ds[1]); PlotLine(pt->s[0]+2,pt->s[1]); penpos3Ds[0]=pt->s[0]+2; penpos3Ds[1]=pt->s[1]; PlotMove(pt->o[0],pt->o[1]); } return; } void PlotStr3D(Pt3Dptr pt,char *s) { PlotStr(pt->o[0],pt->o[1],s); if(stereo3D) { PlotStr(pt->s[0]+2,pt->s[1],s); penpos3Ds[0]=pt->s[0]+2; penpos3Ds[1]=pt->s[1]; PlotMove(pt->o[0],pt->o[1]); } return; } void Rotate3D(char c,float alpha) { float *m,*temp; if(!c) return; m=work3D1; setstdM(m,3,3,1); if(c==31) {m[4]=m[8]=cos(alpha);m[5]=-(m[7]=sin(alpha)); } else if(c==30) {m[4]=m[8]=cos(alpha);m[5]=-(m[7]=-sin(alpha)); } else if(c==28) {m[0]=m[8]=cos(alpha);m[2]=-(m[6]=sin(alpha)); } else if(c==29) {m[0]=m[8]=cos(alpha);m[2]=-(m[6]=-sin(alpha)); } else if(c=='.') {m[0]=m[4]=cos(alpha);m[1]=-(m[3]=sin(alpha)); } else if(c=='/') {m[0]=m[4]=cos(alpha);m[1]=-(m[3]=-sin(alpha)); } else return; dotMM(m,p2o3D,work3D2,3,3,3); temp=p2o3D;p2o3D=work3D2;work3D2=temp; if(stereo3D) { dotMM(m,p2s3D,work3D2,3,3,3); temp=p2s3D;p2s3D=work3D2;work3D2=temp; } return; } void UpdatePt3D(Pt3Dptr pt,int internal) { if(internal&&pt->r2p) dotVM(pt->r,pt->r2p,pt->p,3,3); dotMV(p2o3D,pt->p,pt->o,3,3); pt->o[0]*=dist3D/(dist3D-pt->o[2]); pt->o[1]*=dist3D/(dist3D-pt->o[2]); if(stereo3D) { dotMV(p2s3D,pt->p,pt->s,3,3); pt->s[0]*=dist3D/(dist3D-pt->s[2]); pt->s[1]*=dist3D/(dist3D-pt->s[2]); } return; } Draw3Dptr Draw3DAlloc(int max,float *r2p) { Draw3Dptr dr; Pt3Dptr pt; int i; dr=(Draw3Dptr) malloc(sizeof(struct Drawing3D)); if(!dr) return NULL; dr->max=max; dr->n=0; dr->pt=NULL; dr->col=NULL; dr->line=NULL; dr->r2p=r2p; dr->pt=(Pt3Dptr *) calloc(sizeof(Pt3Dptr),max); if(dr->pt) for(i=0;ipt[i]=NULL; dr->col=(char *) calloc(sizeof(char),max); dr->line=(int *) calloc(sizeof(int),max); if(!dr->pt||!dr->col||!dr->line) {Draw3DFree(dr);return NULL;} for(i=0;ipt[i]=Pt3DAlloc(); if(!pt) {Draw3DFree(dr);return NULL;} pt->r[0]=pt->r[1]=pt->r[2]=0; pt->p[0]=pt->p[1]=pt->p[2]=0; pt->o[0]=pt->o[1]=pt->o[2]=0; pt->s[0]=pt->s[1]=pt->s[2]=0; pt->r2p=r2p; dr->col[i]='0'; dr->line[i]=0; } return dr; } void Draw3DFree(Draw3Dptr dr) { int i; if(!dr) return; if(dr->pt) for(i=0;imax;i++) Pt3DFree(dr->pt[i]); if(dr->pt) free(dr->pt); if(dr->col) free(dr->col); if(dr->line) free(dr->line); free(dr); return; } int DrawingPt3D(Draw3Dptr dr,float x,float y,float z,int rel,int line,int col) { int n; Pt3Dptr pt; if(dr->n==dr->max) return 1; n=dr->n++; pt=dr->pt[n]; if(rel) {pt->r[0]=x;pt->r[1]=y;pt->r[2]=z;} else {pt->p[0]=x;pt->p[1]=y;pt->p[2]=z;} pt->r2p=dr->r2p; dr->col[n]=col; dr->line[n]=line; return; } void PlotDraw3D(Draw3Dptr dr) { int i; for(i=0;in;i++) { SetColor(dr->col[i]); if(dr->line[i]) PlotLine3D(dr->pt[i]); else PlotPt3D(dr->pt[i]); } return; } void UpdateDraw3D(Draw3Dptr dr,int internal) { int i; for(i=0;in;i++) UpdatePt3D(dr->pt[i],internal); return; } float *Draw3DOut(Draw3Dptr dr,char c) { int i,j; float *a; a=allocM(dr->n,3); if(!a) return NULL; for(i=0;in;i++) for(j=0;j<3;j++) if(c=='r') a[3*i+j]=dr->pt[i]->r[j]; else if(c=='p') a[3*i+j]=dr->pt[i]->p[j]; else if(c=='s') a[3*i+j]=dr->pt[i]->s[j]; else a[3*i+j]=dr->pt[i]->o[j]; return a; } int Draw3D2ps(Draw3Dptr dr,int zdiv,char *name,int append) { FILE *fptr; char str[256]; Pt3Dptr *pt; int nmfre,er,i,div,divcur; float zmin,zmax; er=GetName(&name,&nmfre); if(er) return er; if(!strcmp(name,"stdout")) fptr=stdout; else if(append==1) fptr=fopen(name,"a"); else if(append==2) fptr=fopen(name,"w"); else { fptr=fopen(name,"r"); if(fptr) { fclose(fptr); fprintf(stderr,"File exists. Do you want to overwrite it? "); scanf("%s",str); if(str[0]!='y'&&str[0]!='Y') { if(nmfre) free(name); return 2;}} fptr=fopen(name,"w");} if(nmfre) free(name); if(!fptr) return 3; pt=dr->pt; /* zmin=zmax=pt[0]->o[2]; for(i=0;in;i++) { if(pt[i]->o[2]o[2]; else if(pt[i]->o[2]>zmax) zmax=pt[i]->o[2]; }*/ zmin=-1; zmax=1; fprintf(fptr,"%!\n"); fprintf(fptr,"%%%% Postscript file produced by Plot3D.c\n"); fprintf(fptr,"/unit {250 mul} def\n"); div=divcur=floor((pt[0]->o[2]-zmin)/(zmax-zmin)*zdiv); if(div<0) div=0; else if(div>=zdiv) div=zdiv-1; fprintf(fptr,"newpath\n"); fprintf(fptr,"%f setlinewidth\n",0.5*(1.0-1.0*div/zdiv)-0.3); fprintf(fptr,"%f unit %f unit moveto\n",3+pt[0]->o[0],6+pt[0]->o[1]); for(i=1;in;i++) { div=floor((zmax-pt[i]->o[2])/(zmax-zmin)*zdiv); if(div<0) div=0; else if(div>=zdiv) div=zdiv-1; if(div==divcur&&dr->line[i]) fprintf(fptr,"%f unit %f unit lineto\n",3+pt[i]->o[0],6+pt[i]->o[1]); else { if(dr->line[i]) fprintf(fptr,"%f unit %f unit lineto\n",3+pt[i]->o[0],6+pt[i]->o[1]); fprintf(fptr,"stroke\n"); fprintf(fptr,"newpath\n"); fprintf(fptr,"%f setlinewidth\n",(1.0-1.0*div/zdiv)-0.3); divcur=div; fprintf(fptr,"%f unit %f unit moveto\n",3+pt[i]->o[0],6+pt[i]->o[1]); }} fprintf(fptr,"stroke\n"); fprintf(fptr,"showpage\n"); if(fptr!=stdout) fclose(fptr); return er; }