/* A10_EXTR.CPP Copyright 1997, Project Pluto */ /* All rights reserved. This source code may be used freely for */ /* non-commercial uses. */ /* Under MSC, compile as: cl -W4 -Ox a10_extr.cpp */ /* Under Watcom, compile as: wcl386 -W4 -Ox a10_extr.cpp */ /* If all you want is the example DOS program, add -c -DMAKE_EXE */ /* This includes some routines to figure out which CDs would be needed */ /* to cover a given area, plus the actual code to do the extraction. */ /* The choice between A1.0 and A2.0 is controlled via the global int */ /* using_a20. If you stick in an SA1.0 or SA2.0 disk, the code will */ /* automatically recognize that fact and extract data from it. */ #include #include #include #define MAX_RA (360L * 3600L * 100L) #define SPACING (MAX_RA / n_entries) #define ZONE_SIZE (MAX_RA / 48L) #define BUFFSIZE 1000 #define EXTRACT struct extract #define SWAP( A, B, TEMP) { TEMP = A; A = B; B = TEMP; } #define SA10_DISK 99 static long n_entries = 1440L; /* Yes, I realize globals are evil... but: */ int using_a20 = 0; EXTRACT { long ra1, ra2, spd1, spd2; long start_rec, end_rec; int zone_no, cd_no; }; /* The 24 declination zones of the A1.0 catalog are spread out in a */ /* somewhat random manner across ten CDs, as shown in this table: */ static const char cd_table[24] = { 1, 1, 6, 5, 3, 2, 1, 4, 6, 5, 7, 10, 8, 7, 8, 9, 9, 4, 10, 3, 2, 6, 2, 3 }; /* Those of the A2.0 are spread out as follows, over eleven CDs: */ static const char cd_table_a20[24] = { 1, 1, 9, 7, 5, 4, 3, 2, 1, 6, 7, 10, 9, 8, 8,11,10,11, 6, 4, 2, 3, 3, 2 }; /* 0 15 30 45 60 75 */ /* 90 105 120 135 150 165 */ int find_needed_a10_cds( const double center_dec_degrees, const double height_degrees, int *ret_arr) { int zone, rval = 0, i, j, temp_int; double south_end_spd = 90. + center_dec_degrees - height_degrees / 2.; double north_end_spd = 90. + center_dec_degrees + height_degrees / 2.; const char *table = (using_a20 ? cd_table_a20 : cd_table); for( zone = 0; zone < 24; zone++) if( (double)(zone + 1) * 7.5 > south_end_spd && (double)zone * 7.5 < north_end_spd) { for( i = 0; i < rval && table[zone] != ret_arr[i]; i++) ; if( i == rval) ret_arr[rval++] = table[zone]; } /* bubblesort in order of CD # (small array) */ for( i = 0; i < rval; i++) for( j = i + 1; j < rval; j++) if( ret_arr[j] < ret_arr[i]) SWAP( ret_arr[i], ret_arr[j], temp_int); return( rval); } static int find_extracts( EXTRACT *ret_arr, const long center_ra, const long center_spd, const long width, const long height) { EXTRACT total, *tptr = ret_arr; int rval, i, j; long zone, delta = 0L; total.ra1 = center_ra - width / 2L; total.ra2 = center_ra + width / 2L; total.spd1 = center_spd - height / 2L; total.spd2 = center_spd + height / 2L; for( zone = 0; zone < 24L; zone++) if( zone * ZONE_SIZE <= total.spd2 && (zone + 1L) * ZONE_SIZE > total.spd1) { memcpy( tptr, &total, sizeof( EXTRACT)); if( tptr->spd2 > (zone + 1L) * ZONE_SIZE) tptr->spd2 = (zone + 1L) * ZONE_SIZE; if( tptr->spd1 < zone * ZONE_SIZE) tptr->spd1 = zone * ZONE_SIZE; tptr->zone_no = (int)zone; tptr->cd_no = (using_a20 ? cd_table_a20[tptr->zone_no] : cd_table[tptr->zone_no]); tptr++; } rval = tptr - ret_arr; if( total.ra1 < 0L) delta = MAX_RA; if( total.ra2 > MAX_RA) delta = -MAX_RA; if( delta) /* wraps around 0h: duplicating time: */ { memcpy( tptr, ret_arr, rval * sizeof( EXTRACT)); for( i = 0; i < rval; i++, tptr++) { tptr->ra1 += delta; tptr->ra2 += delta; } rval *= 2; tptr = ret_arr; for( i = 0; i < rval; i++, tptr++) { if( tptr->ra1 < 0L) tptr->ra1 = 0L; if( tptr->ra2 < 0L) tptr->ra2 = 0L; if( tptr->ra1 > MAX_RA) tptr->ra1 = MAX_RA; if( tptr->ra2 > MAX_RA) tptr->ra2 = MAX_RA; } } /* bubblesort in order of CD # (small array) */ /* within a CD, sort by zone # */ for( i = 0; i < rval; i++) for( j = i + 1; j < rval; j++) if( ret_arr[j].cd_no < ret_arr[i].cd_no || (ret_arr[j].cd_no == ret_arr[i].cd_no && ret_arr[j].zone_no < ret_arr[i].zone_no)) { total = ret_arr[j]; ret_arr[j] = ret_arr[i]; ret_arr[i] = total; } return( rval); } static int set_file_extents( int n_extents, EXTRACT *ret_arr) { char *filename = (n_entries == 180L ? "sa10.idx" : "a10.idx"); FILE *ifile; if( using_a20) filename = (n_entries == 180L ? "sa20.idx" : "a20.idx"); ifile = fopen( filename, "rb"); if( !ifile) return( -2); while( n_extents--) { int start = (int)( ret_arr->ra1 / SPACING); int end = (int)( (ret_arr->ra2 + SPACING - 1) / SPACING); long loc = ((n_entries + 1L) * (long)ret_arr->zone_no + start); fseek( ifile, loc * 4L, SEEK_SET); fread( &ret_arr->start_rec, sizeof( long), 1, ifile); loc += (long)( end - start); fseek( ifile, loc * 4L, SEEK_SET); fread( &ret_arr->end_rec, sizeof( long), 1, ifile); ret_arr++; } fclose( ifile); return( 0); } int extract_a10_data( const int cd_letter, const double ra_degrees, const double dec_degrees, const double width_degrees, const double ht_degrees, FILE *ofile) { EXTRACT *ret_arr = (EXTRACT *)calloc( 48, sizeof( EXTRACT)); int i, n_ret, rval = 0; long *buff; char sa10_file[20]; FILE *sa_test; n_ret = find_extracts( ret_arr, (long)( ra_degrees * 360000.), (long)( (dec_degrees + 90.) * 360000.), (long)( width_degrees * 360000.), (long)( ht_degrees * 360000.)); n_entries = 1440L; /* if ZONE0450.CAT is on the CD, and is smaller than 100MB, */ /* it's SA 1.0 or 2.0 */ sprintf( sa10_file, "%c:\\zone0450.cat", cd_letter); sa_test = fopen( sa10_file, "rb"); if( sa_test) { fseek( sa_test, 0L, SEEK_END); if( ftell( sa_test) < 100000000L) { n_entries = 180L; rval = SA10_DISK; } fclose( sa_test); } if( set_file_extents( n_ret, ret_arr)) { free( ret_arr); return( -2); } buff = (long *)calloc( BUFFSIZE, 3 * sizeof( long)); for( i = 0; i < n_ret; i++) { FILE *ifile; char filename[40]; EXTRACT *eptr = ret_arr + i; sprintf( filename, "%c:zone%04d.cat", cd_letter, eptr->zone_no * 75); ifile = fopen( filename, "rb"); if( ifile) { long n_to_read; int j, k, n_read; fseek( ifile, eptr->start_rec * 12L, SEEK_SET); n_to_read = eptr->end_rec - eptr->start_rec; while( n_to_read && ofile) { n_read = (( n_to_read > BUFFSIZE) ? BUFFSIZE : (int)n_to_read); n_read = fread( buff, 12, n_read, ifile); for( j = 0; j < n_read; j++) { long swapped[3], ra, spd; memcpy( swapped, buff + j * 3, 3 * sizeof( long)); for( k = 0; k < 3; k++) /* A1.0 data is "wrong-endian" */ { char tchar, *swapptr = (char *)( swapped + k); SWAP( swapptr[0], swapptr[3], tchar); SWAP( swapptr[1], swapptr[2], tchar); } ra = swapped[0]; spd = swapped[1]; if( spd > eptr->spd1 && spd < eptr->spd2 && ra > eptr->ra1 && ra < eptr->ra2) fwrite( buff + j * 3, 3, sizeof( long), ofile); } n_to_read -= n_read; } if( !rval) rval = eptr->cd_no; fclose( ifile); } } free( buff); free( ret_arr); return( rval); } #ifdef _WINDOWS #include /* For MessageBox( ) prototype */ int build_prompt_string( const int n_needed, const int *needed_cds, const char *prompt_string, const int cd_letter, char *output_prompt) { char tbuff[50]; int i; *tbuff = '\0'; if( n_needed > 1) { /* If multiple CDs will be needed, list 'em all up front: */ for( i = 0; i < n_needed - 1; i++) sprintf( tbuff + strlen( tbuff), "%d, ", needed_cds[i]); sprintf( tbuff + strlen( tbuff), "or %d", needed_cds[i]); } if( n_needed == 1) sprintf( tbuff, "%d", needed_cds[0]); for( i = 0; prompt_string[i] != '%'; i++) output_prompt[i] = prompt_string[i]; output_prompt[i] = ' '; strcpy( output_prompt + i + 1, tbuff); sprintf( output_prompt + strlen( output_prompt), prompt_string + i + 2, cd_letter); return( 0); } long windows_extract_a10_data( const int cd_letter, const double ra_degrees, const double dec_degrees, const double width_degrees, const double ht_degrees, FILE *ofile, const char *prompt_string) { int i, needed_cds[12], n_needed; n_needed = find_needed_a10_cds( dec_degrees, ht_degrees, needed_cds); while( n_needed) { int cd_no; cd_no = extract_a10_data( cd_letter, ra_degrees, dec_degrees, width_degrees, ht_degrees, ofile); if( cd_no == SA10_DISK) /* SA1.0 CD */ { /* printf( "SA1.0 data extracted\n"); */ return( 0); } if( cd_no > 0) { /* printf( "Data extracted from A1.0 CD #%d\n", cd_no); */ for( i = 0; i < n_needed; i++) if( cd_no == needed_cds[i]) { n_needed--; memmove( needed_cds + i, needed_cds + i + 1, (n_needed - i) * sizeof( int)); } } if( cd_no == -2) { /* printf( "A1.0/SA1.0 index not found!\n"); */ return( -2); } if( n_needed) { char buff[100], title[10]; build_prompt_string( n_needed, needed_cds, prompt_string, cd_letter, buff); sprintf( title, "A%d.0", using_a20 + 1); if( MessageBox( NULL, buff, title, MB_OKCANCEL) == IDCANCEL) return( -3); } } return( 0); } #else #include #include long dos_prompt_extract_a10_data( const int cd_letter, const double ra_degrees, const double dec_degrees, const double width_degrees, const double ht_degrees, FILE *ofile) { int i, needed_cds[12], n_needed; n_needed = find_needed_a10_cds( dec_degrees, ht_degrees, needed_cds); printf( "%d A%d.0 CDs needed for this area\n", n_needed, using_a20 + 1); if( n_needed == 0) /* a problem with the input area asked for */ return( -3L); while( n_needed) { int cd_no = extract_a10_data( cd_letter, ra_degrees, dec_degrees, width_degrees, ht_degrees, ofile); if( cd_no == SA10_DISK) /* SA1.0 CD */ { printf( "SA%d.0 data extracted\n", using_a20 + 1); return( 0); } if( cd_no > 0) { printf( "Data extracted from A%d.0 CD #%d\n", using_a20 + 1, cd_no); for( i = 0; i < n_needed; i++) if( cd_no == needed_cds[i]) { n_needed--; memmove( needed_cds + i, needed_cds + i + 1, (n_needed - i) * sizeof( int)); } } if( cd_no == -2) { printf( "A%d.0/SA%d.0 index not found!\n", using_a20 + 1, using_a20 + 1); return( -2); } if( n_needed > 1) { /* If multiple CDs will be needed, list 'em all up front: */ printf( "Please insert A%d.0 CD #", using_a20 + 1); for( i = 0; i < n_needed - 1; i++) printf( "%d, ", needed_cds[i]); printf( "or %d and hit Enter:\n", needed_cds[i]); } if( n_needed == 1) printf( "Please insert A%d.0 CD #%d and hit Enter:\n", using_a20 + 1, needed_cds[0]); if( n_needed) if( getch( ) == 27) return( -1); else { struct _find_t c_file; char *path = "z:\\*.*"; *path = (char)cd_letter; _dos_findfirst( path, _A_VOLID, &c_file); printf( "Volume name: %s\n", c_file.name); } } return( 0); } #endif #ifdef MAKE_EXE #include void main( int argc, char **argv) { int cd_letter = argv[5][0]; FILE *ofile = NULL; double center_ra = atof( argv[1]); double center_dec = atof( argv[2]); double width = atof( argv[3]); double height = atof( argv[4]); if( argc > 6) ofile = fopen( argv[6], "ab"); dos_prompt_extract_a10_data( cd_letter, center_ra, center_dec, width, height, ofile); if( ofile) fclose( ofile); printf( "Please reinsert the Guide CD and hit any key:"); getch( ); } #endif