|
|
1.1 root 1: #include <stdio.h>
2: #include <math.h>
3: /* development of a loxodrome from a unit sphere onto a plane
4: the loxodrome passes through 0,0 on the sphere,
5: inclined a (alpha) from the equator
6:
7: latitude p (phi) positive north
8: longitude t (theta) positive east - opposite to "map"
9: all angles in radians
10:
11: x,y are coords of developed curve
12: c (chi) is angle of inclination of developed curve from x axis
13:
14: dx/dp = cos(c)/sin(a)
15: dy/dp = sin(c)/sin(a)
16: dc/dp = tan(p)/tan(a)
17: dt/dp = 1/(cos(p)*tan(a))
18:
19: cc lox.c -lport -lF77 -lI77
20: a.out alpha here alpha is in degrees
21: */
22: extern char *realloc();
23: static double renorm();
24: static bsearch(), getxy(), calcf(), solve();
25: #define DEG (180/PI)
26:
27: /* curlicue is an ordered sequence of points
28: along the midline of the spiral, in both geographic
29: and developed coordinates */
30: struct curl {
31: double phi,x,y,theta,chi;
32: } *curlicue; /* the midline */
33: int nc; /* number of points on the midline */
34:
35: double a = PI/10;/* 45 degrees */
36: double sa,ca,ta; /* sin(a), cos(a), tan(a) */
37: static signa = 1;
38: static double z[4]; /* x==z[0],y==z[1],t=z[2],c==z[3] */
39:
40: /* inputs to dodes, port library integration routine */
41:
42: static int n = 4;
43: static double z0[4]; /* initial values = 0,0,0,a */
44: static double p0; /* initial value of p = 0 */
45: static double p1 = 86*PI/180; /* final value */
46: static double dt; /* current time step */
47: static double deg = PI/180; /* 1 degree */
48: static float errpar[2] = {1.e-7,1.e-7};
49:
50: static
51: f(p,z,n,r)
52: double *p, *z, *r;
53: int *n;
54: {
55: r[0] = cos(z[3])/sa;
56: r[1] = sin(z[3])/sa;
57: r[2] = 1/(cos(*p)*ta);
58: r[3] = sin(*p)*r[2];
59: }
60: static
61: handle(t0,z0,t1,z1,n,dt,ts,e)
62: double *t0,*z0,*t1,*z1,*dt,*ts;
63: float *e;
64: int *n;
65: {
66: if(*dt > deg) *dt = deg;
67: if(fabs(z1[3]-z0[3])>.1 && *dt >.00001)
68: *dt *= .1/fabs(z1[3]-z0[3]);
69: if(*t1 + *dt >= PI/2)
70: *dt = (PI/2 - *t1)/2;
71: if(*t1 + *dt > *ts)
72: *dt = *ts - *t1 + .00001;
73: curlicue = (struct curl*)realloc((char*)curlicue,
74: (nc+1)*sizeof(*curlicue));
75: curlicue[nc].phi = *t1;
76: curlicue[nc].x = z1[0];
77: curlicue[nc].y = z1[1];
78: curlicue[nc].theta = z1[2];
79: curlicue[nc].chi = z1[3];
80: nc++;
81: printf("%f %f %f %f %f\n",*t1*DEG,
82: z1[0]*DEG,z1[1]*DEG,z1[2]*DEG,z1[3]*DEG);
83: fflush(stdout);
84: if(*t0==*t1) abort();
85: }
86: main(argc,argv)
87: char **argv;
88: {
89: double u,v,x,y;
90: a = atof(argv[1])/DEG;
91: if(a < 0)
92: signa = -1;
93: sa = sin(a);
94: ca = cos(a);
95: ta = sa/ca;
96: z0[3] = a;
97: dt = deg;
98: handle(°,z0,&p0,z0,&n,°,&p1,errpar);
99: dodes_(f,z0,&n,&p0,&p1,&dt,errpar,handle);
100: while(scanf("%lf %lf",&u,&v)==2) {
101: double u1 = u/DEG, v1=v/DEG;
102: double d,p,t;
103: v1 = renorm(u1,bsearch(u1,0),v1);
104: solve(u1,v1,&d,&p,&t);
105: printf("%f %f %f %f %f %f\n",
106: u,v,v1*DEG,d*DEG,p*DEG,t*DEG);
107: fflush(stdout);
108: getxy(d,p,&x,&y);
109: printf("%f %f\n",x*DEG,y*DEG);
110: fflush(stdout);
111: }
112: }
113: /* find the index for latitude (i=0) or longitude (i=1)
114: in array curlicue. In case of longitude, u must have
115: been normalized by renorm() */
116: static
117: bsearch(u,i)
118: double u;
119: {
120: int top = nc;
121: int bot = 0;
122: int mid;
123: while(bot<top-1) {
124: mid = (bot+top)/2;
125: if(i==0&&curlicue[mid].phi<=u||
126: i==1&&(signa>0&&curlicue[mid].theta<=u||
127: signa<0&&curlicue[mid].theta>=u))
128: bot = mid;
129: else
130: top = mid;
131: }
132: return bot;
133: }
134: /* wind v thru multiples of 2*PI until it lies within PI
135: of the (linearly interpolated) midline */
136: static double
137: renorm(u,n,v)
138: double u,v;
139: {
140: double t,fract;
141: fract = (u-curlicue[n].phi)/
142: (curlicue[n+1].phi-curlicue[n].phi);
143: t = curlicue[n].theta*(1-fract) +
144: curlicue[n+1].theta*fract;
145: if(signa > 0) while(v<t-PI)
146: v += 2*PI;
147: else while(v>t+PI)
148: v -= 2*PI;
149: return v;
150: }
151: /* given the height (d) and foot (p,t) of the perpendicular projection
152: of a point onto the midline, return the x-y coordinates of the point*/
153: static
154: getxy(d,p,xp,yp)
155: double d,p,*xp,*yp;
156: {
157: int n, sign = 1;
158: double fract, x0, y0, c0;
159: if(p < 0) {
160: p = -p;
161: sign = -1;
162: }
163: n = bsearch(p,0);
164: fract = (p-curlicue[n].phi)/
165: (curlicue[n+1].phi-curlicue[n].phi);
166: /*printf("n,fract %d %f\n",n,fract);*/
167: x0 = sign*(curlicue[n].x*(1-fract) +
168: curlicue[n+1].x*fract);
169: y0 = sign*(curlicue[n].y*(1-fract) +
170: curlicue[n+1].y*fract);
171: c0 = curlicue[n].chi*(1-fract) +
172: curlicue[n+1].chi*fract;
173: *xp = x0 - d*sin(c0);
174: *yp = y0 + d*cos(c0);
175: }
176:
177: /*
178: solve simultaneously for d,p,t (dist to midline,
179: phi lat on midline,
180: theta lon on midline)
181: given a, u, v (rhumb angle from parallels, lat, east lon)
182:
183: sin d sin a = cos u sin(t-v) law of sines
184: sin u = cos d sin p + sin d cos p cos a law of cosines
185: t tan a = log tan (p/2 + PI/4) eqn of rhumb line
186:
187: initial guess: d=u-p, t=v, p from table lookup in curlicue
188: */
189: static double su,cu,v0;
190: static int n3 = 3, jmax = 50;
191: static double acc = 1e-6;
192: static
193: calcf(n,x,nf,g)
194: int *n, *nf;
195: double *x,*g;
196: {
197: double f[3], sd;
198: if(x[1]>=PI/2) {
199: *nf = 0;
200: return;
201: }
202: sd = sin(x[0]);
203: f[0] = sd*sa-cu*sin(x[2]-v0);
204: f[1] = su - cos(x[0])*sin(x[1]) - sd*cos(x[1])*ca;
205: f[2] = x[2]*ta - log(tan(x[1]/2+PI/4));
206: /*printf("calcf: d p t %f %f %f",
207: x[0]*DEG,x[1]*DEG,x[2]*DEG);
208: printf(" resid %f %f %f\n",f[0],f[1],f[2]);
209: fflush(stdout);*/
210: *g = f[0]*f[0]+f[1]*f[1]+f[2]*f[2];
211: }
212: /* given renormed lat-lon (u,v) find the height (*dp) and foot
213: (*pp,*tp) of a perpendicular to the midline. precondition: u>=0 */
214: static
215: solve(u,v,dp,pp,tp)
216: double u,v,*dp,*pp,*tp;
217: {
218: double z[3]; /* d, p, t */
219: int n;
220: if(u < 0) {
221: solve(-u,-v,dp,pp,tp);
222: *dp = -*dp;
223: *pp = -*pp;
224: *tp = -*tp;
225: return;
226: }
227: n = bsearch(signa*fabs(v),1);
228: su = sin(u);
229: cu = cos(u);
230: z[1] = curlicue[n].phi; /* initial guess */
231: if(signa*v < 0) z[1] = -z[1];
232: z[0] = u - z[1];
233: z[2] = v0 = v;
234: printf("inputs (deg) %f %f\n",u*DEG,v*DEG);
235: printf("interval %d guess (deg) %f %f %f\n",n,
236: z[0]*DEG,z[1]*DEG,z[2]*DEG);
237: fflush(stdout);
238: dsmnf_(&n3,z,calcf,&jmax,&acc);
239: *dp = z[0];
240: *pp = z[1];
241: *tp = z[2];
242: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.