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