/* project.c 2-20-90 This is a last (I hope) attempt at standardizing the lat/lon to x/y and back again functions for generic map use. pj1.bat = cl /AL project.c vimage dispio */ #include #include #include "font.h" #define R 6367.65 #define PI 3.1415927 #define PI2 1.5707963 #define PI4 0.7853981 #define DEG_RAD 0.01745329251 /* converts degrees to radians */ #define NUM_PROJ 16 float MaxLat=90.0,MinLat=-90.0,MaxLon=180.0,MinLon=-180.0; unsigned char Inbuff[BUFSIZ],Inbuff2[BUFSIZ],Outbuff[BUFSIZ]; int Grey=0; unsigned char P_Buff[12][640]; struct Color { unsigned char r, g, b; }lut[256],lutm[256],lutc[256],luts[256]; struct control { char proj; int pnum; double lon_0,lon_1,lon_2,lon_p; double lat_0,lat_1,lat_2,lat_p; double pixsize,scale; double x0,y0; double c,C,F,H,k,k0,k1,k2,n,P,rho_0; double omega; /* elevation (tilt of surface plane) */ double gamma; /* azimuth (east of north) */ double horiz; /* radius of horizon arc */ }; double S[2][4]= { {1.0,-1.0,1.0,-1.0}, {1.0,1.0,-1.0,-1.0} }; struct projection { char name[80]; char id; }Proj[NUM_PROJ]= { { "Mercator",'m'}, { "Transverse Mercator",'u'}, { "Oblique Mercator",'o'}, { "Modified Plate Carree",'p'}, { "Albers Equal-Area Conic",'a'}, { "Lambert Conformal Conic",'l'}, { "Bonne",'b'}, { "Orthographic",'t'}, { "Stereographic",'s'}, { "Gnomonic",'g'}, { "Vertical Perspective",'V'}, { "Tilted Perspective",'P'}, {"Lambert Azimuthal Equal-Area",'L'}, { "Azimuthal Equidistant",'z'}, { "Sinusoidal",'S'}, { "Polyconic",'y'} }; void set_lut(); int choose_projection(); int get_constants(); int ll2xy(); int xy2ll(); int graticule(); int coast_lines(); int horizon(); void compress(); int expand(); /******************************************************************** ** ** ** ********************************************************************* */ int auto_set_constants(cc) struct control *cc; { int i,j,k; char mode='p'; char ans; char where[100]; double scale,sign=1.0,tval; cc->scale=R/cc->scale; if(cc->scale<=0.0) return(-1); cc->horiz=-1.0; if(cc->proj=='m') { return(0); } if(cc->proj=='u') { cc->lat_0*=DEG_RAD; cc->lon_0*=DEG_RAD; cc->k0=0.9996; return(1); } if(cc->proj=='o') { cc->lon_p=atan2( (cos(cc->lat_1*DEG_RAD)*sin(cc->lat_2*DEG_RAD)*cos(cc->lon_1*DEG_RAD)- sin(cc->lat_1*DEG_RAD)*cos(cc->lat_2*DEG_RAD)*cos(cc->lon_2*DEG_RAD)), (sin(cc->lat_1*DEG_RAD)*cos(cc->lat_2*DEG_RAD)*sin(cc->lon_2*DEG_RAD)- cos(cc->lat_1*DEG_RAD)*sin(cc->lat_2*DEG_RAD)*sin(cc->lon_1*DEG_RAD))); cc->lat_p=atan(-cos(cc->lon_p-cc->lon_1*DEG_RAD)/tan(cc->lat_1)); cc->lon_0=cc->lon_p+PI/2.0; cc->k0=0.9996; return(2); } if(cc->proj=='p') { if(cc->lat_0==90.0||cc->lat_0==-90.0) return(-1); cc->k1=cc->scale*PI/180.0; /* km/deg lat */ cc->k2=cc->scale*PI/180.0*cos(cc->lat_0*DEG_RAD); /* km/deg lon */ } if(cc->proj=='a') { if(cc->lat_0<0.0)sign=-1.0; cc->lat_1=cc->lat_1*sign; cc->lat_2=cc->lat_2*sign; cc->n=(sin(cc->lat_1*DEG_RAD)+sin(cc->lat_2*DEG_RAD))/2.0; cc->C=cos(cc->lat_1*DEG_RAD)*cos(cc->lat_1*DEG_RAD)+ 2.0*cc->n*sin(cc->lat_1*DEG_RAD); cc->rho_0=cc->scale*sqrt(cc->C-2.0*cc->n*sin(cc->lat_0*DEG_RAD))/cc->n; } if(cc->proj=='l') { if(cc->lat_0==0.0)return(-1); cc->lat_0*=DEG_RAD; cc->lon_0*=DEG_RAD; if(cc->lat_0<0.0)sign=-1.0; cc->lat_1=cc->lat_1*sign*DEG_RAD; cc->lat_2=cc->lat_2*sign*DEG_RAD; if(cc->lat_0==cc->lat_1&&cc->lat_0==cc->lat_2) cc->n=sin(cc->lat_1); else cc->n=log(cos(cc->lat_1)/cos(cc->lat_2))/ log(tan(PI4+cc->lat_2/2.0)/tan(PI4+cc->lat_1/2.0)); cc->F=cos(cc->lat_1)*pow(tan(PI4+cc->lat_1/2.0),cc->n)/cc->n; cc->rho_0=R*cc->F/pow(tan(PI4+cc->lat_0/2.0),cc->n); } if(cc->proj=='b') { cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='t') { cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='s') { cc->scale*=cc->k0; cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='g') { cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='V') { cc->P=cc->H/cc->scale+1.0; cc->horiz=cc->scale*sqrt((cc->P-1.0)/(cc->P+1.0)); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='P') { cc->P=cc->H/cc->scale+1.0; cc->horiz=cc->scale*sqrt((cc->P-1.0)/(cc->P+1.0)); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; cc->gamma*=DEG_RAD; cc->omega*=DEG_RAD; cc->H=cc->scale/(cc->P-1.0); } if(cc->proj=='L') { cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='z') { cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='S') { cc->lon_0*=DEG_RAD; } if(cc->proj=='y') { cc->lon_0*=DEG_RAD; cc->lat_0*=DEG_RAD; } } /******************************************************************** ** ** ** ********************************************************************* */ int expand(filename,buffer) char *filename; unsigned char buffer[640]; { int i,j,k,x,y; FILE *fpin; int xyn[3]; fpin=fopen(filename,"rb"); if(!fpin)return(-1); paint_box(3,0,P_Buff,0,0,640,480); while( fread((char *)xyn,sizeof(int),3,fpin)==3) { fread((char *)buffer,sizeof(char),xyn[2],fpin); plotrow(3,xyn[0],xyn[0]+xyn[2]-1,xyn[1],buffer); } fclose(fpin); } /******************************************************************** ** ** compresses an image (takes out missing data ** ********************************************************************* */ void compress(filename,buffer) char *filename; unsigned char buffer[640]; { int i,j,k,x,y; int *npt,xyn[3]; int numplanes=0; unsigned int numpts; FILE *fpout; int x1,npr; long total=0; float perc; fpout = fopen(filename,"w+b"); setbuf(fpout,Outbuff); if(!fpout) { printf("\n\nFailure in opening %s!!!!\n\n\n",filename); return; } /* find first point */ x=640; y=0; while(y<480&&x==640) { getrow(3,0,639,y,buffer); x=0; while(x<640&&buffer[x]==0)x+=1; y+=1; } y-=1; if(x>639&&y>439) { fclose(fpout); return; } /* process the image */ while(y<480) { getrow(3,0,639,y,buffer); x=0; while(x<640) { x1=-1; while(x<640&&buffer[x]==0)x+=1; if(x<640) { x1=x; numpts=0; while(x<640&&buffer[x]!=0) { numpts+=1; x+=1; } } if(x1>=0) { total+=numpts; xyn[0]=x1;xyn[1]=y;xyn[2]=numpts; if((npr=fwrite((char *)xyn,sizeof(int),3,fpout))<3) { printf("\n\nOutput Disk full!!!\n\n\n"); printf("Wrote only %d of '3'\n",npr); printf("HIT ANY KEY TO EXIT PROGRAM\n\n"); getch(); return; } if((npr=fwrite((char *)buffer+x1,sizeof(char),numpts,fpout)) MaxLon||mnlt>MaxLat||mxln=0) { ix=x-cx; iy=cy-y; if(ix>=xc&&ixyc&&iy=xc&&ixoyc&&iyo0&&ret>0&&reto>0) { plotln(3,ix,iy,ixo,iyo,val); } reto=ret; ixo=ix;iyo=iy; } } } } fclose(fp); fclose(fphdr); return(1); } /******************************************************************** ** ** ** ********************************************************************* */ int horizon(xc,yc,xs,ys,clat,clon,cc,line,debug) int xc,yc,xs,ys,line; double clat,clon; struct control cc; int debug; { int i,j,k,rs; double lat,lon,x,y,xo,yo,H,A; double cx,cy,xt,yt; int ret,ix,iy,px,py,pxo,pyo; double latmax=90.0,latmin=-90.0,lonmax=180.0,lonmin=-180.0; double nx,ny; if(cc.horiz<=1.0)return(-1); ret=ll2xy(clat,clon,&cx,&cy,cc); cx-=xs/2; cy+=ys/2; if(ret<0) return(ret); lat=cc.lat_1/DEG_RAD;lon=cc.lon_0/DEG_RAD; ll2xy(lat,lon,&nx,&ny,cc); rs=cc.horiz; H=cc.horiz*cc.horiz; if(debug==1) printf("cc.proj = %c H=%lf rs=%d\n",cc.proj,H,rs); if(cc.proj=='P') { for(k=0;k<2;k++) { for(i=0;i<=rs;i++) { xt=i; yt=sqrt(H-xt*xt); A=(yt*cos(cc.gamma)+xt*sin(cc.gamma))* sin(cc.omega)/cc.H+cos(cc.omega); x=(xt*cos(cc.gamma)-yt*sin(cc.gamma))/A; y=(yt*cos(cc.gamma)+xt*sin(cc.gamma))*cos(cc.omega)/A; if(i>0) { plotln(3,(int)((nx+xo*S[0][k])-cx),(int)(cy-(ny+yo*S[1][k])), (int)((nx+x*S[0][k])-cx),(int)(cy-(ny+y*S[1][k])),line); } xo=x;yo=y; } xt=cc.horiz; yt=0.0; A=(yt*cos(cc.gamma)+xt*sin(cc.gamma))* sin(cc.omega)/cc.H+cos(cc.omega); x=(xt*cos(cc.gamma)-yt*sin(cc.gamma))/A; y=(yt*cos(cc.gamma)+xt*sin(cc.gamma))*cos(cc.omega)/A; plotln(3,(int)((nx+xo*S[0][k])-cx),(int)(cy-(ny+yo*S[1][k])), (int)((nx+x*S[0][k])-cx),(int)(cy-(ny+y*S[1][k])),line); } return(1); } if(cc.proj=='V') { for(k=0;k<4;k++) { for(i=0;i<=rs;i++) { x=i; y=sqrt(H-x*x); px=i; py=y; if(i>0) { plotln(3,(int)((nx+pxo*S[0][k])-cx),(int)(cy-(ny+pyo*S[1][k])), (int)((nx+px*S[0][k])-cx),(int)(cy*S[1][k]-(ny+py)),line); } pxo=px;pyo=py; } px=rs;py=0; plotln(3,(int)((nx+pxo*S[0][k])-cx),(int)(cy-(ny+pyo*S[1][k])), (int)((nx+px*S[0][k])-cx),(int)(cy-(ny+py*S[1][k])),line); } return(1); } } /******************************************************************** ** ** ** ********************************************************************* */ int graticule(xc,yc,xs,ys,clat,clon,cc,line,num,spacing,debug,steps, constant) int xc,yc,xs,ys,line,num; double clat,clon; struct control cc; float spacing,steps; int debug; struct control constant; { int i,j,k,rs; double lat,lon,x,y,H; double del=spacing,latp=-90.0,lonp=-90.0; double cx,cy; int ret,ix,iy,px,py,pxo,pyo; double latmax=90.0,latmin=-90.0,lonmax=180.0,lonmin=-180.0; double nx,ny; ret=ll2xy(clat,clon,&cx,&cy,cc); cx-=xs/2; cy+=ys/2; if(ret<0) return(ret); MaxLat=-100; MinLat= 100; MaxLon=-190; MinLon= 190; latp=-90.0; do { px=py=pxo=pyo=-999; lonp=lonmin;j=0; do { if(debug==1) printf("1--latp = %lf lonp = %lf\n",latp,lonp); if(kbhit()!=0) if(getch()=='\033') return(-1); ret=ll2xy(latp,lonp,&x,&y,cc); if(ret<0) { px=py=-999; } else { px=x-cx; py=cy-y; if(latp>MaxLat)MaxLat=latp; if(latpMaxLon)MaxLon=lonp; if(lonp=xc&&pxyc&&py=xc&&pxoyc&&pyo=xc&&pxyc&&py=xc&&pxoyc&&pyo=latmin); lonp=0.0; do { px=py=pxo=pyo=-999; latp=latmin;i=0; do { if(debug==1) printf("3--latp = %lf lonp = %lf\n",latp,lonp); if(kbhit()!=0) if(getch()=='\033') return(-1); ret=ll2xy(latp,lonp,&x,&y,cc); if(ret<0) { px=py=-999; } else { px=x-cx; py=cy-y; } if(debug==1) printf("3--ret=%d cx=%lf cy=%lf x=%lf y=%lf px=%d py=%d\n", ret,cx,cy,x,y,px,py); if(px!=-999&&pxo!=-999&&(px>=xc&&pxyc&&py=xc&&pxoyc&&pyo=xc&&pxyc&&py=xc&&pxoyc&&pyo=lonmin); MaxLat+=spacing; MinLat-=spacing; MaxLon+=spacing; MinLon-=spacing; return(1); } /******************************************************************** ** ** converts x and y in kilometers to lat and lon in degrees ** ** returns: ** ** 0 - 13 = number of successfully processed projection ** -1 = no such projection ** -99 = scale is zero ** ********************************************************************* */ int xy2ll(x,y,lat,lon,cc) double x,y,*lat,*lon; struct control cc; { double A,B,c,D,H,M,Q; double sign=1.0,rho,theta,latn,latn1,diff; if(cc.scale==0.0)return(-99); if(cc.proj=='m') { *lat=90.0-2.0*atan(exp(-y/cc.scale))/DEG_RAD; *lon=x/cc.scale/DEG_RAD+cc.lon_0; return(0); } if(cc.proj=='u') { D=y/(cc.scale*cc.k0)+cc.lat_0; *lat=asin(sin(D)/cosh(x/(cc.scale*cc.k0)))/DEG_RAD; *lon=cc.lon_0+atan(sinh(x/(cc.scale*cc.k0))/cos(D))/DEG_RAD; return(1); } if(cc.proj=='o') { *lat=asin(sin(cc.lat_p)*tanh(y/(cc.scale*cc.k0))+ cos(cc.lat_p)*sin(x/(cc.scale*cc.k0))/ cosh(y/(cc.scale*cc.k0))); *lat/=DEG_RAD; *lon=cc.lon_0+atan((sin(cc.lat_p)*sin(x/(cc.scale*cc.k0))- cos(cc.lat_p)*sinh(y/(cc.scale*cc.k0)))/cos(x/(cc.scale*cc.k0))); *lon/=DEG_RAD; return(2); } if(cc.proj=='p') { *lat=y/cc.k1+cc.lat_0; *lon=x/cc.k2+cc.lon_0; return(3); } if(cc.proj=='a') { if(cc.lat_0<0.0)sign=-1.0; y*=sign; rho=sqrt(x*x+(cc.rho_0-y)*(cc.rho_0-y)); theta=atan2(x,cc.rho_0-y); *lat=asin((cc.C-(rho*cc.n/cc.scale)*(rho*cc.n/cc.scale))/(2.0*cc.n)); *lat/=DEG_RAD*sign; *lon=theta/cc.n/DEG_RAD+cc.lon_0; return(4); } if(cc.proj=='l') { if(cc.lat_0<0.0)sign=-1.0; y*=sign; rho=sqrt(x*x+(cc.rho_0-y)*(cc.rho_0-y)); theta=atan2(x,cc.rho_0-y); *lat=2.0*atan(pow(cc.scale*cc.F/rho,1.0/cc.n))-PI4*2.0; *lat/=DEG_RAD*sign; *lon=theta/cc.n+cc.lon_0; *lon/=DEG_RAD; return(5); } if(cc.proj=='b') { if(cc.lat_0<0.0)sign=-1.0; rho=sqrt(x*x+ (cc.scale*tan(1.0/cc.lat_1)-y)* (cc.scale*tan(1.0/cc.lat_1)-y))*sign; *lat=tan(1.0/cc.lat_1)+cc.lat_1-rho/cc.scale; *lon=cc.lon_0+ rho*atan2(x,cc.scale*tan(1.0/cc.lat_1)-y)/ (cc.scale*cos(*lat)); *lat/=DEG_RAD; *lon/=DEG_RAD; return(6); } if(cc.proj=='t') { rho=x*x+y*y; if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { rho=sqrt(rho); c=asin(rho/cc.scale); *lat=asin(cos(c)*sin(cc.lat_1)+y*sin(c)*cos(cc.lat_1)/rho); if(cc.lat_1==90.0) *lon=cc.lon_0+atan2(x,-y); else if(cc.lat_1==-90.0) *lon=cc.lon_0+atan2(x,y); else *lon=cc.lon_0+atan2(x*sin(c), rho*cos(cc.lat_1)*cos(c)-y*sin(c)*sin(cc.lat_1)/rho); } *lat/=DEG_RAD; *lon/=DEG_RAD; return(7); } if(cc.proj=='s') { rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=2.0*atan(rho/(2.0*cc.scale)); *lat=asin(cos(c)*sin(cc.lat_1)+y*sin(c)*cos(cc.lat_1)/rho); *lon=cc.lon_0+ atan2(x*sin(c),rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); *lat/=DEG_RAD; *lon/=DEG_RAD; } return(8); } if(cc.proj=='g') { rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=atan(rho/cc.scale); *lat=asin(cos(c)*sin(cc.lat_1)+y*sin(c)*cos(cc.lat_1)/rho); if(cc.lat_1==90.0) *lon=cc.lon_0+atan2(x,-y); else if(cc.lat_1==-90.0) *lon=cc.lon_0+atan2(x,y); else *lon=cc.lon_0+ atan2(x*sin(c),rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); *lat/=DEG_RAD; *lon/=DEG_RAD; } return(9); } if(cc.proj=='V') { rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=asin((cc.P- sqrt(1.0-rho*rho*(cc.P+1.0)/(cc.scale*cc.scale*(cc.P-1.0))) )/(cc.scale*(cc.P-1.0)/rho+rho/(cc.scale*(cc.P-1.0)))); *lat=asin(cos(c)*sin(cc.lat_1)+y*sin(c)*cos(cc.lat_1)/rho); *lon=cc.lon_0+ atan2(x*sin(c), rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); *lat/=DEG_RAD; *lon/=DEG_RAD; } return(10); } if(cc.proj=='P') { M=cc.H*x*cos(cc.omega)/(cc.H-y*sin(cc.omega)); Q=cc.H*y/(cc.H-y*sin(cc.omega)); x=M*cos(cc.gamma)+Q*sin(cc.gamma); y=Q*cos(cc.gamma)-M*sin(cc.gamma); rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=asin((cc.P- sqrt(1.0-rho*rho*(cc.P+1.0)/(cc.scale*cc.scale*(cc.P-1.0))) )/(cc.scale*(cc.P-1.0)/rho+rho/(cc.scale*(cc.P-1.0)))); *lat=asin(cos(c)*sin(cc.lat_1)+y*sin(c)*cos(cc.lat_1)/rho); *lon=cc.lon_0+ atan2(x*sin(c), rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); *lat/=DEG_RAD; *lon/=DEG_RAD; } return(11); } if(cc.proj=='L') { rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=2.0*asin(rho/(2.0*cc.scale)); *lat=asin(cos(c)*sin(cc.lat_1)+(y*sin(c)*cos(cc.lat_1)/rho)); *lon=cc.lon_0+ atan2(x*sin(c),rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); } *lat/=DEG_RAD; *lon/=DEG_RAD; return(12); } if(cc.proj=='z') { rho=sqrt(x*x+y*y); if(rho==0.0) { *lat=cc.lat_1; *lon=cc.lon_0; } else { c=rho/cc.scale; *lat=asin(cos(c)*sin(cc.lat_1)+(y*sin(c)*cos(cc.lat_1)/rho)); *lon=cc.lon_0+atan2(x*sin(c), rho*cos(cc.lat_1)*cos(c)-y*sin(cc.lat_1)*sin(c)); } *lat/=DEG_RAD; *lon/=DEG_RAD; return(13); } if(cc.proj=='S') { *lat=y/cc.scale; if(*lat==90.0||*lat==-90.0) *lon=0.0; else *lon=cc.lon_0+x/(cc.scale*cos(*lat)); *lat/=DEG_RAD; *lon/=DEG_RAD; return(14); } if(cc.proj=='y') { if(y==(-cc.scale*cc.lat_0)) { *lat=0.0; *lon=x/cc.scale+cc.lon_0; } else { A=cc.lat_0+y/cc.scale; B=x*x/(cc.scale*cc.scale)+A*A; latn=A; do { latn1=latn-(A*(latn*tan(latn)+1.0)-latn- 0.5*(latn*latn+B)*tan(latn))/ ((latn-A)/tan(latn)-1.0); diff=(latn-latn1)*(latn-latn1); latn=latn1; }while(diff>3.046E-18); *lat=latn; *lon=asin(x*tan(latn)/cc.scale)/sin(latn)+cc.lon_0; } *lat/=DEG_RAD; *lon/=DEG_RAD; return(15); } return(-1); } /******************************************************************** ** ** converts lat and lon in degrees into x and y in kilometers ** ** returns number of projection used. If < 0 error or back side of earth ** ** returns: ** ** 0 - 13 = number of successfully processed projection ** -7 = back side of earth ** -99 = scale is zero ** ** ********************************************************************* */ int ll2xy(lat,lon,x,y,cc) double lat,lon,*x,*y; struct control cc; { double A,B,c,E,k,xt,yt; double sign=1.0,rho,theta,tval,dlon,cosc; if(cc.scale==0.0)return(-99); if(lat>90.0||lat<-90.0) return(-1); if(cc.proj=='m') { if(lat==90.0||lat==-90.0)return(-100); *x=cc.scale*(lon-cc.lon_0)*DEG_RAD; *y=cc.scale*(log(tan((45.0+lat/2)*DEG_RAD))); return(0); } if(cc.proj=='u') { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; if(dlon<=-PI2||dlon>=PI2)return(-101); B=cos(lat)*sin((dlon)); if(B>=1.0||B<=-1.0)return(-101); *x=0.5*cc.scale*cc.k0*log((1.0+B)/(1.0-B)); *y=cc.scale*cc.k0*(atan2(tan(lat),cos(dlon))-cc.lat_0); return(1); } if(cc.proj=='o') { A=sin(cc.lat_p)*sin(lat*DEG_RAD)-cos(cc.lat_p)*cos(lat*DEG_RAD)* sin(lon*DEG_RAD-cc.lon_0); if(A==1.0)return(-102); *x=cc.scale*cc.k0*atan((tan(lat*DEG_RAD)*cos(cc.lat_p)+ sin(cc.lat_p)*sin(lon*DEG_RAD-cc.lon_0))/cos(lon*DEG_RAD-cc.lon_0)); *y=cc.scale/2.0*cc.k0*log((1.0+A)/(1.0-A)); return(2); } if(cc.proj=='p') { *x=(lon-cc.lon_0)*cc.k2; *y=(lat-cc.lat_0)*cc.k1; return(3); } if(cc.proj=='a') { if(cc.n==0.0)return(-104); if(cc.lat_0<0.0)sign=-1.0; lat*=sign; rho=cc.scale*sqrt(cc.C-2.0*cc.n*sin(lat*DEG_RAD))/cc.n; theta=cc.n*(lon-cc.lon_0)*DEG_RAD; *x=rho*sin(theta); *y=(cc.rho_0-rho*cos(theta))*sign; return(4); } if(cc.proj=='l') { lat*=DEG_RAD;lon*=DEG_RAD; if(cc.lat_0<0.0)sign=-1.0; lat*=sign; if((PI4+lat/2.0)<=0.0)return(-105); tval=pow(tan(PI4+lat/2.0),cc.n); rho=cc.scale*cc.F/tval; theta=cc.n*(lon-cc.lon_0); *x=rho*sin(theta); *y=(cc.rho_0-rho*cos(theta))*sign; return(5); } if(cc.proj=='b') { lat*=DEG_RAD;lon*=DEG_RAD; if(cc.lat_1==0.0)return(-106); rho=cc.scale*(tan(1.0/cc.lat_1)+cc.lat_1-lat); if(rho==0.0)return(-106); E=cc.scale*(lon-cc.lon_0)*cos(lat)/rho; *x=rho*sin(E); *y=cc.scale*tan(1.0/cc.lat_1)-rho*cos(E); return(6); } if(cc.proj=='t') { lat*=DEG_RAD;lon*=DEG_RAD; *x=cc.scale*cos(lat)*sin(lon-cc.lon_0); *y=cc.scale*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(lon-cc.lon_0)); if( sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(lon-cc.lon_0) <=0.0)return(-7); /* point on back side of earth */ return(7); } if(cc.proj=='s') { lat*=DEG_RAD;lon*=DEG_RAD; tval=1.0+sin(cc.lat_1)*sin(lat)+ cos(cc.lat_1)*cos(lat)*cos(lon-cc.lon_0); if(tval==0.0)return(-108); k=2.0/tval; *x=cc.scale*k*cos(lat)*sin(lon-cc.lon_0); *y=cc.scale*k*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(lon-cc.lon_0)); return(8); } if(cc.proj=='g') { if(cc.lat_1==PI2) { if(lat<=0.0)return(-109); if(lat=90.0) *x=*y=0.0; else { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; *x=cc.scale*1.0/tan(lat)*sin(dlon); *y=-cc.scale*1.0/tan(lat)*cos(dlon); } } else if(cc.lat_1==-PI2) { if(lat>=0.0)return(-109); if(lat=-90.0) *x=*y=0.0; else { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; *x=-cc.scale*1.0/tan(lat)*sin(dlon); *y=cc.scale*1.0/tan(lat)*cos(dlon); } } else { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; cosc=sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(dlon); if(cosc<=0.00001)return(-109); k=1/cosc; *x=cc.scale*k*cos(lat)*sin(dlon); *y=cc.scale*k*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(dlon)); } return(9); } if(cc.proj=='V') { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; cosc=sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(dlon); if(cosc<1.0/cc.P)return(-110); k=(cc.P-1.0)/(cc.P-cosc); *x=cc.scale*k*cos(lat)*sin(dlon); *y=cc.scale*k*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(dlon)); return(10); } if(cc.proj=='P') { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; cosc=sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(dlon); if(cosc<1.0/cc.P)return(-110); k=(cc.P-1.0)/(cc.P-cosc); xt=cc.scale*k*cos(lat)*sin(dlon); yt=cc.scale*k*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(dlon)); A=(yt*cos(cc.gamma)+xt*sin(cc.gamma))*sin(cc.omega)/cc.H+cos(cc.omega); *x=(xt*cos(cc.gamma)-yt*sin(cc.gamma))/A; *y=(yt*cos(cc.gamma)+xt*sin(cc.gamma))*cos(cc.omega)/A; return(11); } if(cc.proj=='L') { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; k=1.0+sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(dlon); if(k<=0.0)return(-12); k=sqrt(2.0/k); *x=cc.scale*k*cos(lat)*sin(dlon); *y=cc.scale*k*(cos(cc.lat_1)*sin(lat)-sin(cc.lat_1)*cos(lat)*cos(dlon)); return(12); } if(cc.proj=='z') { lat*=DEG_RAD;lon*=DEG_RAD; dlon=lon-cc.lon_0; cosc=sin(cc.lat_1)*sin(lat)+cos(cc.lat_1)*cos(lat)*cos(dlon); if(cosc==-1.0)return(-113); if(cosc==1.0) *x=*y=0.0; else { c=acos(cosc); k=c/sin(c); *x=cc.scale*k*cos(lat)*sin(dlon); *y=cc.scale*k*(cos(cc.lat_1)*sin(lat)- sin(cc.lat_1)*cos(lat)*cos(dlon)); } return(13); } if(cc.proj=='S') { lat*=DEG_RAD;lon*=DEG_RAD; *x=cc.scale*(lon-cc.lon_0)*cos(lat); *y=cc.scale*lat; return(14); } if(cc.proj=='y') { lat*=DEG_RAD;lon*=DEG_RAD; if(lat==0.0) { *x=cc.scale*(lon-cc.lon_0); *y=-cc.scale*cc.lat_0; } else { E=(lon-cc.lon_0)*sin(lat); *x=cc.scale*sin(E)/tan(lat); *y=cc.scale*(lat-cc.lat_0+(1.0-cos(E))/tan(lat)); } return(15); } return(-1); } /******************************************************************** ** ** ** ********************************************************************* */ int get_constants(cc) struct control *cc; { int i,j,k; char mode='p'; char ans; char where[100]; double scale,sign=1.0,tval; if(cc->proj=='m')strcpy(where,"at the equator"); if(cc->proj=='u')strcpy(where,"along the central meridian"); if(cc->proj=='o')strcpy(where,"along the great circle arc"); if(cc->proj=='p')strcpy(where,"at the map or image center"); if(cc->proj=='a')strcpy(where,"at the map or image center"); if(cc->proj=='l')strcpy(where,"at the map or image center"); if(cc->proj=='b')strcpy(where,"at the map or image center"); if(cc->proj=='t')strcpy(where,"at the map or image center"); if(cc->proj=='s')strcpy(where,"at the pole"); if(cc->proj=='g')strcpy(where,"at the map or image center"); if(cc->proj=='V')strcpy(where,"at the map or image center"); if(cc->proj=='P')strcpy(where,"at the map or image center"); if(cc->proj=='L')strcpy(where,"at the map or image center"); if(cc->proj=='z')strcpy(where,"at the map or image center"); if(cc->proj=='S')strcpy(where,"at the map or image center"); if(cc->proj=='y')strcpy(where,"at the map or image origin"); printf("Enter scale of map ( 1:______) or pixel size %s.\n",where); scanf("%lf",&scale); cc->scale=R/scale; if(cc->scale<=0.0) return(-1); cc->horiz=-1.0; if(cc->proj=='m') { printf("Give longitude (degrees) of central meridian of map\n"); scanf("%lf",&cc->lon_0); return(0); } if(cc->proj=='u') { printf("Give central latitude (degrees) of map\n"); scanf("%lf",&cc->lat_0); cc->lat_0*=DEG_RAD; printf("Give longitude (degrees) of central meridian of map\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->k0=0.9996; return(1); } if(cc->proj=='o') { printf("Give latitude and longitude (degrees) of first point.\n"); scanf("%lf%lf",&cc->lat_1,&cc->lon_1); printf("Give latitude and longitude (degrees) of second point.\n"); scanf("%lf%lf",&cc->lat_2,&cc->lon_2); cc->lon_p=atan2( (cos(cc->lat_1*DEG_RAD)*sin(cc->lat_2*DEG_RAD)*cos(cc->lon_1*DEG_RAD)- sin(cc->lat_1*DEG_RAD)*cos(cc->lat_2*DEG_RAD)*cos(cc->lon_2*DEG_RAD)), (sin(cc->lat_1*DEG_RAD)*cos(cc->lat_2*DEG_RAD)*sin(cc->lon_2*DEG_RAD)- cos(cc->lat_1*DEG_RAD)*sin(cc->lat_2*DEG_RAD)*sin(cc->lon_1*DEG_RAD))); cc->lat_p=atan(-cos(cc->lon_p-cc->lon_1*DEG_RAD)/tan(cc->lat_1)); cc->lon_0=cc->lon_p+PI/2.0; cc->k0=0.9996; return(2); } if(cc->proj=='p') { printf("Give latitude and longitude (degrees) of origin.\n"); scanf("%lf%lf",&cc->lat_0,&cc->lon_0); if(cc->lat_0==90.0||cc->lat_0==-90.0) return(-1); cc->k1=cc->scale*PI/180.0; /* km/deg lat */ cc->k2=cc->scale*PI/180.0*cos(cc->lat_0*DEG_RAD); /* km/deg lon */ } if(cc->proj=='a') { printf("Give latitude and longitude (degrees) of origin.\n"); scanf("%lf%lf",&cc->lat_0,&cc->lon_0); printf("Give latitude of 2 standard parallels.\n"); scanf("%lf%lf",&cc->lat_1,&cc->lat_2); if(cc->lat_0<0.0)sign=-1.0; cc->lat_1=cc->lat_1*sign; cc->lat_2=cc->lat_2*sign; cc->n=(sin(cc->lat_1*DEG_RAD)+sin(cc->lat_2*DEG_RAD))/2.0; cc->C=cos(cc->lat_1*DEG_RAD)*cos(cc->lat_1*DEG_RAD)+ 2.0*cc->n*sin(cc->lat_1*DEG_RAD); cc->rho_0=cc->scale*sqrt(cc->C-2.0*cc->n*sin(cc->lat_0*DEG_RAD))/cc->n; } if(cc->proj=='l') { printf("Give latitude and longitude (degrees) of origin.\n"); scanf("%lf%lf",&cc->lat_0,&cc->lon_0); if(cc->lat_0==0.0)return(-1); cc->lat_0*=DEG_RAD; cc->lon_0*=DEG_RAD; printf("Give latitude of 2 standard parallels.\n"); scanf("%lf%lf",&cc->lat_1,&cc->lat_2); if(cc->lat_0<0.0)sign=-1.0; cc->lat_1=cc->lat_1*sign*DEG_RAD; cc->lat_2=cc->lat_2*sign*DEG_RAD; if(cc->lat_0==cc->lat_1&&cc->lat_0==cc->lat_2) cc->n=sin(cc->lat_1); else cc->n=log(cos(cc->lat_1)/cos(cc->lat_2))/ log(tan(PI4+cc->lat_2/2.0)/tan(PI4+cc->lat_1/2.0)); cc->F=cos(cc->lat_1)*pow(tan(PI4+cc->lat_1/2.0),cc->n)/cc->n; cc->rho_0=R*cc->F/pow(tan(PI4+cc->lat_0/2.0),cc->n); } if(cc->proj=='b') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='t') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='s') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); printf("GIve scale factor (usually 1).\n"); scanf("%lf",&cc->k0); cc->scale*=cc->k0; cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='g') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='V') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); printf("GIve altitude of view in kilometers.\n"); scanf("%lf",&cc->H); cc->P=cc->H/cc->scale+1.0; cc->horiz=cc->scale*sqrt((cc->P-1.0)/(cc->P+1.0)); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='P') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); printf("GIve altitude of view in kilometers.\n"); scanf("%lf",&cc->H); cc->P=cc->H/cc->scale+1.0; cc->horiz=cc->scale*sqrt((cc->P-1.0)/(cc->P+1.0)); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; printf("Give viewing azimuth (N=0,E=90,S=180,W=270).\n"); scanf("%lf",&cc->gamma); printf("Give viewing angle up from straight down.\n"); scanf("%lf",&cc->omega); cc->gamma*=DEG_RAD; cc->omega*=DEG_RAD; cc->H=cc->scale/(cc->P-1.0); } if(cc->proj=='L') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='z') { printf("Give latitude of standard parallel.\n"); scanf("%lf",&cc->lat_1); printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; cc->lat_1*=DEG_RAD; } if(cc->proj=='S') { printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); cc->lon_0*=DEG_RAD; } if(cc->proj=='y') { printf("Give longitude (degrees) of central meridian.\n"); scanf("%lf",&cc->lon_0); printf("Give latitude of origin ( usually = 0.0).\n"); scanf("%lf",&cc->lat_0); cc->lon_0*=DEG_RAD; cc->lat_0*=DEG_RAD; } } /******************************************************************** ** ** ** ********************************************************************* */ int choose_projection(cc) struct control *cc; { int i,num=-1; char ans; printf("\nChoose projection type\n\n"); for(i=0;iproj=ans; cc->pnum=num; return(num); } /******************************************************************** ** ** type g -- grey all lut[] files ** G -- grey only lut[] ** i -- initial header map ** r -- reset lut[] to lutc[] ** ********************************************************************* */ void set_lut(type) char type; { int k,hue,brite,j; int color[3]; double dbrite,dval; float val,minval; if(type=='c') { Grey=0; for(k=15;k<256;k++) { lutc[k].r=lut[k].r=k; lutc[k].g=lut[k].g=k; lutc[k].b=lut[k].b=k; } lut[ 0].r= 0;lut[ 0].g= 0;lut[ 0].b= 0; lut[ 1].r= 46;lut[ 1].g= 46;lut[ 1].b= 46; lut[ 2].r=128;lut[ 2].g=128;lut[ 2].b=128; lut[ 3].r=255;lut[ 3].g=255;lut[ 3].b=255; lut[ 4].r=255;lut[ 4].g= 0;lut[ 4].b= 0; lut[ 5].r=255;lut[ 5].g=128;lut[ 5].b= 0; lut[ 6].r=255;lut[ 6].g=255;lut[ 6].b= 0; lut[ 7].r= 0;lut[ 7].g=255;lut[ 7].b= 0; lut[ 8].r= 0;lut[ 8].g=255;lut[ 8].b=255; lut[ 9].r= 64;lut[ 9].g= 64;lut[ 9].b=255; lut[10].r=255;lut[10].g= 0;lut[10].b=255; lut[11].r=192;lut[11].g= 96;lut[11].b= 48; lut[12].r= 96;lut[12].g= 28;lut[12].b= 14; lut[13].r=128;lut[13].g=128;lut[13].b=255; lut[14].r=105;lut[14].g= 90;lut[14].b= 75; lut[15].r= 0;lut[15].g= 20;lut[15].b= 60; } if(type=='g') { for(k=0;k<256;k++) { lutc[k].r=lut[k].r=k; lutc[k].g=lut[k].g=k; lutc[k].b=lut[k].b=k; } Grey=1; } if(type=='G') { for(k=0;k<256;k++) { lut[k].r=k; lut[k].g=k; lut[k].b=k; } Grey=1; } if(type=='i') { for(k=0;k<256;k++) { lutc[k].r=lut[k].r=k; lutc[k].g=lut[k].g=k; lutc[k].b=lut[k].b=k; } lut[ 64].r= 0;lut[ 64].g= 0;lut[ 64].b=128; lut[127].r= 0;lut[127].g=100;lut[127].b= 0; lut[191].r=255;lut[191].g= 0;lut[191].b= 0; lut[192].r=255;lut[192].g=128;lut[192].b= 0; lut[193].r=255;lut[193].g=255;lut[193].b= 0; lut[194].r= 0;lut[194].g=255;lut[194].b= 0; lut[195].r= 0;lut[195].g=255;lut[195].b=255; lut[196].r= 20;lut[196].g= 55;lut[196].b=255; lut[253].r=100;lut[253].g= 1;lut[253].b= 1; lut[254].r=100;lut[254].g= 1;lut[254].b= 1; } if(type=='r') { for(k=0;k<256;k++) { lut[k].r=lutc[k].r; lut[k].g=lutc[k].g; lut[k].b=lutc[k].b; } } WritePalette(lut); }