|
|
1.1 ! root 1: #include "map.h" ! 2: ! 3: /* For Albers formulas see Deetz and Adams "Elements of Map Projection", */ ! 4: /* USGS Special Publication No. 68, GPO 1921 */ ! 5: ! 6: static float r0sq, r1sq, d2, n, den, sinb1, sinb2; ! 7: static struct place plat1, plat2; ! 8: static southpole; ! 9: ! 10: static float num(s) ! 11: float s; ! 12: { ! 13: if(d2==0) ! 14: return(1); ! 15: s = d2*s*s; ! 16: return(1+s*(2./3+s*(3./5+s*(4./7+s*5./9)))); ! 17: } ! 18: ! 19: /* Albers projection for a spheroid, good only when N pole is fixed */ ! 20: ! 21: static int ! 22: Xspalbers(place,x,y) ! 23: struct place *place; ! 24: float *x, *y; ! 25: { ! 26: float r = sqrt(r0sq-2*(1-d2)*place->nlat.s*num(place->nlat.s)/n); ! 27: float t = n*place->wlon.l; ! 28: *y = r*cos(t); ! 29: if(!southpole) ! 30: *y = -*y; ! 31: *x = -r*sin(t); ! 32: return(1); ! 33: } ! 34: ! 35: /* lat1, lat2: std parallels; e2: squared eccentricity */ ! 36: ! 37: int (*albinit(lat1,lat2,e2))() ! 38: float lat1,lat2,e2; ! 39: { ! 40: float r1,r2; ! 41: extern (*azequalarea())(); ! 42: extern (*cylequalarea())(); ! 43: float t; ! 44: for(;;) { ! 45: if(lat1 < -90) ! 46: lat1 = -180 - lat1; ! 47: if(lat2 > 90) ! 48: lat2 = 180 - lat2; ! 49: if(lat1 <= lat2) ! 50: break; ! 51: t = lat1; lat1 = lat2; lat2 = t; ! 52: } ! 53: if(lat2-lat1 < 1) { ! 54: if(lat1 > 89) ! 55: return(azequalarea()); ! 56: return(0); ! 57: } ! 58: if(fabs(lat2+lat1) < 1) ! 59: return(cylequalarea(lat1)); ! 60: d2 = e2; ! 61: den = num(1.); ! 62: deg2rad(lat1,&plat1); ! 63: deg2rad(lat2,&plat2); ! 64: sinb1 = plat1.nlat.s*num(plat1.nlat.s)/den; ! 65: sinb2 = plat2.nlat.s*num(plat2.nlat.s)/den; ! 66: n = (plat1.nlat.c*plat1.nlat.c/(1-e2*plat1.nlat.s*plat1.nlat.s) - ! 67: plat2.nlat.c*plat2.nlat.c/(1-e2*plat2.nlat.s*plat2.nlat.s)) / ! 68: (2*(1-e2)*den*(sinb2-sinb1)); ! 69: r1 = plat1.nlat.c/(n*sqrt(1-e2*plat1.nlat.s*plat1.nlat.s)); ! 70: r2 = plat2.nlat.c/(n*sqrt(2-e2*plat2.nlat.s*plat2.nlat.s)); ! 71: r1sq = r1*r1; ! 72: r0sq = r1sq + 2*(1-e2)*den*sinb1/n; ! 73: southpole = lat1<0 && plat2.nlat.c>plat1.nlat.c; ! 74: return(Xspalbers); ! 75: } ! 76: ! 77: int (*sp_albers(lat1,lat2))() ! 78: float lat1, lat2; ! 79: { ! 80: return(albinit(lat1,lat2,EC2)); ! 81: } ! 82: ! 83: int (*albers(lat1,lat2))() ! 84: float lat1,lat2; ! 85: { ! 86: return(albinit(lat1,lat2,0.)); ! 87: } ! 88: ! 89: static float scale = 1; ! 90: static float twist = 0; ! 91: ! 92: albscale(x,y,lat,lon) ! 93: float x,y,lat,lon; ! 94: { ! 95: struct place place; ! 96: float alat, alon, x1,y1; ! 97: scale = 1; ! 98: twist = 0; ! 99: invalb(x,y,&alat,&alon); ! 100: twist = lon - alon; ! 101: deg2rad(lat,&place.nlat); ! 102: deg2rad(lon,&place.wlon); ! 103: Xspalbers(&place,&x1,&y1); ! 104: scale = sqrt((x1*x1+y1*y1)/(x*x+y*y)); ! 105: } ! 106: ! 107: invalb(x,y,lat,lon) ! 108: float x,y,*lat,*lon; ! 109: { ! 110: int i; ! 111: float sinb_den, sinp; ! 112: x *= scale; ! 113: y *= scale; ! 114: *lon = atan2(-x,fabs(y))/(RAD*n) + twist; ! 115: sinb_den = (r0sq - x*x - y*y)*n/(2*(1-d2)); ! 116: sinp = sinb_den; ! 117: for(i=0; i<5; i++) ! 118: sinp = sinb_den/num(sinp); ! 119: *lat = asin(sinp)/RAD; ! 120: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.