/* Atmospheric refraction * Returns correction in degrees to be added to true altitude * to obtain apparent altitude. * * -- S. L. Moshier */ extern double atpress; /* millibars */ extern double attemp; /* degrees C */ extern double DTR; /* pi/180 */ #if __STDC__ double tan (double); #else double tan(); #endif double refrac(alt) double alt; /* altitude in degrees */ { double y, y0, D0, N, D, P, Q; int i; if( (alt < -2.0) || (alt >= 90.0) ) return(0.0); /* For high altitude angle, AA page B61 * Accuracy "usually about 0.1' ". */ if( alt > 15.0 ) { D = 0.00452*atpress/((273.0+attemp)*tan( DTR*alt )); return(D); } /* Formula for low altitude is from the Almanac for Computers. * It gives the correction for observed altitude, so has * to be inverted numerically to get the observed from the true. * Accuracy about 0.2' for -20C < T < +40C and 970mb < P < 1050mb. */ /* Start iteration assuming correction = 0 */ y = alt; D = 0.0; /* Invert Almanac for Computers formula numerically */ P = (atpress - 80.0)/930.0; Q = 4.8e-3 * (attemp - 10.0); y0 = y; D0 = D; for( i=0; i<4; i++ ) { N = y + (7.31/(y+4.4)); N = 1.0/tan(DTR*N); D = N*P/(60.0 + Q * (N + 39.0)); N = y - y0; y0 = D - D0 - N; /* denominator of derivative */ if( (N != 0.0) && (y0 != 0.0) ) /* Newton iteration with numerically estimated derivative */ N = y - N*(alt + D - y)/y0; else /* Can't do it on first pass */ N = alt + D; y0 = y; D0 = D; y = N; } return( D ); }