int fill_planet_data( PLANET_DATA *pdata, const int planet_no, const double jd, const double observer_lat, const double observer_lon, const char *vsop_data) { double loc_sidereal_time = green_sidereal_time( jd) + observer_lon; double t_centuries = (jd - J2000) / 36525.; double obliquity = mean_obliquity( t_centuries); double loc[3]; pdata->jd = jd; if( planet_no == 10) /* get lunar data, not VSOP */ { double fund[N_FUND]; lunar_fundamentals( vsop_data, t_centuries, fund); lunar_lon_and_dist( vsop_data, fund, &pdata->ecliptic_lon, &pdata->r, 0L); pdata->ecliptic_lon *= pi / 180.; pdata->ecliptic_lat = lunar_lat( vsop_data, fund, 0L) * pi / 180.; } else { /* What we _really_ want is the location of the sun as */ /* seen from the earth. VSOP gives us the opposite, */ /* i.e., where the _earth_ is as seen from the _sun_. */ /* To evade this, we add PI to the longitude and */ /* negate the latitude. */ pdata->ecliptic_lon = calc_vsop_loc( vsop_data, planet_no, 0, t_centuries, 0.) + pi; pdata->ecliptic_lat = -calc_vsop_loc( vsop_data, planet_no, 1, t_centuries, 0.); pdata->r = calc_vsop_loc( vsop_data, planet_no, 2, t_centuries, 0.); } polar3_to_cartesian( loc, pdata->ecliptic_lon, pdata->ecliptic_lat); memcpy( pdata->ecliptic_loc, loc, 3 * sizeof( double)); /* At this point, loc is a unit vector in ecliptic */ /* coords of date. Rotate it by 'obliquity' to get */ /* a vector in equatorial coords of date: */ rotate_vector( loc, obliquity, 0); memcpy( pdata->equatorial_loc, loc, 3 * sizeof( double)); /* The following two rotations take us from a vector in */ /* equatorial coords of date to an alt/az vector: */ rotate_vector( loc, -loc_sidereal_time, 2); /* printf( "LST: %lf\n", fmod( loc_sidereal_time * 180. / pi, 360.)); */ pdata->hour_angle = atan2( loc[1], loc[0]); rotate_vector( loc, observer_lat - pi / 2., 1); memcpy( pdata->altaz_loc, loc, 3 * sizeof( double)); return( 0); }
int main( const int argc, const char **argv) { const double j2000 = 2451545.; /* 1.5 Jan 2000 = JD 2451545 */ int i, julian = 0, verbose = 0, chinese_calendar = 0; double t, t_centuries, t_cen2, t_cen3, t_cen4, t0, ut_time; double m, mp, f, e, max_date = 4000. * 365.25 + j2000; double lunar, dist, fund[N_FUND], rate = 29.5306, t_final; char buff[80]; long long_to_write; double k; FILE *log_file = NULL, *vsop_file, *data_file = NULL; char *vsop_tbuff, FAR *vsop_data; time_t curr_time = time( NULL); vsop_file = fopen( "vsop.bin", "rb"); if( !vsop_file) { printf( "Couldn't open vsop.bin"); return( -1); } vsop_tbuff = (char *)malloc( VSOP_CHUNK); vsop_data = (char *)malloc( VSOP_CHUNK * 22U); for( i = 0; i < 22; i++) { if( !fread( vsop_tbuff, VSOP_CHUNK, 1, vsop_file)) { printf( "Couldn't read VSOP data\n"); return( -2); } FMEMCPY( vsop_data + (unsigned)i * VSOP_CHUNK, vsop_tbuff, VSOP_CHUNK); } fclose( vsop_file); free( vsop_tbuff); for( i = 0; i < argc; i++) if( argv[i][0] == '-') switch( argv[i][1]) { case 'j': case 'J': julian = 1; break; case 'c': case 'C': chinese_calendar = 1; break; case 'v': case 'V': verbose = 1; break; case 'l': case 'L': log_file = fopen( argv[i] + 2, "wb"); break; case 'd': case 'D': data_file = fopen( argv[i] + 2, "wb"); break; case 'm': case 'M': max_date = (atof( argv[i] + 2) - 2000.) * 365.25 + j2000; break; default: break; } t0 = t = j2000 + 365.25 * (atof( argv[1]) - 2000.); k = floor( (atof( argv[1]) - 2000.) * 12.3685); if( data_file) { long_to_write = (long)k; fwrite( &long_to_write, 1, sizeof( long), data_file); } t_final = max_date - 1.; while( t_final < max_date) for( i = 0; i < 4; i++) { double t2, dlon_1, dlon_2, phase_angle, solar_lon, time_lag; static const char *phase_name[4] = { "New moon ", "1st qtr. ", "Full moon", "last qtr." }; t_centuries = k / 1236.85; /* first approx */ t = 2451550.09765 + 29.530588853 * k + (1.337e-4 - 1.5e-7 * t_centuries) * t_centuries * t_centuries; t_centuries = (t - j2000) / 36525.; t_cen2 = t_centuries * t_centuries; t_cen3 = t_cen2 * t_centuries; t_cen4 = t_cen3 * t_centuries; m = 2.5534 + 29.10535669 * k - 2.18e-5 * t_cen2 - 1.1e-7 * t_cen3; mp = 201.5643 + 385.81693528 * k + .0107438 * t_cen2 + 1.239e-5 * t_cen3 - 5.8e-8 * t_cen4; f = 160.7108 + 390.67050274 * k - 1.6541e-3 * t_cen2 - 2.27e-6 * t_cen3 + 1.1e-8 * t_cen4; m *= PI / 180.; f *= PI / 180.; mp *= PI / 180.; e = 1. - .002516 * t_centuries - 7.4e-6 * t_cen2; switch( i) { case NEW_MOON: t += -.40720 * sin( mp) +.17241 * sin( m) * e +.01608 * sin( mp + mp) +.01039 * sin( f + f) +.00739 * sin( mp - m) * e -.00514 * sin( mp + m) * e +.00208 * sin( m + m) * e * e -.00111 * sin( mp - f - f); break; case FIRST_QUARTER: case LAST_QUARTER: t += -.62801 * sin( mp) +.17172 * sin( m) * e -.01183 * sin( mp + m) * e +.00862 * sin( mp + mp) +.00804 * sin( f + f) +.00454 * sin( mp - m) * e +.00204 * sin( m + m) * e * e -.00180 * sin( mp - f - f); t += ((i == FIRST_QUARTER) ? .00306 : -.00306); break; case FULL_MOON: t += -.40614 * sin( mp) +.17302 * sin( m) * e +.01614 * sin( mp + mp) +.01043 * sin( f + f) +.00734 * sin( mp - m) * e -.00515 * sin( mp + m) * e +.00209 * sin( m + m) * e * e -.00111 * sin( mp - f - f); break; default: break; } phase_angle = (double)i * 90.; t_centuries = (t - j2000) / 36525.; time_lag = approx_solar_dist( t_centuries) / SPEED_OF_LIGHT; time_lag /= 86400. * 36525.; lunar_fundamentals( vsop_data, t_centuries, fund); lunar_lon_and_dist( vsop_data, fund, &lunar, &dist, 0L); solar_lon = calc_vsop_loc( vsop_data, 3, 0, t_centuries - time_lag, 0.); solar_lon = solar_lon * 180. / PI - 180.; dlon_1 = lunar - solar_lon - phase_angle; while( dlon_1 < -180.) dlon_1 += 360.; while( dlon_1 > 180.) dlon_1 -= 360.; if( verbose) { full_ctime( buff, t, julian); printf( " first time is %s; lon diff %lf\n", buff, dlon_1); } t2 = t - rate * dlon_1 / 360.; t_centuries = (t2 - j2000) / 36525.; lunar_fundamentals( vsop_data, t_centuries, fund); lunar_lon_and_dist( vsop_data, fund, &lunar, &dist, 0L); solar_lon = calc_vsop_loc( vsop_data, 3, 0, t_centuries - time_lag, 0.); solar_lon = solar_lon * 180. / PI - 180.; dlon_2 = lunar - solar_lon - phase_angle; while( dlon_2 < -180.) dlon_2 += 360.; while( dlon_2 > 180.) dlon_2 -= 360.; if( verbose) { full_ctime( buff, t2, julian); printf( " second time is %s; lon diff %lf\n", buff, dlon_2); } t_final = (t * dlon_2 - t2 * dlon_1) / (dlon_2 - dlon_1); ut_time = t_final - td_minus_ut( t_final) / 86400.; full_ctime( buff, ut_time, julian); if( log_file) { if( chinese_calendar) fprintf( log_file, "%7ld %s\n", (long)floor( ut_time - 1. / 6.), buff); else fprintf( log_file, "%s: %s\n", phase_name[i], buff); } buff[17] = '\0'; /* trim the seconds */ if( !chinese_calendar) { printf( "%s ", buff); if( i == 3) printf( "\n"); } if( data_file) { double diff = t_final - ( 2451550.09765 + 29.530588853 * k); diff *= 86400.; if( verbose) printf( "Time diff %lf\n", diff); long_to_write = (long)diff; fwrite( &long_to_write, 1, sizeof( long), data_file); } if( chinese_calendar) { k++; i = 4; } else /* just moving to next _phase_ */ k += .25; if( curr_time != time( NULL)) { curr_time = time( NULL); printf( "JD %.3lf (%.3lf)\r", t_final, (t_final - j2000) / 365.25 + 2000.); } } if( chinese_calendar) while( t0 < max_date) { double t_centuries, time_lag, delta_t = 1.; double solar_lon; const double thirty_deg = PI / 6.; long solar_month = 0L, year; while( fabs( delta_t) > .00001) /* resolution a little better than 1s */ { t_centuries = (t0 - j2000) / 36525.; time_lag = approx_solar_dist( t_centuries) / SPEED_OF_LIGHT; time_lag /= 86400. * 36525.; solar_lon = calc_vsop_loc( vsop_data, 3, 0, t_centuries - time_lag, 0.); solar_month = (long)floor( solar_lon / thirty_deg + .5); solar_lon -= (double)solar_month * thirty_deg; delta_t = solar_lon * 365.25 / (2. * PI); t0 -= delta_t; if( verbose) printf( "delta_t: %.5lf JD %.5lf\n", delta_t, t0); } solar_month = (solar_month + 7) % 12; /* flip around to winter sol */ year = (long) floor( (t0 - (double)solar_month * 30.5 - 100.) / 365.25); year -= 2074L; ut_time = t0 - td_minus_ut( t0) / 86400.; full_ctime( buff, ut_time, julian); if( log_file) fprintf( log_file, "%7ld z %s %2ld %5ld\n", (long)floor( ut_time - 1. / 6.), buff, solar_month + 1, year); if( curr_time != time( NULL)) { curr_time = time( NULL); printf( "%7ld z %s %2ld %5ld: %.3lf\n", (long)floor( ut_time - 1. / 6.), buff, solar_month + 1, year, (ut_time - j2000) / 365.25 + 2000.); } t0 += 365.25 / 12.; } fclose( data_file); fclose( log_file); return( 0); }
int find_events( int sat_no, double t1, double t2, int viewpoint, EVENT *e) { double t, lon_j, lat_j, rad_j, lon_e, lat_e, rad_e; double loc[9], tloc[18], *tptr, step, delta_lat, prev_delta_lat; double tc, lon_s, lat_s, rad_s, prev_delta = 0., delta; int i, rval = 0; t = t1; step = 10. / speeds[sat_no - 1]; while( t < t2) { tc = (t - 2451545.) / 36525.; /* re-cvt to julian centuries */ lon_j = calc_vsop_loc( vsop_data, 5, 0, tc, 0.); lat_j = calc_vsop_loc( vsop_data, 5, 1, tc, 0.); rad_j = calc_vsop_loc( vsop_data, 5, 2, tc, 0.); lon_e = calc_vsop_loc( vsop_data, 3, 0, tc, 0.); lat_e = calc_vsop_loc( vsop_data, 3, 1, tc, 0.); rad_e = calc_vsop_loc( vsop_data, 3, 2, tc, 0.); loc[0] = rad_j * cos( lat_j) * cos( lon_j); loc[1] = rad_j * cos( lat_j) * sin( lon_j); loc[2] = rad_j * sin( lat_j); loc[6] = rad_e * cos( lat_e) * cos( lon_e); loc[7] = rad_e * cos( lat_e) * sin( lon_e); loc[8] = rad_e * sin( lat_e); calc_jsat_loc( t, tloc, 1 << (sat_no - 1), 0L); tptr = tloc + (sat_no - 1) * 3; loc[3] = loc[0] + tptr[0] * AU_PER_JRAD; loc[4] = loc[1] + tptr[1] * AU_PER_JRAD; loc[5] = loc[2] + tptr[2] * AU_PER_JRAD; if( viewpoint) { for( i = 0; i < 9; i++) loc[i] -= loc[6 + i % 3]; lon_j = atan2( loc[1], loc[0]); lat_j = atan( loc[2] / sqrt( loc[0] * loc[0] + loc[1] * loc[1])); } rad_s = sqrt( loc[3] * loc[3] + loc[4] * loc[4] + loc[5] * loc[5]); lon_s = atan2( loc[4], loc[3]); while( lon_s - lon_j > PI) lon_s -= PI + PI; while( lon_s - lon_j <-PI) lon_s += PI + PI; lat_s = asin( loc[5] / rad_s); delta = (lon_s - lon_j) * rad_s / AU_PER_JRAD; delta_lat = (lat_s - lat_j) * rad_s / AU_PER_JRAD; delta_lat *= 1.071374; /* stretch for jup's oblateness */ if( delta * prev_delta < 0.) /* zero crossed */ { double t_crossing, diff, a, b, c, dx, dy, dist = 0.; dx = prev_delta - delta; dy = prev_delta_lat - delta_lat; a = dx * dx + dy * dy; /* quadratic for intercept */ b = 2. * (dx * delta + dy * delta_lat); c = delta_lat * delta_lat + delta * delta - 1.; diff = b * b - 4. * a * c; t_crossing = t + b * step / (2. * a); t = t_crossing + (180. / speeds[sat_no - 1]) * .9; if( diff > 0.) /* if real solution, ie, sat doesn't miss */ { diff = sqrt( diff) * step / (2. * a); diff = fabs( diff); for( i = 0; i < 3; i++) dist += (loc[i + 6] - loc[i]) * (loc[i + 6] - loc[i]); t_crossing += sqrt( dist) / AU_PER_DAY; e[0].t = t_crossing - diff; e[0].sat = sat_no; e[0].event_type = (prev_delta > 0.); if( !viewpoint) e[0].event_type |= FROM_SUN; e[1].t = t_crossing + diff; e[1].sat = sat_no; e[1].event_type = e[0].event_type; e[0].event_type |= EVENT_START; if( !quiet) { show_event( stdout, e); show_event( stdout, e + 1); } e += 2; rval += 2; } delta = 0.; } prev_delta = delta; prev_delta_lat = delta_lat; t += step; } return( rval); }