├── chinese.dat ├── .gitignore ├── ll_test.txt ├── README.md ├── lun_tran.h ├── .github └── workflows │ └── github_actions_build.yml ├── gust86.h ├── mjd_defs.h ├── showelem.h ├── riseset3.h ├── colors.h ├── gaia.hdr ├── cgi_func.h ├── test_min.cpp ├── test_des.cpp ├── get_test.txt ├── xxx2rov.c ├── desigcgi.c ├── pollute.c ├── stringex.h ├── mini_dll.cpp ├── lun_test.cpp ├── mpc_hdr.htm ├── get_test.cpp ├── prectes2.cpp ├── vislimit.h ├── ll_test.c ├── utc_test.cpp ├── obliquit.cpp ├── ssattest.cpp ├── oblitest.cpp ├── cosptest.cpp ├── them_cat.c ├── comets.h ├── triton.cpp ├── moidtest.txt ├── cgicheck.htm ├── jpl_xref.h ├── jpl_url.c ├── disttest.cpp ├── gust_ref.cpp ├── test_des.txt ├── get_bin.h ├── getplane.cpp ├── adestags.c ├── watdefs.h ├── rckin.cpp ├── vsopson.cpp ├── get_out.txt ├── lunar.h ├── mpcorb2.cpp ├── superga2.cpp ├── big_vsop.txt ├── nanosecs.cpp ├── jsattest.cpp ├── watmake ├── mpc_time.c ├── adestest.cpp ├── brentmin.h ├── text_ca2.c ├── lunar64.def ├── mpc_func.h ├── cgicheck.cpp ├── utc_algo.cpp ├── mms.cpp ├── lunar.def ├── themis.cpp ├── pluto.cpp └── uranus1.cpp /chinese.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Bill-Gray/lunar/HEAD/chinese.dat -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled Object files 2 | *.slo 3 | *.lo 4 | *.o 5 | *.obj 6 | 7 | # Precompiled Headers 8 | *.gch 9 | *.pch 10 | 11 | # Compiled Dynamic libraries 12 | *.so 13 | *.dylib 14 | *.dll 15 | 16 | # Data files 17 | big_vsop.bin 18 | vsop.bin 19 | ps_1996.dat 20 | elp82.dat 21 | 22 | # Fortran module files 23 | *.mod 24 | 25 | # Compiled Static libraries 26 | *.lai 27 | *.la 28 | *.a 29 | *.lib 30 | 31 | # Executables 32 | *.exe 33 | *.out 34 | *.app 35 | 36 | adestest 37 | astcheck 38 | astephem 39 | calendar 40 | cgicheck 41 | colors 42 | colors2 43 | cosptest 44 | de_plan 45 | dist 46 | easter 47 | get_test 48 | htc20b 49 | integrat 50 | jd 51 | jevent 52 | jpl2b32 53 | jsattest 54 | lun_test 55 | marstime 56 | moidtest 57 | mpc2sof 58 | mpc_code 59 | oblitest 60 | persian 61 | phases 62 | prectest 63 | prectes2 64 | ps_1996 65 | ssattest 66 | tables 67 | testprec 68 | test_min 69 | test_ref 70 | themis 71 | them_cat 72 | uranus1 73 | utc_test 74 | vislimit 75 | -------------------------------------------------------------------------------- /ll_test.txt: -------------------------------------------------------------------------------- 1 | # Lines starting with '#' are comments. These are test 2 | # cases for 'll_test.c' (q.v.) 3 | #rval long. lat. alt. 4 | 0 290.1 44.02 18. n44 01 12.0, 69.9W, alt. 18m 5 | 0 221.04 -71.1 100. 221 2.4e, 71.1s 6 | 0 277.3 -55.45 217. w82.7 55.45s 217m 7 | 0 267.3 15.45 1028.7 w92.7 15.45N alt. 3375.0 ft 8 | 0 182.765 66.63625 3141. COM Long. 177 14 6W, Lat. 66 38 10.5 n, Alt. 3141m 9 | 0 177.663 -31.4159 2718. COM Long. 177.663E, Lat. s 31.4159, Alt. 2718m 10 | # Next line should fail; lat. minutes are > 60 11 | -2 0. 0. 0. COM Long. 177 14 6W, Lat. 66 61 10.5 n, Alt. 3141m 12 | # Next two lines should fail; compass direction are both for latitude or both for longit 13 | -2 0. 0. 0. COM Long. 177 14 6W, Lat. 66 21 10.5 E, Alt. 3141m 14 | -1 0. 0. 0. 69 53 49.2N n22 10 4.8, 98.425ft 15 | 0 290.103 22.168 38.1 69 53 49.2W n22 10 4.8, 125ft 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lunar 2 | Basic astronomical functions for solar system ephemerides, time systems, 3 | coordinate systems, etc. This includes some utilities based on these 4 | functions, such as a calendar computer and a utility to numerically 5 | integrate asteroid orbits. The code can be built for Windows, Linux, 6 | or BSD, and probably OS/X. Some documentation (in need of updates) is at 7 | 8 | http://www.projectpluto.com/source.htm#astrocalc 9 | 10 | On Linux, run `make` to build the library and various test executables. 11 | (You can also do this with MinGW under Windows.) In Linux, you 12 | can then run `make install` to put libraries in `/usr/local/lib` and some 13 | include files in `/usr/local/include`. (You will probably have to make that 14 | `sudo make install`.) For BSD, and probably OS/X, run `gmake CLANG=Y` 15 | (GNU make, with the clang compiler), then `sudo gmake install`. 16 | 17 | On Windows, run `nmake -f lunar.mak` with MSVC++. Optionally, add 18 | `BITS_32=Y` for 32-bit code. 19 | -------------------------------------------------------------------------------- /lun_tran.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | double get_lunar_transit_time( const int year, const int month, 19 | const int day, const double latitude, const double longitude, 20 | const int time_zone, const int dst, const int real_transit); 21 | void format_hh_mm( char *buff, const double time); 22 | int get_zip_code_data( const int zip_code, double *latitude, 23 | double *longitude, int *time_zone, int *use_dst, 24 | char *place_name); 25 | -------------------------------------------------------------------------------- /.github/workflows/github_actions_build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push, pull_request] 4 | 5 | jobs: 6 | buildUbuntu: 7 | runs-on: ubuntu-latest 8 | 9 | steps: 10 | - uses: actions/checkout@master 11 | - name: make 12 | run: make ERRORS=Y 13 | 14 | buildOSX: 15 | runs-on: macOS-latest 16 | 17 | steps: 18 | - uses: actions/checkout@master 19 | - name: make 20 | run: make CLANG=Y ERRORS=Y 21 | 22 | buildWindowsX64: 23 | runs-on: windows-latest 24 | 25 | steps: 26 | - uses: actions/checkout@master 27 | - name: make 28 | run: | 29 | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x64 30 | nmake -f lunar.mak 31 | shell: cmd 32 | - name: Archive .EXEs 33 | uses: actions/upload-artifact@v4 34 | with: 35 | name: exes 36 | path: '*.exe' 37 | 38 | buildWindowsX86: 39 | runs-on: windows-latest 40 | 41 | steps: 42 | - uses: actions/checkout@master 43 | - name: make 44 | run: | 45 | call "C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat" x86 46 | nmake -f lunar.mak BITS_32=Y 47 | shell: cmd 48 | -------------------------------------------------------------------------------- /gust86.h: -------------------------------------------------------------------------------- 1 | /* gust86.h: header file for Uranian satellite computations 2 | Copyright (C) 2010, Project Pluto 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | 02110-1301, USA. */ 18 | 19 | /* Output state vector is in AU and AU/second */ 20 | 21 | #ifndef __stdcall 22 | #define __stdcall 23 | #endif 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | void __stdcall gust86_posn( const double jde, const int isat, double *r ); 29 | #ifdef __cplusplus 30 | } 31 | #endif 32 | 33 | #define GUST86_ARIEL 0 34 | #define GUST86_UMBRIEL 1 35 | #define GUST86_TITANIA 2 36 | #define GUST86_OBERON 3 37 | #define GUST86_MIRANDA 4 38 | -------------------------------------------------------------------------------- /mjd_defs.h: -------------------------------------------------------------------------------- 1 | #ifndef MJD_DEFS_H 2 | #define MJD_DEFS_H 3 | 4 | /* These macros determine the MJD of the start of a month in the given 5 | (Gregorian) 'YEAR' at compile time. Separate macros are needed for 6 | positive and non-negative years. 7 | 8 | February 1 will always be 31 days after January 1. March 1 through 9 | December 1 will always be a fixed number of days before January 1 of 10 | the following year. */ 11 | 12 | #define JAN_1_POS( YEAR) ((YEAR) * 365L + ((YEAR) - 1) / 4L - ((YEAR) - 1) / 100L \ 13 | + ((YEAR) - 1) / 400L - 678940L) 14 | #define JAN_1_NEG( YEAR) ((YEAR) * 365L + (YEAR) / 4L - (YEAR) / 100L \ 15 | + (YEAR) / 400L - 678940L - 1L) 16 | #define JAN_1( YEAR) ((YEAR) > 0 ? JAN_1_POS( YEAR) : JAN_1_NEG( YEAR)) 17 | 18 | #define FEB_1( YEAR) (JAN_1( YEAR) + 31) 19 | #define DEC_1( YEAR) (JAN_1( (YEAR)+1) - 31) 20 | #define NOV_1( YEAR) (DEC_1( YEAR) - 30) 21 | #define OCT_1( YEAR) (NOV_1( YEAR) - 31) 22 | #define SEP_1( YEAR) (OCT_1( YEAR) - 30) 23 | #define AUG_1( YEAR) (SEP_1( YEAR) - 31) 24 | #define JUL_1( YEAR) (AUG_1( YEAR) - 31) 25 | #define JUN_1( YEAR) (JUL_1( YEAR) - 30) 26 | #define MAY_1( YEAR) (JUN_1( YEAR) - 31) 27 | #define APR_1( YEAR) (MAY_1( YEAR) - 30) 28 | #define MAR_1( YEAR) (APR_1( YEAR) - 31) 29 | 30 | #endif /* #ifdef MJD_DEFS_H */ 31 | -------------------------------------------------------------------------------- /showelem.h: -------------------------------------------------------------------------------- 1 | /* showelem.h: header file for 8-line element display functions 2 | Copyright (C) 2010, Project Pluto 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | 02110-1301, USA. */ 18 | 19 | #define SHOWELEM_PRECISION_MASK 0x0f 20 | #define SHOWELEM_PERIH_TIME_MASK 0x10 21 | #define SHOWELEM_OMIT_PQ_MASK 0x20 22 | #define SHOWELEM_COMET_MAGS_NUCLEAR 0x40 23 | 24 | /* REMEMBER: set 'central_obj', 'epoch', 'abs_mag', 'slope_param' fields */ 25 | 26 | #ifdef __cplusplus 27 | extern "C" { 28 | #endif /* #ifdef __cplusplus */ 29 | 30 | int DLL_FUNC elements_in_mpc_format( char *obuff, const size_t obuff_size, 31 | const ELEMENTS *elem, const char *obj_id, 32 | const int is_cometary, const int format); 33 | #ifdef __cplusplus 34 | } 35 | #endif /* #ifdef __cplusplus */ 36 | -------------------------------------------------------------------------------- /riseset3.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #define PLANET_DATA struct planet_data 19 | 20 | PLANET_DATA 21 | { 22 | double ecliptic_loc[3], equatorial_loc[3], altaz_loc[3]; 23 | double r, ecliptic_lon, ecliptic_lat, jd; 24 | double hour_angle; 25 | }; 26 | 27 | int fill_planet_data( PLANET_DATA *pdata, const int planet_no, const double jd, 28 | const double observer_lat, const double observer_lon, 29 | const char *vsop_data); 30 | double look_for_rise_set( const int planet_no, 31 | const double jd0, const double jd1, 32 | const double observer_lat, const double observer_lon, 33 | const char *vsop_data, int *is_setting); 34 | char *load_file_into_memory( const char *filename, size_t *filesize); 35 | -------------------------------------------------------------------------------- /colors.h: -------------------------------------------------------------------------------- 1 | /* date.h: header file for color conversions 2 | Copyright (C) 2010, Project Pluto 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | 02110-1301, USA. */ 18 | 19 | double v_minus_i_to_b_minus_v( const double v_minus_i); /* colors.c */ 20 | double b_minus_v_to_v_minus_i( const double b_minus_v); /* colors.c */ 21 | double v_minus_i_to_v_minus_r( const double v_minus_i); /* colors.c */ 22 | double v_minus_r_to_v_minus_i( const double v_minus_r); /* colors.c */ 23 | double v_minus_r_to_b_minus_v( const double v_minus_r); /* colors.c */ 24 | double b_minus_v_to_v_minus_r( const double b_minus_v); /* colors.c */ 25 | double johnson_b_minus_v_from_tycho_b_minus_v( const double b_v_t); 26 | double johnson_v_from_tycho_b_minus_v( const double b_v_t, const double tycho_v); 27 | int tycho_to_johnson_colors( double bt_minus_vt, double *results); 28 | -------------------------------------------------------------------------------- /gaia.hdr: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 258 7 | Gaia 8 | 9 | 10 | C. Ordenovic 11 | OCA 12 | 13 | 14 | Gaia team 15 | 16 | 17 | Gaia data reduction software of the Gaia DPAC team 18 | 19 | 20 | Gaia 21 | Off-axis TMA 22 | 0.5 23 | 4Kx2K CCD in TDI mode 24 | 70 25 | 0.102 26 | 27 | 28 | Gaia data reduction software of the Gaia DPAC team 29 | Gaia data reduction software of the Gaia DPAC team 30 | 31 | 32 | P. Tanga 33 | J. Bertier 34 | A. Dell'Oro 35 | A. Cellino 36 | D. Hestroffer 37 | T. Pauwels 38 | J.-M. Petit 39 | K. Muinonen 40 | W. Thuillot 41 | F. Mignard 42 | 43 | 44 | A. Jonckheere 45 | E. Van Hemelrycke 46 | P. David 47 | L. Gallucio 48 | 49 | 50 | 51 | * 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /cgi_func.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #ifdef __cplusplus 19 | extern "C" { 20 | #endif /* #ifdef __cplusplus */ 21 | 22 | 23 | void avoid_runaway_process( const int max_time_to_run); /* cgi_func.c */ 24 | int get_urlencoded_form_data( const char **idata, /* cgi_func.c */ 25 | char *field, const size_t max_field, 26 | char *buff, const size_t max_buff); 27 | int get_multipart_form_data( const char *boundary, char *field, 28 | char *buff, char *filename, const size_t max_len); 29 | 30 | 31 | int get_cgi_data( char *field, char *data, char *filename, 32 | const size_t max_buff); 33 | int initialize_cgi_reading( void); 34 | void free_cgi_data( void); 35 | int get_load_data( void); 36 | 37 | #ifdef __cplusplus 38 | } 39 | #endif /* #ifdef __cplusplus */ 40 | -------------------------------------------------------------------------------- /test_min.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "brentmin.h" 6 | 7 | /* Code for testing 'brentmin.cpp', a modified version of Brent's 8 | single-variable minimization routine. Note that the starting 9 | values specified on the command line _must_ bracket a minimum. */ 10 | 11 | double func( const double x) 12 | { 13 | return( -x * exp( -x)); /* minimum at 1 */ 14 | // return( sin( x)); /* minima at (2n+1.5) * pi */ 15 | } 16 | 17 | int main( const int argc, const char **argv) 18 | { 19 | double x[3]; 20 | int i, is_done = 0; 21 | brent_min_t b; 22 | 23 | assert( argc >= 4); 24 | for( i = 0; i < 3; i++) 25 | x[i] = atof( argv[i + 1]); 26 | brent_min_init( &b, x[0], func( x[0]), x[1], func( x[1]), 27 | x[2], func( x[2])); 28 | if( argc == 5) 29 | b.tolerance = atof( argv[4]); 30 | while( !is_done && b.n_iterations < 30) 31 | { 32 | const double new_x = brent_min_next( &b); 33 | const double new_y = func( new_x); 34 | const char *types[5] = { "Done", "Golden", "cubic", "shrink", "quadratic" }; 35 | 36 | assert( new_x == b.next_x); 37 | assert( new_x != b.xmax); 38 | assert( new_x != b.xmin); 39 | assert( new_x < b.xmax); 40 | assert( new_x > b.xmin); 41 | is_done = brent_min_add( &b, new_y); 42 | printf( "%2d %f %f (%f to %f, range %.12f) %s; gold=%f\n", 43 | b.n_iterations, new_x, new_y, b.xmin, b.xmax, 44 | b.xmax - b.xmin, types[b.step_type], b.gold_ratio); 45 | printf( "%.15f %.15f %.15f\n", b.x[1] - b.x[0], b.x[2] - b.x[0], b.x[3] - b.x[0]); 46 | } 47 | if( b.tolerance) 48 | printf( is_done ? "Converged\n" : "FAILED TO CONVERGE TO TOLERANCE\n"); 49 | return( 0); 50 | } 51 | -------------------------------------------------------------------------------- /test_des.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mpc_func.h" 7 | 8 | /* Unit test code for packing and unpacking MPC designations. Runs 9 | through all designations in 'test_des.txt' both ways to make sure the 10 | functions in 'mpc_fmt.cpp' and 'unpack.cpp' return the expected output. */ 11 | 12 | int main( void) 13 | { 14 | FILE *ifile = fopen( "test_des.txt", "rb"); 15 | char buff[200]; 16 | size_t i; 17 | int n_errors_found = 0; 18 | int testing = 3, n_unpacked = 0, n_packed = 0; 19 | 20 | assert( ifile); 21 | while( fgets( buff, sizeof( buff), ifile)) 22 | if( *buff != '#') 23 | { 24 | char tbuff[100]; 25 | const int rval = unpack_mpc_desig( tbuff, buff); 26 | 27 | for( i = 0; buff[i] >= ' '; i++) 28 | ; 29 | buff[i] = '\0'; 30 | if( testing & 1) 31 | { 32 | if( strcmp( buff + 16, tbuff) || rval != atoi( buff + 13)) 33 | { 34 | n_errors_found++; 35 | printf( "UNPACKING MISMATCH\n'%s'\n'%s'\n", buff + 16, tbuff); 36 | } 37 | else 38 | n_unpacked++; 39 | } 40 | if( testing & 2) 41 | { 42 | create_mpc_packed_desig( tbuff, buff + 16); 43 | if( memcmp( tbuff, buff, 12)) 44 | { 45 | n_errors_found++; 46 | printf( "PACKING MISMATCH\n'%.12s'\n'%.12s'\n", tbuff, buff); 47 | } 48 | else 49 | n_packed++; 50 | } 51 | } 52 | else if( !memcmp( buff, "# Test ", 7)) 53 | testing = buff[7] - '0'; 54 | printf( "%d packed correctly; %d unpacked correctly\n", 55 | n_packed, n_unpacked); 56 | if( !n_errors_found) 57 | printf( "No errors found\n"); 58 | return( 0); 59 | } 60 | -------------------------------------------------------------------------------- /get_test.txt: -------------------------------------------------------------------------------- 1 | ; Test cases for 'get_time': 2 | format 6 (day/month/year: 0009-aug-07) 3 | se 2009 4 | 7 oct 5 | 12 29 6 | 28 11 7 | oct 1912 8 | 7 dec 1941 3:14 9 | 22 1963 nov18:19:22 10 | 081225 : 11 | 17760704 12:00 12 | 2451545 13 | 2008 n 14 | se 11 2001 15 | -3h 16 | +5d 17 | 17: 18 | :7 19 | 2008/50.25 20 | d : 21 | 3:14:15.92653 22 | -443 2 12 23 | 1997.06.05 12:30:23.3348 24 | BC 415o9 12:33 -2h 25 | 21000203 03:14 26 | 650225 16:00 27 | 3:14:15.9 28 | 11/2 : 29 | 12 3 30 | 11.25-2 31 | 3-13.4 32 | j2451545 33 | Ap : 34 | 6/18/2004 35 | :17:12.3 36 | JD 2451545. 37 | 2008-03-14T15:26:53.5 38 | mjd 51000 39 | 50 2008 3:14.159 40 | y1952.34 41 | 50.75 2008 42 | 1952.34 43 | :8.4 44 | +9.25 45 | format 806 (year/day/month: following should be 0003-may-4, jun-7) 46 | 3 4 5 47 | 7 6 48 | format 1806 (year/month/day: following should be 0001-feb-6, sep-11) 49 | 1.2.6 50 | 9 11 51 | format 6 (day/month/year: 0009-aug-07) 52 | 7 8 9 53 | format 1006 (month/day/year: 0012-oct-11) 54 | 10 11 12 55 | 15 2 2008 56 | 3 16 2009 57 | 7 4 bc11 58 | 2008.15.2 4: 59 | 2009 7 16 60 | ; If a field has a decimal point in it, it should be recognized as a day: 61 | 1941 4 3.2 62 | 5.5 10 2009 63 | 2002-6.25-8 64 | 1.3 1997 4 65 | ; Next line _should_ change between runs... 66 | now-4d 67 | ; ...but nothing else should! 68 | 10/5.4/2015 69 | 3 1917 7.75 70 | 9.125 5 71 | 2 7.25 72 | ; find time three days before new moon... 73 | nm-3d 74 | 1457 oct 3 BC 12:34 75 | ; Start from 2011 dec 13, back up four weeks, find the time of the 76 | ; nearest Third Quarter phase, then add two days: 77 | 2011 dec 13 -4w 3Q +2d 78 | ; Similar efforts: 79 | 15o1843-300d1q+16d-22.43h 80 | +60d nm 81 | 1q 3:00 82 | 4:56:07 p.m. 83 | 5 4 37 6:10 pm -2h 84 | 8/3 3:01 A.M. 85 | 14/9 12:17 pm 86 | s11 12:51am 87 | 2009-10-01T21:41:23.8 88 | format 6 (day/month/year: 0009-aug-07) 89 | 1997-03-04T03:14:16 90 | ; Added 2019 Jul 21 : 91 | unix3141592653 92 | gps20633+13h+14.2m 93 | ; Added 2024 Mar 01 : the following should cause errores to be returned 94 | z28 95 | 3Ock2021 17:00 96 | 2022 Maz 21 97 | Jan 15 z 3:17 98 | -------------------------------------------------------------------------------- /xxx2rov.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "mpc_func.h" 7 | 8 | /* This code will read a file of observations containing (XXX) observations, 9 | preceded by a line defining the lat/lon/alt as 10 | 11 | COM Long. 239 18 45 E, Lat. 33 54 11 N, Alt. 100m, Google Earth 12 | 13 | or similar; see 'mpc_func.cpp' for details. (XXX) observations following 14 | that line will be converted from (XXX) to roving observer data at (247). To 15 | be used for programs that know about (247) but don't know about the (XXX) 16 | lat/lon/alt format. (Which doesn't describe any of my programs. But it 17 | may be useful for other programs. I may make this an on-line service; 18 | paste in your COD XXX-style observations, and it'll put out COD 247 19 | roving observer observations.) Compile with 20 | 21 | gcc -Wall -Wextra -pedantic -Werror -o xxx2rov xxx2rov.c liblunar.a -lm */ 22 | 23 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923 24 | 25 | int main( const int argc, const char **argv) 26 | { 27 | FILE *ifile = fopen( argv[1], "rb"); 28 | char buff[300]; 29 | mpc_code_t cinfo; 30 | 31 | assert( argc == 2); 32 | assert( ifile); 33 | cinfo.code[0] = '\0'; 34 | while( fgets( buff, sizeof( buff), ifile)) 35 | { 36 | if( get_xxx_location_info( &cinfo, buff) == -2) 37 | { 38 | fprintf( stderr, "ERROR : malformed lat/lon/alt line\n%s\n", buff); 39 | exit( -1); 40 | } 41 | else if( !memcmp( buff, "COD XXX", 7)) 42 | memcpy( buff + 4, "247", 3); 43 | else if( strlen( buff) > 80 && buff[80] < ' ' && !memcmp( buff + 77, "XXX", 3)) 44 | { 45 | memcpy( buff + 77, "247", 3); 46 | buff[14] = 'V'; 47 | printf( "%s", buff); 48 | buff[14] = 'v'; 49 | sprintf( buff + 32, "1 %9.5f %+9.5f %4.0f", 50 | cinfo.lon * 180. / PI, cinfo.lat * 180. / PI, cinfo.alt); 51 | buff[61] = ' '; 52 | } 53 | printf( "%s", buff); 54 | } 55 | fclose( ifile); 56 | return( 0); 57 | } 58 | -------------------------------------------------------------------------------- /desigcgi.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "mpc_func.h" 8 | #ifdef __has_include 9 | #if __has_include("cgi_func.h") 10 | #include "cgi_func.h" 11 | #else 12 | #error \ 13 | 'cgi_func.h' not found. This project depends on the 'lunar'\ 14 | library. See www.github.com/Bill-Gray/lunar .\ 15 | Clone that repository, 'make' and 'make install' it. 16 | #ifdef __GNUC__ 17 | #include 18 | /* Above line suppresses cascading errors. */ 19 | #endif 20 | #endif 21 | #else 22 | #include "cgi_func.h" 23 | #endif 24 | 25 | /* Code to pack/unpack designations for 'packed.htm' (q.v) via CGI. 26 | Compiles with 27 | 28 | gcc -Wall -Wextra -pedantic -o desigcgi desigcgi.c liblunar.a -lcurl -lm */ 29 | 30 | int main( void) 31 | { 32 | char field[30], buff[100], tbuff[100]; 33 | int rval; 34 | 35 | printf( "Content-type: text/html\n\n"); 36 | printf( "
");
37 |    avoid_runaway_process( 300);
38 |    rval = initialize_cgi_reading( );
39 |    if( rval <= 0)
40 |       {
41 |       printf( "

CGI data reading failed : error %d ", rval); 42 | printf( "This isn't supposed to happen. Please report this.

\n"); 43 | return( 0); 44 | } 45 | while( !get_cgi_data( field, buff, NULL, sizeof( buff))) 46 | { 47 | if( !strcmp( field, "packed") && strlen( buff) > 3) 48 | { 49 | rval = unpack_unaligned_mpc_desig( tbuff, buff); 50 | printf( "'%s' unpacks to '%s'\n", buff, tbuff); 51 | if( rval == -1) 52 | printf( "(This does not appear to be a valid packed designation)\n"); 53 | } 54 | if( !strcmp( field, "unpacked") && strlen( buff) > 3) 55 | { 56 | rval = create_mpc_packed_desig( tbuff, buff); 57 | printf( "'%s' packs to '%s'\n", buff, tbuff); 58 | if( rval == -1) 59 | printf( "(This was not successfully packed.)\n"); 60 | } 61 | } 62 | return( 0); 63 | } 64 | -------------------------------------------------------------------------------- /pollute.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define CSI "\x1b\x5b" 5 | 6 | /* Code to extract chunks of the light pollution map at 7 | 8 | https://www.nasa.gov/feature/goddard/2017/new-night-lights-maps-open-up-possible-real-time-applications/ 9 | 10 | and output a roughly 120x120-km (40x40) pixel area as an image 11 | on an xterm, using color control codes. 12 | 13 | The 8 MByte JPG is 13500 x 6750 pixels, roughly three km to the pixel : 14 | 15 | https://www.nasa.gov/specials/blackmarble/2016/globalmaps/BlackMarble_2016_3km.jpg 16 | 17 | Run 'convert BlackMarble_2016_3km.jpg /tmp/night.pgm', and you have 18 | something this program can use. I doubt that anyone else is apt to use 19 | this code, but it's helped me to visualize the map. */ 20 | 21 | int main( const int argc, const char **argv) 22 | { 23 | const int xsize = 13500, ysize = xsize / 2; 24 | FILE *ifile = fopen( "/tmp/night.pgm", "rb"); 25 | int x0, y0; 26 | int x, y, size = (argc > 3 ? atoi( argv[3]) : 20); 27 | long header_size = 18; 28 | unsigned char buff[200]; 29 | 30 | if( !ifile) 31 | printf( "This program gets data from /tmp/night.pgm, and cannot\n" 32 | "open that file. See 'pollute.c' for details.\n"); 33 | if( argc < 3) 34 | printf( "Usage : ./pollute longitude latitude\n"); 35 | if( !ifile || argc < 3) 36 | return( -1); 37 | x0 = (int)( ( 180. + atof( argv[1])) * (double)xsize / 360.); 38 | y0 = (int)( ( 90. - atof( argv[2])) * (double)ysize / 180.); 39 | x0 %= xsize; 40 | for( y = y0 - size; y < y0 + size; y++) 41 | { 42 | long loc = header_size + (long)y * (long)xsize + (long)( x0 - size); 43 | 44 | fseek( ifile, loc, SEEK_SET); 45 | if( fread( (char *)buff, size * 2, 1, ifile)) 46 | { 47 | for( x = 0; x < size * 2; x++) 48 | if( x == size && y == y0) 49 | printf( CSI "48;2;255;128;0m "); 50 | else 51 | printf( CSI "48;2;%d;%d;%dm ", buff[x], buff[x], buff[x]); 52 | printf( CSI "49m\n"); /* reset default bkgrnd */ 53 | } 54 | } 55 | return( -1); 56 | } 57 | -------------------------------------------------------------------------------- /stringex.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGEX_H_INCLUDED 2 | #define STRINGEX_H_INCLUDED 3 | 4 | /* Some extensions to the usual string/snprintf functions. These 5 | silently truncate buffer overruns, or abort so you know you 6 | have such overruns. 7 | 8 | First, the OpenBSD strlcxx functions. See comments in 'stringex.cpp'. */ 9 | 10 | #ifdef __cplusplus 11 | extern "C" { 12 | #endif /* #ifdef __cplusplus */ 13 | 14 | 15 | #if !defined( __APPLE__) && !defined( __OpenBSD__) 16 | size_t strlcpy( char *dst, const char *src, const size_t dsize); 17 | size_t strlcat( char *dst, const char *src, const size_t dsize); 18 | #endif 19 | 20 | /* The above truncate silently. On occasion, one wants that. Most of 21 | the time, such truncation indicates a bug, and the program should 22 | abort (at least in debug builds and, arguably, always). The 23 | '_err()' variants will do so. */ 24 | 25 | size_t strlcpy_err( char *dst, const char *src, const size_t dsize); 26 | size_t strlcat_err( char *dst, const char *src, const size_t dsize); 27 | 28 | /* Frequently, 'dsize' is simply sizeof( dst). The following macros 29 | can result in slightly easier to read code in such cases. */ 30 | 31 | #define strlcat_error( a, b) strlcat_err( a, b, sizeof( a)) 32 | #define strlcpy_error( a, b) strlcpy_err( a, b, sizeof( a)) 33 | 34 | /* Older MSVC/C++ lacks snprintf(). See 'stringex.cpp' for details. */ 35 | 36 | #if defined(_MSC_VER) && _MSC_VER < 1900 37 | #define NO_BUILT_IN_SNPRINTF 38 | #endif 39 | 40 | #ifdef NO_BUILT_IN_SNPRINTF 41 | int snprintf( char *string, const size_t max_len, const char *format, ...); 42 | #endif 43 | 44 | int snprintf_append( char *string, const size_t max_len, 45 | const char *format, ...) 46 | #ifdef __GNUC__ 47 | __attribute__ (( format( printf, 3, 4))) 48 | #endif 49 | ; 50 | 51 | int snprintf_err( char *string, const size_t max_len, 52 | const char *format, ...) 53 | #ifdef __GNUC__ 54 | __attribute__ (( format( printf, 3, 4))) 55 | #endif 56 | ; 57 | 58 | #ifdef __cplusplus 59 | } 60 | #endif /* #ifdef __cplusplus */ 61 | #endif /* #ifndef STRINGEX_H_INCLUDED */ 62 | -------------------------------------------------------------------------------- /mini_dll.cpp: -------------------------------------------------------------------------------- 1 | /* mini_dll.cpp: probably obsolete code for a 16-bit DLL! 2 | I don't think use has been made of this in a decade or so. 3 | 4 | Copyright (C) 2010, Project Pluto 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 | 02110-1301, USA. */ 20 | 21 | // libentry.cpp : Defines the entry point for the DLL application. 22 | // 23 | /* Usually, the following lines come from a separate file, STDAFX.H. 24 | However, for the 'mini-DLL', STDAFX is used only in this file, 25 | and maintaining a separate include file seems superfluous. */ 26 | 27 | /* ------ STDAFX.H BEGINS HERE ------ */ 28 | // stdafx.h : include file for standard system include files, 29 | // or project specific include files that are used frequently, but 30 | // are changed infrequently 31 | // 32 | 33 | #if !defined(AFX_STDAFX_H__298970FE_2CDF_11D5_A298_000102CA0D3E__INCLUDED_) 34 | #define AFX_STDAFX_H__298970FE_2CDF_11D5_A298_000102CA0D3E__INCLUDED_ 35 | 36 | #if _MSC_VER > 1000 37 | #pragma once 38 | #endif // _MSC_VER > 1000 39 | 40 | 41 | // Insert your headers here 42 | #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers 43 | 44 | #include 45 | 46 | // TODO: reference additional headers your program requires here 47 | 48 | //{{AFX_INSERT_LOCATION}} 49 | // Microsoft Visual C++ will insert additional declarations immediately before the previous line. 50 | 51 | #endif // !defined(AFX_STDAFX_H__298970FE_2CDF_11D5_A298_000102CA0D3E__INCLUDED_) 52 | /* ------ STDAFX.H ENDS HERE ------ */ 53 | 54 | BOOL APIENTRY DllMain( HANDLE hModule, 55 | DWORD ul_reason_for_call, 56 | LPVOID lpReserved 57 | ) 58 | { 59 | return TRUE; 60 | } 61 | 62 | -------------------------------------------------------------------------------- /lun_test.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #include 19 | #include 20 | #include "lun_tran.h" 21 | 22 | int main( const int argc, const char **argv) 23 | { 24 | double lon, lat; 25 | int day, zip_code, year, month; 26 | int time_zone, use_dst; 27 | char place_name[100]; 28 | 29 | if( argc != 4) 30 | { 31 | printf( "'lun_test' requires, as command-line arguments, a year,\n"); 32 | printf( "month, and US five-digit postal code. For example,\n\n"); 33 | printf( "./luntest 2015 2 04008\n\n"); 34 | printf( "would produce a list of lunar transit times for 2015 February\n"); 35 | printf( "for the town of Bowdoinham, Maine, which has ZIP code 04008.\n\n"); 36 | return( -2); 37 | } 38 | year = atoi( argv[1]); 39 | month = atoi( argv[2]); 40 | zip_code = atoi( argv[3]); 41 | if( get_zip_code_data( zip_code, &lat, &lon, &time_zone, 42 | &use_dst, place_name)) 43 | { 44 | printf( "Couldn't get data for ZIP code %05d\n", zip_code); 45 | return( -1); 46 | } 47 | 48 | printf( "Lat %f Lon %f Time zone %d DST=%d %s\n", 49 | lat, lon, time_zone, use_dst, place_name); 50 | for( day = 1; day <= 31; day++) 51 | { 52 | const double transit_time = 53 | get_lunar_transit_time( year, month, day, 54 | lat, lon, time_zone, use_dst, 1); 55 | const double antitransit_time = 56 | get_lunar_transit_time( year, month, day, 57 | lat, lon, time_zone, use_dst, 0); 58 | char transit_buff[6], antitransit_buff[6]; 59 | 60 | format_hh_mm( transit_buff, transit_time); 61 | format_hh_mm( antitransit_buff, antitransit_time); 62 | 63 | printf( "%2d: %s %s\n", day, 64 | transit_buff, antitransit_buff); 65 | } 66 | return( 0); 67 | } 68 | -------------------------------------------------------------------------------- /mpc_hdr.htm: -------------------------------------------------------------------------------- 1 | # Header for HTML versions of the MPC observatory code list. See 2 | # 'mpc_code.cpp' for explanation. This file is read in, and any 3 | # line not starting with '#' is output. Then the actual observatory 4 | # data is written. 5 | 6 | 7 | 8 | MPC station sites 9 | 10 | 11 | 12 | 13 |

MPC observatory codes

14 | 15 |

Created %.24s UTC

16 | 17 |

18 | Click here for a G__gle Map showing all observatory codes

19 | 20 |

Click here for 21 | information about this page. 22 | 23 |

The first half of each line (MPC code, lon, lat) links to a G__gle™ 24 | map for that observatory; the rest of the line links to a Bing® map.

25 | 26 | # 'rovers' off (i.e., don't show these lines for that file) 27 |

28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 |
000 100 200 300 400 500 600 700 800
900 A00 B00 C00 D00 E00 F00 G00 H00
I00 J00 K00 L00 M00 N00 O00 P00 Q00
R00 S00 T00 U00 V00 W00 X00 Y00 Z00
75 | # 'rovers' on (i.e., always show these lines) 76 |

77 | 


--------------------------------------------------------------------------------
/get_test.cpp:
--------------------------------------------------------------------------------
 1 | /* get_test.cpp: tests/exercises the get_time_from_string( ) function
 2 | 
 3 | Copyright (C) 2010, Project Pluto
 4 | 
 5 | This program is free software; you can redistribute it and/or
 6 | modify it under the terms of the GNU General Public License
 7 | as published by the Free Software Foundation; either version 2
 8 | of the License, or (at your option) any later version.
 9 | 
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 | GNU General Public License for more details.
14 | 
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 | 02110-1301, USA.    */
19 | 
20 | #include 
21 | #include 
22 | #include 
23 | #include 
24 | #include 
25 | #include "watdefs.h"
26 | #include "date.h"
27 | 
28 | /* Test routine for get_time_from_string().  This function is supposed
29 | to puzzle out a huge range of bizarre inputs,  such as "March 4" (fourth
30 | day of March) vs. "4 Mar" and so on.  'get_test.txt' contains some example
31 | inputs;  'get_test' reads those inputs,  prints out the resulting times,
32 | and you can then check to make sure that the approved output resulted
33 | by comparing it to 'get_out.txt'.  Exactly one line -- the one corresponding
34 | to 'now-4d' -- should differ. */
35 | 
36 | int main( int argc, char **argv)
37 | {
38 |    FILE *ifile = fopen( argc == 1 ? "get_test.txt" : argv[1], "rb");
39 | 
40 |    if( ifile)
41 |       {
42 |       char buff[80];
43 |       double jd = 0;
44 |       int i;
45 |       unsigned time_format = 0;
46 | 
47 |       setvbuf( stdout, NULL, _IONBF, 0);
48 |       while( fgets( buff, sizeof( buff), ifile))
49 |          {
50 |          for( i = 0; buff[i] >= ' '; i++)
51 |             ;
52 |          buff[i] = '\0';
53 |          if( !memcmp( buff, "format", 6))
54 |             {
55 |             sscanf( buff + 6, "%x", &time_format);
56 |             printf( "%s\n", buff);
57 |             }
58 |          else if( *buff != ';')
59 |             {
60 |             char obuff[80];
61 |             int is_ut;
62 | 
63 |             jd = get_time_from_string( jd, buff, (int)time_format, &is_ut);
64 |             full_ctime( obuff, jd, FULL_CTIME_MILLISECS | CALENDAR_JULIAN_GREGORIAN);
65 |             printf( "%s %d %s\n", obuff, is_ut, buff);
66 |             }
67 |          else
68 |             printf( "%s\n", buff);
69 |          }
70 |       fclose( ifile);
71 |       }
72 |    return( ifile ? 0 : -1);
73 | }
74 | 


--------------------------------------------------------------------------------
/prectes2.cpp:
--------------------------------------------------------------------------------
 1 | /* prectes2.cpp: compares Earth precession done in ecliptic and equatorial
 2 | systems.  See 'precess.cpp' for details as to why both methods matter
 3 | and when they ought to be used.
 4 | 
 5 | Copyright (C) 2017, Project Pluto
 6 | 
 7 | This program is free software; you can redistribute it and/or
 8 | modify it under the terms of the GNU General Public License
 9 | as published by the Free Software Foundation; either version 2
10 | of the License, or (at your option) any later version.
11 | 
12 | This program is distributed in the hope that it will be useful,
13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 | GNU General Public License for more details.
16 | 
17 | You should have received a copy of the GNU General Public License
18 | along with this program; if not, write to the Free Software
19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
20 | 02110-1301, USA.    */
21 | 
22 | #include 
23 | #include 
24 | #include 
25 | #include "watdefs.h"
26 | #include "afuncs.h"
27 | #include "date.h"
28 | #include "lunar.h"         /* for obliquity( ) prototype */
29 | 
30 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
31 | 
32 | int DLL_FUNC setup_equatorial_precession_from_j2000( double DLLPTR *matrix,
33 |                            const double year);
34 | 
35 | #include 
36 | #include 
37 | 
38 | int main( const int argc, const char **argv)
39 | {
40 |    double t1, matrix[9];
41 |    int i, pass;
42 |    const double J2000 = 2451545.;
43 | 
44 |    t1 = get_time_from_string( 0., (argc == 1 ? "now" : argv[1]),
45 |                                                 FULL_CTIME_YMD, NULL);
46 |    printf( "JD %f =", t1);
47 |    t1 = (t1 - J2000) / 365.25 + 2000.;
48 |    printf( " year %f\n", t1);
49 |    printf( "Last digits represent about 0.64 mm on earth's surface\n");
50 |    for( pass = 0; pass < 3; pass++)
51 |       {
52 |       if( !pass)
53 |          {
54 |          printf( "New,  ecliptic-based precession :\n");
55 |          setup_precession( matrix, 2000., t1);
56 |          }
57 |       else if( pass == 1)
58 |          {
59 |          printf( "Original,  rougher precession :\n");
60 |          setup_equatorial_precession_from_j2000( matrix, t1);
61 |          }
62 |       else
63 |          {
64 |          double mat2[9];
65 | 
66 |          printf( "Differences are (old - new) :\n");
67 |          setup_equatorial_precession_from_j2000( matrix, t1);
68 |          setup_precession( mat2, 2000., t1);
69 |          for( i = 0; i < 9; i++)
70 |             matrix[i] -= mat2[i];
71 |          }
72 |       for( i = 0; i < 9; i++)
73 |          printf( "%14.10f%s", matrix[i], (i % 3 == 2) ? "\n" : " ");
74 |       }
75 | }
76 | 


--------------------------------------------------------------------------------
/vislimit.h:
--------------------------------------------------------------------------------
 1 | /* vislimith: header file for visibility/sky brightness computations
 2 | Copyright (C) 2010, Project Pluto
 3 | 
 4 | This program is free software; you can redistribute it and/or
 5 | modify it under the terms of the GNU General Public License
 6 | as published by the Free Software Foundation; either version 2
 7 | of the License, or (at your option) any later version.
 8 | 
 9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 | GNU General Public License for more details.
13 | 
14 | You should have received a copy of the GNU General Public License
15 | along with this program; if not, write to the Free Software
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 | 02110-1301, USA.    */
18 | 
19 | /* Visibility is computed in five bands : U, B, V, R, I.
20 | Thus,  the k[0], k[1], ... k[4] values give the total extinction
21 | coefficients for U, B, V, R, I respectively.  */
22 | 
23 | #define BRIGHTNESS_DATA struct brightness_data
24 | 
25 | #pragma pack(4)
26 | BRIGHTNESS_DATA
27 |    {
28 |                /* constants for a given time: */
29 |    double zenith_ang_moon, zenith_ang_sun, moon_elongation;
30 |    double ht_above_sea_in_meters, latitude;
31 |    double temperature_in_c, relative_humidity;
32 |    double year, month;
33 |                /* values varying across the sky: */
34 |    double zenith_angle;
35 |    double dist_moon, dist_sun;         /* angular,  not real linear */
36 |    int mask;   /* indicates which of the 5 photometric bands we want */
37 |                /* Items computed in set_brightness_params: */
38 |    double air_mass_sun, air_mass_moon, lunar_mag;
39 |    double k[5], c3[5], c4[5];
40 |    double ka[5];        /* Aerosol extinction coeffs in UBVRI */
41 |    double kr[5];        /* Rayleigh extinction coeffs */
42 |    double ko[5];        /* Ozone extinction */
43 |    double kw[5];        /* Water extinction */
44 |    double year_term;    /* variation due to 11-year solar cycle */
45 |                /* Items computed in compute_limiting_mag: */
46 |    double air_mass_gas, air_mass_aerosol, air_mass_ozone;
47 |    double extinction[5];
48 |                /* Internal parameters from compute_sky_brightness: */
49 |    double air_mass;
50 |    double brightness[5];
51 |    };
52 | #pragma pack( )
53 | 
54 | #ifdef _WIN32
55 | #define DLL_FUNC __stdcall
56 | #else
57 | #define DLL_FUNC
58 | #endif
59 | 
60 | #ifdef __cplusplus
61 | extern "C" {
62 | #endif
63 | 
64 | int DLL_FUNC set_brightness_params( BRIGHTNESS_DATA *b);
65 | int DLL_FUNC compute_sky_brightness( BRIGHTNESS_DATA *b);
66 | double DLL_FUNC compute_limiting_mag( BRIGHTNESS_DATA *b);
67 | int DLL_FUNC compute_extinction( BRIGHTNESS_DATA *b);
68 | 
69 | #ifdef __cplusplus
70 | }
71 | #endif
72 | 


--------------------------------------------------------------------------------
/ll_test.c:
--------------------------------------------------------------------------------
 1 | #include 
 2 | #include 
 3 | #include 
 4 | #include 
 5 | #include "watdefs.h"
 6 | #include "mpc_func.h"
 7 | 
 8 | /* Run as,  e.g.,  './ll_test "n23 45 12.3, w31.4159, 200ft"' to test out
 9 | the lat/lon parsing code in 'mpc_code.cpp.'  Compile with
10 | 
11 | gcc -Wall -Wextra -pedantic -o ll_test ll_test.c liblunar.a -lm      */
12 | 
13 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
14 | 
15 | static void run_tests( void)
16 | {
17 |    FILE *ifile = fopen( "ll_test.txt", "rb");
18 |    char buff[200];
19 |    int n_tests = 0;
20 | 
21 |    assert( ifile);
22 |    while( fgets( buff, sizeof( buff), ifile))
23 |       if( *buff != '#')
24 |          {
25 |          double lat, lon, alt;
26 |          int expected_rval, rval;
27 |          mpc_code_t cinfo;
28 | 
29 |          if( !memcmp( buff + 32, "COM Long.", 9))
30 |             rval = get_xxx_location_info( &cinfo, buff + 32);
31 |          else
32 |             rval = get_lat_lon_info( &cinfo, buff + 32);
33 |          assert( 4 == sscanf( buff, "%d %lf %lf %lf", &expected_rval, &lon, &lat, &alt));
34 |          if( rval != expected_rval)
35 |             fprintf( stderr, "Error with string '%s'; got %d\n", buff + 32, rval);
36 |          else if( !rval)         /* should have succeeded */
37 |             {
38 |             const double lat1 = cinfo.lat * 180. / PI;
39 |             const double lon1 = cinfo.lon * 180. / PI;
40 |             const double rounding_tolerance = 1e-8;
41 | 
42 |             if( alt - cinfo.alt < -rounding_tolerance
43 |                         || alt - cinfo.alt > rounding_tolerance
44 |                         || lat - lat1 < -rounding_tolerance
45 |                         || lat - lat1 > rounding_tolerance
46 |                         || lon - lon1 < -rounding_tolerance
47 |                         || lon - lon1 > rounding_tolerance)
48 |                fprintf( stderr, "Error with string '%s'; got %.8lf %.8lf %.8lf\n",
49 |                        buff + 32,
50 |                        cinfo.lat * 180. / PI, cinfo.lon * 180. / PI, cinfo.alt);
51 |             }
52 |          n_tests++;
53 |          }
54 |    printf( "%d tests run\n", n_tests);
55 |    fclose( ifile);
56 | }
57 | 
58 | int main( const int argc, const char **argv)
59 | {
60 |    if( argc > 1)
61 |       {
62 |       mpc_code_t cinfo;
63 |       int rval;
64 | 
65 |       if( !memcmp( argv[1], "COM Long.", 9))
66 |          rval = get_xxx_location_info( &cinfo, argv[1]);
67 |       else
68 |          rval = get_lat_lon_info( &cinfo, argv[1]);
69 | 
70 |       if( rval)
71 |          printf( "Failed %d\n", rval);
72 |       else
73 |          {
74 |          printf( "Lat %lf\nLon %lf\n", cinfo.lat * 180. / PI, cinfo.lon * 180. / PI);
75 |          printf( "Alt %lf metres\n", cinfo.alt);
76 |          }
77 |       }
78 |    else
79 |       run_tests( );
80 |    return( 0);
81 | }
82 | 


--------------------------------------------------------------------------------
/utc_test.cpp:
--------------------------------------------------------------------------------
 1 | /* Copyright (C) 2018, Project Pluto
 2 | 
 3 | This program is free software; you can redistribute it and/or
 4 | modify it under the terms of the GNU General Public License
 5 | as published by the Free Software Foundation; either version 2
 6 | of the License, or (at your option) any later version.
 7 | 
 8 | This program is distributed in the hope that it will be useful,
 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | 
13 | You should have received a copy of the GNU General Public License
14 | along with this program; if not, write to the Free Software
15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 | 02110-1301, USA. */
17 | 
18 | #include 
19 | #include 
20 | #include "watdefs.h"
21 | #include "afuncs.h"
22 | #include "mjd_defs.h"
23 | 
24 | int main( const int argc, const char **argv)
25 | {
26 |    int year = 1970, end_year = 2040, i;
27 |    unsigned count = 0;
28 | 
29 |    for( i = 1; i < argc; i++)
30 |       if( argv[i][0] == '-')
31 |          switch( argv[i][1])
32 |             {
33 |             case 'p':
34 |                mjd_end_of_predictive_leap_seconds = atoi( argv[i] + 2);
35 |                printf( "No predicted leap seconds after MJD %d\n",
36 |                            mjd_end_of_predictive_leap_seconds);
37 |                break;
38 |             default:
39 |                printf( "Option '%s' ignored\n", argv[i]);
40 |                break;
41 |             }
42 |       else
43 |          sscanf( argv[i], "%d,%d", &year, &end_year);
44 |    printf( "Leap seconds for years %d to %d\n", year, end_year);
45 |    printf( "(See the 'official' list at https://hpiers.obspm.fr/iers/bul/bulc/UTC-TAI.history)\n");
46 |    printf( "Future leap seconds are predicted using the method described\n");
47 |    printf( "in 'delta_t.cpp',  and come without warranty of any kind.\n");
48 |    for( ; year <= end_year; year++)
49 |       if( year >= 1972)
50 |          for( unsigned pass = 0; pass < 2; pass++)
51 |             {
52 |             const double tai_minus_tdt = -32.184;      /* by definition */
53 |             const double jd = 2400000.5 + (pass ? JUL_1( year) : JAN_1( year));
54 |             const double tai_minus_utc_before =
55 |                        tai_minus_tdt + td_minus_utc( jd - .0001);
56 |             const double tai_minus_utc_after =
57 |                        tai_minus_tdt + td_minus_utc( jd + .0001);
58 | 
59 |             if( tai_minus_utc_before != tai_minus_utc_after)
60 |                {
61 |                printf( "%d %s : %.3f%s", year, (pass ? "Jul" : "Jan"),
62 |                               tai_minus_utc_after,
63 |                               (count % 3 == 2 ? "\n" : "   "));
64 |                count++;
65 |                }
66 |             }
67 |    printf( "\n");
68 |    return( 0);
69 | }
70 | 


--------------------------------------------------------------------------------
/obliquit.cpp:
--------------------------------------------------------------------------------
 1 | /* obliquit.cpp: function to compute earth's obliquity
 2 | 
 3 | Copyright (C) 2010, Project Pluto
 4 | 
 5 | This program is free software; you can redistribute it and/or
 6 | modify it under the terms of the GNU General Public License
 7 | as published by the Free Software Foundation; either version 2
 8 | of the License, or (at your option) any later version.
 9 | 
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 | GNU General Public License for more details.
14 | 
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 | 02110-1301, USA.    */
19 | 
20 | /* 21 Sep 2011:  improved caching of previous values.  Also,  the
21 | formula diverges badly outside +/- 10 millenia,  so I "capped"
22 | results at that point.  The test code now compares to the IAU
23 | obliquity formula,  and shows values linearly interpolated from
24 | integrated values from a file due to Laskar.   */
25 | 
26 | #include "watdefs.h"
27 | #include "lunar.h"
28 | 
29 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
30 | #define CVT (PI / 180.)
31 | #define ARCSECONDS_TO_RADIANS (CVT / 3600.)
32 | 
33 |           /* obliquity formula comes from p 135, Meeus,  Astro Algor */
34 |           /* input is time in julian centuries from 2000. */
35 |           /* rval is mean obliq. (epsilon sub 0) in radians */
36 |           /* Valid range is the years -8000 to +12000 (t = -100 to 100) */
37 | 
38 | double DLL_FUNC mean_obliquity( const double t_cen)
39 | {
40 |    double u, u0;
41 |    unsigned i;
42 |    const double obliquit_minus_100_cen = 24.232841111 * PI / 180.;
43 |    const double obliquit_plus_100_cen =  22.611485556 * PI / 180.;
44 |    static double j2000_obliquit = 23. * 3600. + 26. * 60. + 21.448;
45 |    static double t0 = 30000., rval;
46 |    static long coeffs[10] = { -468093L, -155L, 199925L, -5138L,
47 |             -24967L, -3905L, 712L, 2787L, 579L, 245L };
48 | 
49 |    if( t_cen == 0.)      /* common J2000 case;  don't do any math */
50 |       return( j2000_obliquit * ARCSECONDS_TO_RADIANS);
51 | #ifndef CLIP_OBLIQUITY
52 |    else if( t_cen > 100.)      /* Diverges outside +/- 10 millennia,  */
53 |       return( obliquit_plus_100_cen);
54 |    else if( t_cen < -100.)  /* so we might as well clip to that  */
55 |       return( obliquit_minus_100_cen);
56 | #endif
57 | 
58 |    if( t0 == t_cen)    /* return previous answer */
59 |       return( rval);
60 | 
61 |    rval = j2000_obliquit;
62 |    t0 = t_cen;
63 |    u = u0 = t_cen / 100.;     /* u is in julian 10000's of years */
64 |    for( i = 0; i < 10; i++, u *= u0)
65 |       rval += u * (double)coeffs[i] / 100.;
66 | 
67 |    rval *= ARCSECONDS_TO_RADIANS;
68 |    return( rval);
69 | }
70 | 


--------------------------------------------------------------------------------
/ssattest.cpp:
--------------------------------------------------------------------------------
 1 | /* Copyright (C) 2018, Project Pluto
 2 | 
 3 | This program is free software; you can redistribute it and/or
 4 | modify it under the terms of the GNU General Public License
 5 | as published by the Free Software Foundation; either version 2
 6 | of the License, or (at your option) any later version.
 7 | 
 8 | This program is distributed in the hope that it will be useful,
 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | 
13 | You should have received a copy of the GNU General Public License
14 | along with this program; if not, write to the Free Software
15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 | 02110-1301, USA. */
17 | 
18 | #include 
19 | #include 
20 | #include 
21 | #include "watdefs.h"
22 | #include "lunar.h"
23 | #include "date.h"
24 | #include "afuncs.h"
25 | 
26 | #define JUPITER_R (71492. / AU_IN_KM)
27 | #define J2000     2451545.
28 | 
29 | int main( const int argc, const char **argv)
30 | {
31 |    int i;
32 |    double loc[12], jd, precess_matrix[9], t_years, obliquity;
33 |    char buff[80];
34 | 
35 |    if( argc != 2)
36 |       {
37 |       printf( "'ssattest' takes a JD on the command line,  and outputs\n"
38 |               "J2000 ecliptic Cartesian coordinates for the eight main\n"
39 |               "satellites of Saturn and the four Galileans.\n");
40 |       return( -1);
41 |       }
42 |    jd = get_time_from_string( 0., argv[1], 0, NULL);
43 |    full_ctime( buff, jd, FULL_CTIME_YMD);
44 |    t_years = (jd - J2000) / 365.25;
45 |    obliquity = mean_obliquity( t_years / 100.);
46 |    printf( "Coordinates are in AU,  ecliptic J2000\n");
47 |    printf( "Date: %.5f = %s\n", jd, buff);
48 |    for( i = 0; i < 8; i++)
49 |       {
50 |       const char *names[8] = {  "Mimas", "Enceladus", "Tethys",
51 |                   "Dione", "Rhea", "Titan", "Hyperion", "Iapetus" };
52 | 
53 |       calc_ssat_loc( jd, loc, i, 0L);
54 |       printf( "%d: %10.7f %10.7f %10.7f %s\n", i, loc[0], loc[1], loc[2],
55 |                      names[i]);
56 |       }
57 |    printf( "\n");
58 |    setup_precession( precess_matrix, 2000. + t_years, 2000.);
59 |    calc_jsat_loc( jd, loc, 15, 0L);
60 |    for( i = 0; i < 4; i++)
61 |       {
62 |       const char *names[4] = {  "Io", "Europa", "Ganymede", "Callisto" };
63 |       double tloc[3];
64 | 
65 |                         /* turn ecliptic of date to equatorial: */
66 |       rotate_vector( loc + i * 3, obliquity, 0);
67 |                         /* then to equatorial J2000: */
68 |       precess_vector( precess_matrix, loc + i * 3, tloc);
69 |                         /* then to ecliptic J2000: */
70 |       equatorial_to_ecliptic( tloc);
71 |       printf( "%d: %10.7f %10.7f %10.7f %s\n", i, tloc[0] * JUPITER_R,
72 |                tloc[1] * JUPITER_R, tloc[2] * JUPITER_R, names[i]);
73 |       }
74 |    return( 0);
75 | }
76 | 


--------------------------------------------------------------------------------
/oblitest.cpp:
--------------------------------------------------------------------------------
 1 | /* oblitest.cpp: tests various obliquity formulae
 2 | 
 3 | Copyright (C) 2011, Project Pluto
 4 | 
 5 | This program is free software; you can redistribute it and/or
 6 | modify it under the terms of the GNU General Public License
 7 | as published by the Free Software Foundation; either version 2
 8 | of the License, or (at your option) any later version.
 9 | 
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 | GNU General Public License for more details.
14 | 
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 | 02110-1301, USA.    */
19 | 
20 | #include 
21 | #include 
22 | #include "watdefs.h"
23 | #include "lunar.h"
24 | 
25 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
26 | 
27 | /* By default,  this program shows the obliquity from years 0 to 4000 at
28 | 200-year steps,  using a variety of obliquity formulae.  Command-line
29 | arguments can change the range/step.      */
30 | 
31 | double iau_obliquity( const double t_cen);
32 | double file_obliquity( const double t_cen);
33 | double spline_obliquity( const double t_cen);
34 | 
35 | int main( const int argc, const char **argv)
36 | {
37 |    double t0 = (argc > 1 ? atof( argv[1]) : 0.);
38 |    const double dt = (argc > 2 ? atof( argv[2]) : 200.);
39 |    unsigned n_steps = (argc > 3 ? (unsigned)atoi( argv[3]) : 21);
40 |    const char *header_trailer =
41 |    "    year  :    Laskar      cubic         file      spline  dSpline   dCubic\n";
42 | 
43 |    printf( "%s", header_trailer);
44 |    while( n_steps--)
45 |       {
46 |       const double t_cen = (t0 - 2000.) / 100.;
47 |       const double laskar_obliquity = mean_obliquity( t_cen);
48 |       const double iau_value        = iau_obliquity( t_cen);
49 |       const double file_value       = file_obliquity( t_cen);
50 |       const double spline_value     = spline_obliquity( t_cen);
51 | 
52 |       printf( "%10.2f: %.8f %.8f %.8f %.8f %.3f %.3f\n", t0,
53 |                laskar_obliquity * 180. / PI,
54 |                iau_value        * 180. / PI,
55 |                file_value       * 180. / PI,
56 |                spline_value     * 180. / PI,
57 |                (laskar_obliquity - spline_value) * 3600. * 180. / PI,
58 |                (laskar_obliquity - iau_value) * 3600. * 180. / PI);
59 |       t0 += dt;
60 |       }
61 |    printf( "%s", header_trailer);
62 |    if( file_obliquity( 1.) == 0.)
63 |       {
64 |       printf( "'File' obliquity is interpolated from values found in files at\n\n");
65 |       printf( "http://cdsarc.u-strasbg.fr/viz-bin/Cat?VI/63\n\n");
66 |       printf( "Get those files,  and the 'file' obliquities will be computed and shown.\n");
67 |       }
68 |    return( 0);
69 | }
70 | 


--------------------------------------------------------------------------------
/cosptest.cpp:
--------------------------------------------------------------------------------
 1 | /* Copyright (C) 2018, Project Pluto
 2 | 
 3 | This program is free software; you can redistribute it and/or
 4 | modify it under the terms of the GNU General Public License
 5 | as published by the Free Software Foundation; either version 2
 6 | of the License, or (at your option) any later version.
 7 | 
 8 | This program is distributed in the hope that it will be useful,
 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of
10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 | GNU General Public License for more details.
12 | 
13 | You should have received a copy of the GNU General Public License
14 | along with this program; if not, write to the Free Software
15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
16 | 02110-1301, USA. */
17 | 
18 | #include 
19 | #include 
20 | #include 
21 | #include 
22 | #include 
23 | #include "watdefs.h"
24 | #include "afuncs.h"
25 | #include "lunar.h"
26 | 
27 |       /* Unit test code for COSPAR functions.  I've used this     */
28 |       /* after making changes to 'cospar.txt' or 'cospar.cpp'     */
29 |       /* just to verify that only the things that were _supposed_ */
30 |       /* to change,  actually changed.                            */
31 | 
32 | int main( const int argc, const char **argv)
33 | {
34 |    double matrix[9], prev_matrix[9];
35 |    int i, j, system_number, rval;
36 |    clock_t t0 = clock( );
37 | 
38 |    if( argc == 2)          /* you can specify the COSPAR file name from */
39 |       load_cospar_file( argv[1]);         /* the command line */
40 |    setvbuf( stdout, NULL, _IONBF, 0);
41 |    for( i = 0; i < 14; i++)
42 |       {
43 |       const double rate = planet_rotation_rate( i, 0);
44 | 
45 |       printf( "%d: %f deg/day; rotation period %f days\n", i, rate, 360. / rate);
46 |       }
47 |    for( i = 0; i < 9; i++)
48 |       prev_matrix[i] = 0.;
49 |    for( i = -5; i < 2000; i++)
50 |       {
51 |       for( system_number = 0; system_number < 4; system_number++)
52 |          {
53 |          rval = calc_planet_orientation( i, system_number,
54 |                         2451000. + (double)i * 1000., matrix);
55 |          if( rval && rval != -1)
56 |             printf( "rval %d\n", rval);
57 |          else if( !rval)
58 |             if( memcmp( matrix, prev_matrix, 9 * sizeof( double)))
59 |                {
60 |                double radii[3];
61 | 
62 |                printf( "Planet %d, system %d\n", i, system_number);
63 |                planet_radii( i, radii);
64 |                printf( "  Radii %.2f %.2f %.2f km\n",
65 |                              radii[0], radii[1], radii[2]);
66 |                for( j = 0; j < 9; j += 3)
67 |                   printf( "%11.8f %11.8f %11.8f\n",
68 |                              matrix[j], matrix[j + 1], matrix[j + 2]);
69 |                for( j = 0; j < 9; j++)
70 |                   prev_matrix[j] = matrix[j];
71 |                }
72 |          }
73 |       }
74 |    printf( "Total time: %f\n",
75 |             (double)( clock() - t0) / (double)CLOCKS_PER_SEC);
76 |    return( 0);
77 | }
78 | 


--------------------------------------------------------------------------------
/them_cat.c:
--------------------------------------------------------------------------------
 1 | /* See 'themis.cpp'.  The ephems for the Themis satellites cover about 18
 2 | days each.  My plan is to set up a cron job to run once a week or so,
 3 | downloading THEMIS ephems,  running through 'themis' to get those ephems
 4 | in the form used by 'eph2tle',  then using 'eph2tle' to generate 18 TLEs.
 5 | 
 6 |    Then we run this little program to enable TLEs to accumulate,  for
 7 | historical purposes.  Run as
 8 | 
 9 | ./them_cat old_file.tle new_file.tle
10 | 
11 |    it will generate a new "temporary" TLE that contains data from 'old_file'
12 | right up to the point where 'new_file' starts.  Then we finish off with the
13 | 'new_file' data.  If this all runs correctly,  we move the "temporary" file
14 | over to replace the old file.       */
15 | 
16 | #include 
17 | #include 
18 | #include 
19 | #include 
20 | #ifndef _WIN32
21 |    #include 
22 | #endif
23 | #include 
24 | #include 
25 | #include "stringex.h"
26 | 
27 | static FILE *err_fopen( const char *filename, const char *permits)
28 | {
29 |    FILE *rval = fopen( filename, permits);
30 | 
31 |    if( !rval)
32 |       {
33 |       fprintf( stderr, "'%s' not opened ", filename);
34 |       perror( NULL);
35 |       exit( -1);
36 |       }
37 |    return( rval);
38 | }
39 | 
40 | int main( const int argc, const char **argv)
41 | {
42 |    FILE *old_file = err_fopen( argv[1], "rb");
43 |    FILE *new_file = err_fopen( argv[2], "rb");
44 |    FILE *temp_file = err_fopen( "ickywax.ugh", "wb");
45 |    double jd0_new, end_jd_new;
46 |    char buff[200], new_end[200];
47 |    const time_t t0 = time( NULL);
48 |    int i;
49 |    bool found_end = false;
50 | 
51 |    assert( argc >= 3);
52 |    while( fgets( buff, sizeof( buff), new_file)
53 |                   && memcmp( buff, "# Ephem range:", 14))
54 |       ;
55 |    sscanf( buff + 15, "%lf %lf", &jd0_new, &end_jd_new);
56 |    for( i = 0; i < 3; i++)       /* skip lines */
57 |       if( !fgets( buff, sizeof( buff), new_file))
58 |          perror( "Error reading 'new' file");
59 |    strlcpy_error( new_end, buff);
60 | 
61 |    while( !found_end && fgets( buff, sizeof( buff), old_file))
62 |       {
63 |       if( !memcmp( buff, "# Ephem range:", 14))
64 |          snprintf_err( buff + 28, sizeof( buff) - 28, "%f %f\n", end_jd_new, 1.);
65 |       if( !memcmp( buff, "# Ephemeris end:", 16))
66 |          strlcpy_error( buff, new_end);
67 |       if( !memcmp( buff, "# Last updated with", 19))
68 |          strlcpy_err( buff + 42, asctime( gmtime( &t0)), sizeof( buff) - 42);
69 | 
70 |       fputs( buff,  temp_file);
71 |       if( !memcmp( buff, "# MJD ", 6) && atof( buff + 6) == jd0_new - 1.)
72 |          found_end = true;
73 |       }
74 |    assert( found_end);
75 |    for( i = 0; i < 3 && fgets( buff, sizeof( buff), old_file); i++)
76 |       fputs( buff, temp_file);
77 |    fclose( old_file);
78 |    while( fgets( buff, sizeof( buff), new_file))
79 |       fputs( buff, temp_file);
80 |    fclose( temp_file);
81 |    fclose( new_file);
82 | #ifdef _WIN32
83 |    _unlink( argv[1]);
84 | #else
85 |    unlink( argv[1]);
86 | #endif
87 |    rename( "ickywax.ugh", argv[1]);
88 |    return( 0);
89 | }
90 | 


--------------------------------------------------------------------------------
/comets.h:
--------------------------------------------------------------------------------
 1 | /* comets.h: header file for comet/asteroid functions
 2 | Copyright (C) 2010, Project Pluto
 3 | 
 4 | This program is free software; you can redistribute it and/or
 5 | modify it under the terms of the GNU General Public License
 6 | as published by the Free Software Foundation; either version 2
 7 | of the License, or (at your option) any later version.
 8 | 
 9 | This program is distributed in the hope that it will be useful,
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 | GNU General Public License for more details.
13 | 
14 | You should have received a copy of the GNU General Public License
15 | along with this program; if not, write to the Free Software
16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 | 02110-1301, USA.    */
18 | 
19 | #define ELEMENTS struct elements
20 | 
21 | #pragma pack(4)
22 | ELEMENTS
23 |    {
24 |    double perih_time, q, ecc, incl, arg_per, asc_node;
25 |    double epoch,  mean_anomaly;
26 |             /* derived quantities: */
27 |    double lon_per, minor_to_major;
28 |    double perih_vec[3], sideways[3];
29 |    double angular_momentum, major_axis, t0, w0;
30 |    double abs_mag, slope_param, gm;
31 |    int is_asteroid, central_obj;
32 |    };
33 | #pragma pack( )
34 | 
35 | /* Note that in the above structure,  t0 = 1/n = time to move */
36 | /* one radian in mean anomaly = orbital period / (2*pi).      */
37 | 
38 | #ifdef __cplusplus
39 | extern "C" {
40 | #endif
41 | 
42 | #include 
43 | 
44 | // void calc_vectors( ELEMENTS *elem, const double sqrt_gm);
45 | int DLL_FUNC calc_classical_elements( ELEMENTS *elem, const double *r,
46 |                              const double t, const int ref);
47 | int DLL_FUNC comet_posn_and_vel( ELEMENTS DLLPTR *elem, double t,
48 |                   double DLLPTR *loc, double DLLPTR *vel);
49 | int DLL_FUNC comet_posn( ELEMENTS DLLPTR *elem, double t, double DLLPTR *loc);       /* astfuncs.c */
50 | void DLL_FUNC derive_quantities( ELEMENTS DLLPTR *e, const double gm);
51 | int DLL_FUNC setup_elems_from_ast_file( ELEMENTS DLLPTR *class_elem,
52 |               const uint32_t DLLPTR *elem, const double t_epoch);
53 | double DLL_FUNC phase_angle_correction_to_magnitude( const double phase_angle,
54 |                                  const double slope_param);
55 | int setup_planet_elem( ELEMENTS *elem, const int planet_idx,
56 |                                              const double t_cen);
57 | int extract_sof_data( ELEMENTS *elem, const char *buff, const char *header);
58 | int extract_sof_data_ex( ELEMENTS *elem, const char *buff, const char *header,
59 |                         double *extra_info);                /* sof.cpp */
60 | double extract_yyyymmdd_to_jd( const char *buff);           /* sof.cpp */
61 | 
62 | typedef struct
63 | {
64 |    double obj1_true_anom, jd1;       /* these are set in find_moid_full */
65 |    double obj2_true_anom, jd2;       /* NOT SET YET */
66 |    double barbee_speed;              /* in AU/day */
67 | } moid_data_t;
68 | 
69 | double DLL_FUNC find_moid_full( const ELEMENTS *elem1, const ELEMENTS *elem2, moid_data_t *mdata);
70 | 
71 | #ifdef __cplusplus
72 | }
73 | #endif
74 | 


--------------------------------------------------------------------------------
/triton.cpp:
--------------------------------------------------------------------------------
 1 | /* triton.cpp: low-precision ephems for Triton
 2 | 
 3 | Copyright (C) 2010, Project Pluto
 4 | 
 5 | This program is free software; you can redistribute it and/or
 6 | modify it under the terms of the GNU General Public License
 7 | as published by the Free Software Foundation; either version 2
 8 | of the License, or (at your option) any later version.
 9 | 
10 | This program is distributed in the hope that it will be useful,
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 | GNU General Public License for more details.
14 | 
15 | You should have received a copy of the GNU General Public License
16 | along with this program; if not, write to the Free Software
17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18 | 02110-1301, USA.    */
19 | 
20 | #include 
21 | #include "watdefs.h"
22 | #include "lunar.h"
23 | #include "afuncs.h"
24 | 
25 | #define J2000  2451545.
26 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923
27 | 
28 | /* For the following,  see p 373 of the _Explanatory Supplement_ */
29 | /* Note that 'rocks.cpp' also has code for computing the position of Triton.
30 | The following is,  therefore,  essentially obsolete.   */
31 | 
32 | void DLL_FUNC calc_triton_loc( const double jd, double *vect)
33 | {
34 |    const double t_cent = (jd - J2000) / 36525.;
35 |    const double n = (359.28 + 54.308 * t_cent) * (PI / 180.);
36 |    const double t0 = 2433282.5;
37 |    const double theta = (151.401 + .57806 * (jd - t0) / 365.25) * (PI / 180.);
38 |             /* Semimajor axis is 488.49 arcseconds at one AU: */
39 |    const double semimajor = 488.49 * (PI / 180.) / 3600.;
40 |    const double longitude =
41 |                (200.913 + 61.2588532 * (jd - t0)) * (PI / 180.);
42 |    const double gamma = 158.996 * (PI / 180.);
43 | 
44 |          /* Calculate longitude and latitude on invariable plane: */
45 |    const double lon_on_ip = theta + atan2( sin( longitude) * cos( gamma),
46 |                                      cos( longitude));
47 |    const double lat_on_ip = asin( sin( longitude) * sin( gamma));
48 |          /* Vectors defining invariable plane,  expressed in B1950: */
49 |    double x_axis[3], y_axis[3], z_axis[3];
50 |          /* Vector defining Triton position in invariable plane space: */
51 |    double triton[3];
52 |          /* RA/dec of the pole: */
53 |    double ra_dec_p[2];
54 |    double matrix[9];
55 |    double vect_1950[3];
56 |    int i;
57 | 
58 |    polar3_to_cartesian( triton, lon_on_ip, lat_on_ip);
59 | 
60 |    ra_dec_p[0] = (298.72 * PI / 180.) + (2.58 * PI / 180.) * sin( n)
61 |                      - (0.04 * PI / 180.) * sin( n + n);
62 |    ra_dec_p[1] = (42.63 * PI / 180.) - (1.90 * PI / 180.) * cos( n)
63 |                      + (0.01 * PI / 180.) * cos( n + n);
64 |    setup_precession( matrix, 1950., 2000.);
65 |    precess_ra_dec( matrix, ra_dec_p, ra_dec_p, 1);
66 |    polar3_to_cartesian( x_axis, ra_dec_p[0] + PI / 2., 0.);
67 |    polar3_to_cartesian( y_axis, ra_dec_p[0] + PI, PI / 2. - ra_dec_p[1]);
68 |    polar3_to_cartesian( z_axis, ra_dec_p[0], ra_dec_p[1]);
69 | 
70 |    for( i = 0; i < 3; i++)
71 |       vect_1950[i] = semimajor * (x_axis[i] * triton[0] +
72 |                       y_axis[i] * triton[1] + z_axis[i] * triton[2]);
73 |    precess_vector( matrix, vect_1950, vect);
74 | }
75 | 
76 | 


--------------------------------------------------------------------------------
/moidtest.txt:
--------------------------------------------------------------------------------
 1 | Name        |C |Tp      .       |Te      |q         |i  .      |Om .      |om .      |e         |n_u  |n_o  |rms. |Tfirst     |Tlast      |H . |G   |Twritten.   ^
 2 |     CJ95O010    19970330.3688675 20130813 0.91971424  89.573293 282.053191 130.681474 0.99493312  3616  3616   1.6 19930427.77 20130813.32  2.8 10.0 20181022.1095
 3 |     hale1       19970330.3688675 20130813 0.91971424  89.573293 282.053191 130.681474 0.99993312  3616  3616   1.6 19930427.77 20130813.32  2.8 10.0 20181022.1095
 4 |      K16V01B    20170225.4865665 20161105 0.51790827   2.404097  43.038361 173.857333 0.31567127    44    44   0.7 20161105.45 20161108.11 28.6 0.15 20181019.7512
 5 |      K14S00E    20141006.8011685 20140921 1.02927157  20.051616 351.119492  22.439099 0.17226306    22    22   0.6 20140916.16 20140921.87 25.3 0.15 20181020.0300
 6 |      K05Q11O    20130710.0934002 20140225 1.20160773  45.190269 163.091520 231.376682 0.50943671   181   181   0.5 20050828.15 20140225.04 19.1 0.15 20181020.0317
 7 | 00588           20230503.2487172 20181010 4.44669508  10.318794 316.535808 133.418685 0.14640725  1376  1503   0.6 19720904.84 20181010.29  8.4 0.15 20181022.1083
 8 |      J99A10N    20180823.3237952 20190427 0.63865361  39.931199 314.386280 268.327414 0.56216577   172   173   0.6 19550126.40 20130304.77 18.3 0.15 20181024.0492
 9 |      K18U00L    20180920.9054030 20181020 0.96695902   0.768560 201.447506 151.726056 0.28271825    39    40   0.5 20181018.21 20181019.30 29.1 0.15 20181024.9187
10 |      K11C01Q    20110326.6909216 20110202 0.90886394   1.080878 135.382944  58.713560 0.19555169    35    35   0.9 20110204.23 20110204.75 32.0 0.15 20181024.9327
11 |      A10c9Hw    20190126.5179220 20190218 0.96433842   5.806607 141.193420 340.490896 0.52262560    37    37   0.3 20190215.53 20190218.43 26.1 0.15 20190220.6992
12 |     AK17U010    20170909.4958011 20171123 0.25558762 122.710325  24.598185 241.747571 1.20016896   175   192   0.3 20171018.47 20171123.37 22.0 0.15 20181019.7520
13 |     hale2       19970330.3688675 20130813 0.91971424  89.573293 282.053191 130.681474 1.00010312  3616  3616   1.6 19930427.77 20130813.32  2.8 10.0 20181022.1095
14 |     CK19Q040    20191207.9436140 20190910 2.03235968  43.822756 308.371745 208.531655 3.46244900   128   128   0.7 20190830.04 20190910.63 12.5 0.15 20190919.6215
15 | 
16 | MOID  AK17U010 `Oumuamua : 0.0958212
17 |                         /* (433) Eros : MOID = 0.149341 */
18 |                         /* (4179) Toutatis : MOID = 0.00609937 */
19 |                         /* (163693) Atira : MOID = 0.206823 */
20 | MOID K16V01B 2016 VB1    : 0.0012415773444360
21 | MOID K14S00E             : 0.0342838294450511
22 | MOID K05Q11O               0.3352818313812920
23 | MOID 00588                 3.47306
24 | MOID CJ95O010              0.116025
25 | MOID J99A10N               0.000128404
26 | MOID CK19Q040              1.11575        (wrt jupiter : 2.37345)
27 | 
28 |      A10ccKO    20181219.0435365 20190227 0.80541305  10.359704 336.456356  90.965887 0.24925404     8     8   0.1 20190226.44 20190226.87 25.0 0.15 20190226.9165
29 |      C09JH82    20190409.3478258 20190302 1.75132141  28.792401 105.232279  71.255700 0.30153792    14    14   0.2 20190301.32 20190301.89 17.3 0.15 20190302.0706
30 |      K18J02D    20130910.3301017 20131001 0.21342780  50.894109  54.698961 313.135832 0.88293807   115   115   0.4 20130429.53 20180701.17 18.9 0.15 20190318.7890
31 | 
32 | 


--------------------------------------------------------------------------------
/cgicheck.htm:
--------------------------------------------------------------------------------
 1 | 
 2 | 
 3 | 
 4 |     On-line asteroid identification 
 5 |    
 6 |    
 7 | 
 8 | 
 9 | 
10 | 

On-line asteroid identification

11 | 12 |

13 | Source code for this can be found on GitHub.

14 | 15 |

This is an on-line version of the astcheck 16 | program used for identifying observations with known objects. 17 | Use the form below to find asteroids that might match the position/motion 18 | of objects you've observed.

19 | 20 |

Suggested quick start: Don't panic! Copy/paste observations 21 | for one or more objects in the large text window below, or 22 | click on "Browse" to pick a file containing the astrometry. Then click 23 | the "find matching asteroids" button. That will probably be all you 24 | need.

25 | 26 |

The output will show each object, and its motion in arcseconds/hour. 27 | After that, you'll see possible matching objects, and their offsets in 28 | arcseconds and their motions in arcseconds/hour. You can set a limit for 29 | the search radius, and can tell the program whether to use the Minor 30 | Planet Center's 31 | MPCORB or the Lowell Observatory 32 | ASTORB orbit catalog. The latter offers "current ephemeris uncertainty" 33 | data. This is not perhaps as rock-solid as it ought to be, but can tell 34 | you if the predicted position from the orbital elements is very, very good, 35 | or complete rubbish.

36 | 37 |

You can also show only possible matches with unnumbered objects, useful 38 | to those who are already pretty confident that the object isn't easily identified.

39 | 40 |

If you're still not getting things to work, contact me at 41 | p‮ôç.ötulpťcéjôřp@otúl‬m 42 | (modified to baffle spammers).

43 | 44 |


45 |
47 |

48 | 49 | 50 |

Cut/paste observations in the 51 | 52 | 80-column MPC format below. Don't worry about it if some 53 | other text is copied in as well; extra text will simply be disregarded. 54 | 55 |

56 | 57 |

Or, you can upload a file containing the astrometry. 58 | 59 | 60 |
61 | Use ASTORB
62 | Use MPCORB
63 | Show current ephemeris uncertainties (ASTORB only)
64 | Show only unnumbered objects
65 | 66 |

Find matches within degrees 67 | 68 |

69 | 70 |

71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /jpl_xref.h: -------------------------------------------------------------------------------- 1 | /* The following table is going to need occasional fixes, mostly 2 | as new spacecraft are launched. Cas = Cassini, SoO = Solar Orbiter, 3 | etc. are _not_ official MPC codes; if they ever get them, that 4 | will also cause updates to be made. The list does not reflect 5 | every spacecraft listed on Horizons; it lists those that have 6 | either gotten astrometry or for which I compute TLEs. */ 7 | 8 | typedef struct 9 | { 10 | const char mpc_code[4]; 11 | int jpl_desig, norad_number; 12 | const char *intl_desig, *name; 13 | } jpl_xref_t; 14 | 15 | /* MPC code JPL# NORAD# Intl desig Common name */ 16 | static const jpl_xref_t jpl_xrefs[] = { 17 | { "Cap", -1176, 52914, "2022-070A", "CAPSTONE" }, 18 | { "Cas", -82, 25008, "1997-061A", "Cassini" }, 19 | { "Cha", -151, 25867, "1999-040B", "Chandra X-ray Observatory" }, 20 | { "Cdr", -158, 57320, "2023-098A", "Chandrayaan-3" }, 21 | { "Equ", -101, 79970, "2022-156ZZZ", "EQUULEUS" }, 22 | { "EsB", -9, 66451, "2025-260A", "EscaPADE Blue" }, 23 | { "EsG", -10, 66452, "2025-260B", "EscaPADE Gold" }, 24 | { "273", -680, 57209, "2023-092A", "Euclid" }, 25 | { "EuC", -159, 61507, "2024-182A", "Europa Clipper" }, 26 | { "339", -143, 41388, "2016-017A", "ExoMars Trace Gas Orbiter" }, 27 | { "258", -139479, 39479, "2013-074A", "Gaia" }, 28 | { "Goe", -160133, 60133, "2024-119A", "GOES-19" }, 29 | { "Ha2", -37, 40319, "2014-076A", "Hayabusa 2" }, 30 | { "Her", -91, 61449, "2024-180A", "Hera", }, 31 | { "250", -48, 20580, "1990-037B", "Hubble Space Telescope" }, 32 | { "IM1", -229, 58963, "2024-030A", "IM-1 (Odysseus)" }, 33 | { "274", -170, 50463, "2021-130A", "James Webb Space Telescope" }, 34 | { "Jui", -28, 56176, "2023-053A", "JUICE" }, 35 | { "C55", -227, 34380, "2009-011A", "Kepler" }, 36 | { "C56", -141043, 41043, "2015-070A", "LISA Pathfinder" }, 37 | { "Luc", -49, 49328, "2021-093A", "Lucy" }, 38 | { "LFL", -164, 54697, "2022-168B", "Lunar Flashlight" }, 39 | { "MRO", -74, 28788, "2005-029A", "Mars Reconnaissance Orbiter" }, 40 | { "289", -211, 99999, "2026-000ZZZ", "Nancy Grace Roman Space Telescope" }, 41 | { "C53", -139089, 39089, "2013-009D", "NEOSSat" }, 42 | { "C58", -33, 99999, "2027-000ZZZ", "NEO Surveyor" }, 43 | { "C54", -98, 28928, "2006-001A", "New Horizons" }, 44 | { "OsR", -64, 41757, "2016-055A", "OSIRIS-REx" }, 45 | { "PSP", -96, 43592, "2018-065A", "Parker Solar Probe" }, 46 | { "Prg", -244, 58751, "2024-006A", "Peregrine" }, 47 | { "338", -255, 58049, "2023-157A", "Psyche" }, 48 | { "Sli", -240, 57803, "2023-137D", "SLIM" }, 49 | { "249", -21, 23726, "1995-065A", "SOHO" }, 50 | { "SoO", -144, 45167, "2020-010A", "Solar Orbiter" }, 51 | { "288", -163183, 63183, "2025-047E", "SPHEREx" }, 52 | { "245", -79, 27871, "2003-038A", "Spitzer Space Telescope" }, 53 | { "C49", -234, 29510, "2006-047A", "STEREO-A" }, 54 | { "C50", -235, 29511, "2006-047B", "STEREO-B" }, 55 | { "C52", -128485, 28485, "2004-047A", "Swift" }, 56 | { "C57", -95, 43435, "2018-038A", "TESS" }, 57 | { "Tia", -9901491, 45935, "2020-049A", "Tianwen-1" }, 58 | { "C51", -163, 36119, "2009-071A", "WISE" }, 59 | { "C59", -148840, 48841, "2021-050B", "Yangwang 1" } }; 60 | /* MPC code JPL# NORAD# Intl desig Common name */ 61 | -------------------------------------------------------------------------------- /jpl_url.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "watdefs.h" 6 | #include "date.h" 7 | #include "jpl_xref.h" 8 | 9 | /* You can access vector (and other) ephemerides from JPL Horizons 10 | with a URL. This program generates the URL required for a particular 11 | object covering a particular year at 0.1 day intervals; the resulting 12 | ephemerides can be fed through 'jpl2mpc', then 'eph2tle' to generate 13 | TLEs for that year. The URL looks like (broken into multiple lines 14 | for clarity/explanations; this is for Gaia in 2020): 15 | 16 | https://ssd.jpl.nasa.gov/api/horizons_api?format=text 17 | &COMMAND=%27-139479%27 object -139479 = JPL ID for Gaia 18 | &OBJ_DATA=%27YES%27 give us the header/boilerplate info 19 | &TABLE_TYPE=%27V%27 V = vector ephems 20 | &START_TIME=%272020-01-01%27 starts 2020 Jan 1 21 | &START_TIME=%27JD2458849.5%27 (alternative start format) 22 | &STOP_TIME=%272021-01-01%27 ends the following year 23 | &STOP_TIME=%27JD2459215.5%27 (similarly alternative end format) 24 | &STEP_SIZE=%273660%27 3660 steps (2020 was a leap year) 25 | &VEC_TABLE=%272%27 table type 2 = positions & velocities 26 | &VEC_LABELS=%27NO%27 skip the XYZ VXVYVZ labelling 27 | 28 | Compiles with gcc -Wall -Wextra -pedantic -o jpl_url jpl_url.c liblunar.a -lm */ 29 | 30 | static void error_exit( void) 31 | { 32 | const size_t n_xrefs = sizeof( jpl_xrefs) / sizeof( jpl_xrefs[0]); 33 | size_t i; 34 | 35 | fputs( "usage : jpl_url obj_desig start_date end_date\n" 36 | " obj_desig = MPC code or YYYY-NNNA (COSPAR) designation\n" 37 | "See comments in 'jpl_url.c' for details.\n" 38 | "Supported objects:\n\n" 39 | "MPC COSPAR_desig name\n", stderr); 40 | for( i = 0; i < n_xrefs; i++) 41 | fprintf( stderr, "%s %-11s %s\n", jpl_xrefs[i].mpc_code, 42 | jpl_xrefs[i].intl_desig, 43 | jpl_xrefs[i].name); 44 | exit( -1); 45 | } 46 | 47 | int main( const int argc, const char **argv) 48 | { 49 | size_t i = 0; 50 | const size_t n_xrefs = sizeof( jpl_xrefs) / sizeof( jpl_xrefs[0]); 51 | double jd1, jd2; 52 | const double min_jd = 2447892.5; /* 1990 Jan 1 */ 53 | 54 | if( argc < 4) 55 | error_exit( ); 56 | while( i < n_xrefs && strcmp( argv[1], jpl_xrefs[i].mpc_code) 57 | && strcmp( argv[1], jpl_xrefs[i].intl_desig) 58 | && atoi( argv[1]) != jpl_xrefs[i].jpl_desig) 59 | i++; 60 | if( i == n_xrefs) 61 | { 62 | fprintf( stderr, "'%s' is not a spacecraft MPC code, YYYY-NNNA" 63 | " designation, or Horizons object number\n", argv[1]); 64 | fprintf( stderr, "Valid designations are :\n"); 65 | error_exit( ); 66 | } 67 | jd1 = get_time_from_string( 0., argv[2], 0, NULL); 68 | jd2 = get_time_from_string( jd1, argv[3], 0, NULL); 69 | if( jd1 < min_jd || jd2 < min_jd) 70 | { 71 | fprintf( stderr, "Can't go before JD %f\n", min_jd); 72 | error_exit( ); 73 | } 74 | printf( "https://ssd.jpl.nasa.gov/api/horizons.api?format=text"); 75 | printf( "&COMMAND='%d'", jpl_xrefs[i].jpl_desig); 76 | printf( "&OBJ_DATA='YES'&TABLE_TYPE='V'"); 77 | printf( "&START_TIME='JD%f'", jd1); 78 | printf( "&STOP_TIME='JD%f'", jd2); 79 | printf( "&STEP_SIZE='%d'", (int)( (jd2 - jd1) * 10. + 0.5)); 80 | printf( "&VEC_TABLE='2'&VEC_LABELS='NO'\n"); 81 | return( 0); 82 | } 83 | -------------------------------------------------------------------------------- /disttest.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include "watdefs.h" 23 | #include "afuncs.h" 24 | 25 | /* Test routine for position angle/distance code. 26 | 27 | I'm not using the library rand( ) function, because I want to be 28 | confident that the results will be the same when compiled on different 29 | systems. Following is the MMIX linear congruential pseudo-random number 30 | generator, copied from Donald Knuth. It's not a great PRNG, but it's 31 | fine for the current humble purpose. */ 32 | 33 | uint64_t pseudo_random( const uint64_t prev_value) 34 | { 35 | uint64_t a = UINT64_C( 6364136223846793005); 36 | uint64_t c = UINT64_C( 1442695040888963407); 37 | 38 | return( a * prev_value + c); 39 | } 40 | 41 | static double get_pseudorandom_double( void) 42 | { 43 | static uint64_t rval = 1; 44 | const double two_to_the_53rd_power = 9007199254740992.0; 45 | 46 | rval = pseudo_random( rval); 47 | return (int64_t)(rval >> 11) * (1.0 / two_to_the_53rd_power); 48 | } 49 | 50 | /* Should provide RA/dec values uniformly distributed over the */ 51 | /* celestial sphere. */ 52 | 53 | static void get_random_ra_dec( double *ra, double *dec) 54 | { 55 | double x, y, z, dist; 56 | 57 | do 58 | { 59 | x = get_pseudorandom_double( ) - .5; 60 | y = get_pseudorandom_double( ) - .5; 61 | z = get_pseudorandom_double( ) - .5; 62 | } 63 | while( (dist = x * x + y * y + z * z) > .125); 64 | *ra = atan2( y, x); 65 | *dec = asin( z / sqrt( dist)); 66 | } 67 | 68 | static double calc_dist_with_acos( double *p1, double *p2) 69 | { 70 | double d_ra = p1[0] - p2[0]; 71 | double cos_dist = sin( p1[1]) * sin( p2[1]) + cos( p1[1]) * cos( p2[1]) * cos( d_ra); 72 | 73 | return( acos( cos_dist)); 74 | } 75 | 76 | int main( const int argc, const char **argv) 77 | { 78 | int i; 79 | 80 | for( i = 0; i < 10000; i++) 81 | { 82 | double p1[2], p2[2], dist1, dist2; 83 | const double pi = 3.1415926535897932384626433832795028841971693993751058209749445923; 84 | 85 | get_random_ra_dec( p1, p1 + 1); 86 | get_random_ra_dec( p2, p2 + 1); 87 | if( !i && argc == 5) 88 | { 89 | p1[0] = atof( argv[1]) * pi / 180.; 90 | p1[1] = atof( argv[2]) * pi / 180.; 91 | p2[0] = atof( argv[3]) * pi / 180.; 92 | p2[1] = atof( argv[4]) * pi / 180.; 93 | } 94 | calc_dist_and_posn_ang( p1, p2, &dist1, NULL); 95 | dist2 = calc_dist_with_acos( p1, p2); 96 | printf( "%12.8lf %12.8lf %lg\n", 97 | dist1 * 180. / pi, 98 | dist2 * 180. / pi, 99 | (dist1 - dist2) * 180. / pi); 100 | } 101 | return( 0); 102 | } 103 | -------------------------------------------------------------------------------- /gust_ref.cpp: -------------------------------------------------------------------------------- 1 | /* gust_ref.cpp: function to compute Uranian satellite matrix 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | 20 | #include 21 | 22 | /* The original GUST86 code transformed Uranicentric coords to B1950. 23 | Rather than do that, then precess to J2000, I wrote the snippet below 24 | to compute the full Uranicentric-to-J2000 matrix. Also, the original 25 | code did quite a bit of math to convert alf and del -- the RA and dec 26 | of the Uranian pole in B1950 -- into a rotation matrix. If you just 27 | store the matrix as nine precomputed doubles, you save yourself 28 | some code and time and math. 29 | 30 | Spoiler alert: the resulting output is 31 | 32 | { 0.9753206898, -0.2207422915, 0.0047321138}, 33 | { 0.0619432123, 0.2529905682, -0.9654837185}, 34 | { 0.2119259083, 0.9419493686, 0.2604204221}, 35 | 36 | If you look at the gust86_posn() in gust86.c, you will see this matrix. 37 | So there is not really any reason to build this code. 38 | */ 39 | 40 | int main( const int unused_argc, const char **unused_argv) 41 | { 42 | // const double alf = 76.60666666666667 * DEGREES_TO_RADIANS; 43 | // const double del = 15.03222222222222 * DEGREES_TO_RADIANS; 44 | // The GUST86 method originally used the above 'alf' and 'del' 45 | // values to specify the rotation from the plane of Uranus' 46 | // equator to the B1950 equator. The 3x3 matrix was computed 47 | // within this code. To simplify life a little, I've set the 48 | // matrix to be a batch of 'const' values. 49 | // alf and delta aren't used here, but their sines and cosines are... 50 | const double sin_alf = .9728028367170815; 51 | const double cos_alf = .2316347143137209; 52 | const double sin_del = .2593622252488415; 53 | const double cos_del = .9657801178912150; 54 | // ...to build the following 3x3 matrix to convert from Uranicentric 55 | // coords to B1950: 56 | const double trans[3][3] = { 57 | { sin_alf, -cos_alf, 0. }, 58 | { cos_alf * sin_del, sin_alf * sin_del, -cos_del }, 59 | { cos_alf * cos_del, sin_alf * cos_del, sin_del } }; 60 | 61 | // Rotation matrix for converting from B1950.0 FK4 positions 62 | // to J2000.0 FK5 positions. 63 | 64 | double P[3][3] = 65 | { 66 | { 0.9999256782, -0.0111820611, -0.0048579477 }, 67 | { 0.0111820610, 0.9999374784, -0.0000271765 }, 68 | { 0.0048579479, -0.0000271474, 0.9999881997 } 69 | }; 70 | int i, j, k; 71 | 72 | /* Multiply trans by P and show the resulting matrix: */ 73 | for( i = 0; i < 3; i++) 74 | for( j = 0; j < 3; j++) 75 | { 76 | double elem = 0; 77 | 78 | for( k = 0; k < 3; k++) 79 | elem += trans[i][k] * P[j][k]; 80 | if( !j) 81 | printf( " { "); 82 | printf( "%13.10lf%s", elem, (j == 2) ? "},\n" : ", "); 83 | } 84 | } 85 | -------------------------------------------------------------------------------- /test_des.txt: -------------------------------------------------------------------------------- 1 | # Test input for 'test_des'. See 'test_des.cpp'. 2 | # 'Test 1' = test packing; 'Test 2' = test unpacking; 'Test 3' = test both 3 | # At present, we have one pack-only test. 'Neptune 210' packs to N210S; 4 | # but on unpacking, it becomes 'Neptune CCX'. 5 | # Test 2 6 | N210S 5 Neptune 210 7 | # And we have some unpacking-only tests. The following should 8 | # be unpacked correctly, but you lose the redundant provisional desig 9 | # data in the process. So it can't be packed to get the original input. 10 | # Test 1 11 | 0001IK17U010 3 1I 12 | 0001PI35P010 3 1P 13 | 67282J99A38M 1 (67282) = 1999 AM38 14 | # All the other tests are bidirectional : 15 | # Test 3 16 | # Packed Typ Fullname 17 | J95X00A 0 1995 XA 18 | K07Tf8A 0 2007 TA418 19 | SK03J020 4 S/2003 J 2 20 | SJ45Ux90 4 S/1945 U 599 21 | 0041P 3 41P 22 | 3141P e 3 3141P-E 23 | 3141P az 3 3141P-AZ 24 | DJ65Az9c 2 D/1965 A619-C 25 | XJ65K810 2 X/1965 K81 26 | PLS2040 0 2040 P-L 27 | T3S3141 0 3141 T-3 28 | 00433 1 (433) 29 | G4060 1 (164060) 30 | n1415 1 (491415) 31 | ~0000 1 (620000) 32 | ~000a 1 (620036) 33 | ~00A0 1 (620620) 34 | ~AZaz 1 (3140113) 35 | ~zzzz 1 (15396335) 36 | U024S 5 Uranus XXIV 37 | N924S 5 Neptune CMXXIV 38 | N089S 5 Neptune LXXXIX 39 | U410S 5 Uranus CDX 40 | 1992-044A 6 1992-044A 41 | 1963-731KHG 6 1963-731KHG 42 | WT1190F -1 WT1190F 43 | ZTF0Ep4 -1 ZTF0Ep4 44 | C12J001 -1 C12J001 45 | 9496058 -1 9496058 46 | G4060e -1 G4060e 47 | 1762B11 -1 1762B11 48 | _QC0000 0 2026 CA620 49 | _QC0aEM 0 2026 CZ6190 50 | _QCzzzz 0 2026 CL591673 51 | _AH9fZ7 0 2010 HJ92809 52 | C_3MDZ3v 2 C/2003 MX129941 53 | P_WY0Mpc 2 P/2032 YT4130 54 | # MPC optimistically states (see 55 | # https://minorplanetcenter.net/media/newsletters/MPC_Newsletter_Oct2023.pdf 56 | # ) that the extension allowing packed provisional designations past cycle 620 57 | # = 15500th object in a half-month will not be used after the end of 2035, 58 | # and that therefore the year will be designated by an uppercase letter. I am 59 | # less sanguine and am allowing lowercase letters (hence base-62) to allow the 60 | # scheme to work to the end of 2061. With any luck, I'll be dead by then. 61 | _cRAZaz 0 2038 RO101424 62 | _xMDZ3v 0 2059 MX129941 63 | # MPC provides a few examples at 64 | # https://minorplanetcenter.net/mpcops/documentation/provisional-designation-definition/#extended_packed_provid 65 | # so let's test 'em out : 66 | K23B00A 0 2023 BA 67 | K24C03Z 0 2024 CZ3 68 | K25Dz9Z 0 2025 DZ619 69 | _PD0000 0 2025 DA620 70 | _QD000N 0 2026 DY620 71 | _RD0aEM 0 2027 DZ6190 72 | _SEZZZZ 0 2028 EA339749 73 | _TFzzzz 0 2029 FL591673 74 | # ...and, sometime between my writing the above and 2025 Apr 15, MPC added 75 | # 'explicit examples of cometified [sic] object designations'. Let's test 76 | # them, too. (Note that they're actually the same examples, except with a 77 | # letter-slash prepended.) 78 | PK23B00A 2 P/2023 BA 79 | CK24C03Z 2 C/2024 CZ3 80 | AK25Dz9Z 0 A/2025 DZ619 81 | P_PD0000 2 P/2025 DA620 82 | C_QD000N 2 C/2026 DY620 83 | A_RD0aEM 0 A/2027 DZ6190 84 | C_SEZZZZ 2 C/2028 EA339749 85 | P_TFzzzz 2 P/2029 FL591673 86 | # I had cases (now fixed) of eight-character designations starting with P, C, 87 | # D, X, A, etc. which were erroneously treated as comet or satellite desigs. 88 | # These can't be re-packed (and are not really valid packed designations to 89 | # begin with), so only unpacking is tested. 90 | # Test 1 91 | Censored -1 Censored 92 | P317abo# -1 P317abo# 93 | STress17 -1 STress17 94 | -------------------------------------------------------------------------------- /get_bin.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | /* Code to read integers of various sizes and 64-bit double-precision 19 | floats from binary data buffers. See uses in 'vsopson.cpp' and 'lunar2.cpp' 20 | where data is extracted from binary files. 21 | 22 | It's assumed that the input data is in Intel (little-Endian) order. 23 | 24 | On Intel machines, you can extract such data by type-punning, 25 | even if the data isn't aligned on a word boundary. On some other 26 | machines, the data must be aligned on a word boundary and/or you 27 | may have reverse the byte order. 28 | 29 | OpenWATCOM, Microsoft C, Borland, TurboC, and Digital Mars are all 30 | Intel-only. If we're using one of those compilers, we can type-pun. 31 | gcc and clang #define __x86_64__ or __i386__ for Intel hardware. 32 | 33 | There are probably other cases where we could type-pun. But the 34 | non-punning code will work in all cases; all we lose by not punning 35 | is a very small amount of speed. If I learn of other cases where 36 | punning is possible, the conditions under which USE_TYPE_PUNNING 37 | is defined can be modified. */ 38 | 39 | #if defined(__x86_64__) || defined(__i386__) || defined(__WATCOMC__) \ 40 | || defined(_MSC_VER) || defined (__BORLANDC__) \ 41 | || defined (__TURBOC__) || defined( __DMC__) 42 | #define USE_TYPE_PUNNING 43 | #endif 44 | 45 | #if defined( __WORD_ORDER__) && (__WORD_ORDER__ == __ORDER_BIG_ENDIAN__) 46 | #define USING_BIG_ENDIAN 47 | #endif 48 | 49 | #undef USE_TYPE_PUNNING 50 | 51 | #ifdef USE_TYPE_PUNNING 52 | #define get16bits(d) (*((const uint16_t *) (d))) 53 | #define get32bits(d) (*((const uint32_t *) (d))) 54 | #define get64bits(d) (*((const uint64_t *) (d))) 55 | 56 | /* Signed integer extraction : */ 57 | #define get16sbits(d) (*((const int16_t *) (d))) 58 | #define get32sbits(d) (*((const int32_t *) (d))) 59 | #define get64sbits(d) (*((const int64_t *) (d))) 60 | #define get_double(d) (*((const double *) (d))) 61 | #else /* Can't directly read binary data */ 62 | #define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ 63 | +(uint32_t)(((const uint8_t *)(d))[0]) ) 64 | #define get32bits(d) ((((uint32_t)(((const uint8_t *)(d))[3])) << 24)\ 65 | +(((uint32_t)(((const uint8_t *)(d))[2])) << 16)\ 66 | +(((uint32_t)(((const uint8_t *)(d))[1])) << 8)\ 67 | +(uint32_t)(((const uint8_t *)(d))[0]) ) 68 | 69 | #define get16sbits(d) ((int16_t)( get16bits( d))) 70 | #define get32sbits(d) ((int32_t)( get32bits( d))) 71 | #define get64sbits(d) ((int64_t)( get64bits( d))) 72 | 73 | static inline double get_double( const void *iptr) 74 | { 75 | const char *idata = (const char *)iptr; 76 | int i; 77 | double rval; 78 | char *buff = (char *)&rval; 79 | 80 | #if defined( USING_BIG_ENDIAN) 81 | for( i = 7; i >= 0; i--) 82 | #else 83 | for( i = 0; i < 8; i++) 84 | #endif 85 | buff[i] = *idata++; 86 | return( rval); 87 | } 88 | #endif /* End of code to indirectly read binary data */ 89 | -------------------------------------------------------------------------------- /getplane.cpp: -------------------------------------------------------------------------------- 1 | /* getplane.cpp: functions for computing planetary ephems 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | 20 | #include 21 | #include 22 | #include "watdefs.h" 23 | #include "lunar.h" 24 | #include "afuncs.h" 25 | 26 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923 27 | 28 | /* The compute_planet( ) function is supposed to provide a "standardized" 29 | way to get positions for planets and the moon, in any of four systems. 30 | You give it a pointer to the VSOP data, a planet number (0=sun, 31 | 1=mercury, ... 9 = Pluto, 10 = the Moon), and a time in centuries 32 | from J2000. The returned array of fifteen doubles gives you the object 33 | position in five different systems: 34 | 35 | ovals[0, 1, 2] = lon, lat, r, heliocentric ecliptic of date; 36 | ovals[3, 4, 5] = x, y, z, heliocentric ecliptic of date; 37 | ovals[6, 7, 8] = x, y, z, heliocentric equatorial of date; 38 | ovals[9, 10, 11] = x, y, z, heliocentric equatorial, J2000.0 39 | ovals[12, 13, 14] = x, y, z, heliocentric ecliptical, J2000.0 40 | 41 | I intended to rig this up so you could keep on going to 11=Io, 12=Europa, 42 | etc. This would make all sorts of sense. But I've not done it yet. */ 43 | 44 | int DLL_FUNC compute_planet( const char FAR *vsop_data, const int planet_no, 45 | const double t_c, double DLLPTR *ovals) 46 | { 47 | double lat, lon, r; 48 | const double obliquit = mean_obliquity( t_c); 49 | double matrix[9]; 50 | const double obliq_2000 = 23.4392911 * PI / 180.; 51 | 52 | /* first, compute polar heliocentric in eclip of date */ 53 | if( planet_no != 10) 54 | { 55 | lon = calc_vsop_loc( vsop_data, planet_no, 0, t_c, 0.); 56 | lat = calc_vsop_loc( vsop_data, planet_no, 1, t_c, 0.); 57 | r = calc_vsop_loc( vsop_data, planet_no, 2, t_c, 0.); 58 | } 59 | else 60 | { 61 | double fund[N_FUND]; 62 | 63 | lunar_fundamentals( vsop_data, t_c, fund); 64 | lat = lunar_lat( vsop_data, fund, 0L); 65 | lunar_lon_and_dist( vsop_data, fund, &lon, &r, 0L); 66 | lon *= PI / 180.; 67 | lat *= PI / 180.; 68 | r /= AU_IN_KM; /* from km to AU */ 69 | } 70 | ovals[0] = lon; 71 | ovals[1] = lat; 72 | ovals[2] = r; 73 | /* next, compute polar cartesian in eclip of date */ 74 | ovals[3] = cos( lon) * cos( lat) * r; 75 | ovals[4] = sin( lon) * cos( lat) * r; 76 | ovals[5] = sin( lat) * r; 77 | /* next, compute polar cartesian in eclip of date, */ 78 | /* but in equatorial coords */ 79 | FMEMCPY( ovals + 6, ovals + 3, 3 * sizeof( double)); 80 | rotate_vector( ovals + 6, obliquit, 0); 81 | /* next, precess to get J2000.0 equatorial values */ 82 | setup_precession( matrix, 2000. + t_c * 100., 2000.); 83 | precess_vector( matrix, ovals + 6, ovals + 9); 84 | /* Finally, rotate equatorial J2000.0 into ecliptical J2000 */ 85 | FMEMCPY( ovals + 12, ovals + 9, 3 * sizeof( double)); 86 | rotate_vector( ovals + 12, -obliq_2000, 0); 87 | return( 0); 88 | } 89 | -------------------------------------------------------------------------------- /adestags.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | /* See 'ades2mpc.cpp'. This takes a list of ADES tags, in the order 5 | specified in the documentation, and produces arrays suitable for use 6 | in 'ades2mpc.cpp'. It also sorts the tags; this will allow for a 7 | binary search, gaining 0.001% (probably) in speed. 8 | 9 | 2022 Aug 02 : added shapeOcc, obsSubID, trkMPC elements. */ 10 | 11 | #define INTENTIONALLY_UNUSED_PARAMETER( param) (void)(param) 12 | 13 | int main( const int intentionally_unused_argc, 14 | const char **intentionally_unused_argv) 15 | { 16 | static const char *tags[] = { 17 | "permID", "provID", "artSat", "trkSub", "obsID", "obsSubID", "trkID", 18 | "trkMPC", 19 | "mode", "stn", "trx", "rcv", "sys", "ctr", "pos1", "pos2", "pos3", 20 | "posCov11", "posCov12", "posCov13", 21 | "posCov22", "posCov23", "posCov33", 22 | "prog", "obsTime", "ra", "dec", "raStar", "decStar", "obsCenter", 23 | "deltaRA", "deltaDec", "dist", "pa", "rmsRA", "rmsDec", "rmsDist", 24 | "rmsPA", "rmsCorr", "delay", "rmsDelay", "doppler", "rmsDoppler", 25 | "astCat", "mag", "rmsMag", "band", 26 | "fltr", /* added 2024 Dec 16 */ 27 | "photCat", "photAp", 28 | "nucMag", "logSNR", "shapeOcc", "seeing", "exp", 29 | /* end p6, start p7 */ 30 | "rmsFit", "nStars", "com", 31 | "frq", "ref", "disc", "subFmt", "subFrm", 32 | /* end p7/start p8 */ 33 | "precTime", "precRA", "precDec", "uncTime", "notes", "remarks", 34 | "deprecated", "localUse", "orbProd", "orbID", "resRA", "resDec", 35 | "selAst", "sigRA", "sigDec", "sigCorr", "sigTime", "biasRA", 36 | "biasDec", "biasTime", "photProd", "resMag", "selPhot", 37 | /* end p9/start p10 */ 38 | "sigMag", "biasMag", "photMod", "resDelay", "selDelay", "sigDelay", 39 | "resDoppler", "selDoppler", "sigDoppler", "observatory", "submitter", 40 | "observers", "measurers", "telescope", "software", "coinvestigators", 41 | "collaborators", "fundingSource", 42 | /* end p10/start p11 */ 43 | "comment", "optical", "offset", "occultation", "radar", "obsContext", 44 | "obsData", "obsBlock", "opticalResidual", "radarResidual", "ades", 45 | /* start "Table of Restricted Simple Types" */ 46 | "MPCID", "OpticalID", "RadarID", "RadarValue", "Precision", "Location", 47 | "Photometry", "OffsetVal", "OpticalRes", "OpticalResMag", 48 | "OpticalResiduals", "RadarResiduals", 49 | /* start p 25 */ 50 | "mpcCode", "institution", "design", "aperture", "detector", "fRatio", 51 | "filter", "arrayScale", "pixelScale", "astrometry", "fitOrder", 52 | "photometry", "objectDetection", "line", 53 | "name", 54 | /* added Sep 2018 */ 55 | "rmsTime", 56 | /* added April 2024 */ 57 | "vel1", "vel2", "vel3", 58 | NULL }; 59 | size_t i, j; 60 | 61 | INTENTIONALLY_UNUSED_PARAMETER( intentionally_unused_argv); 62 | INTENTIONALLY_UNUSED_PARAMETER( intentionally_unused_argc); 63 | 64 | for( i = 0; tags[i]; i++) 65 | for( j = i + 1; tags[j]; j++) 66 | if( strcmp( tags[i], tags[j]) > 0) 67 | { 68 | const char *tptr = tags[j]; 69 | 70 | tags[j] = tags[i]; 71 | tags[i] = tptr; 72 | } 73 | 74 | j = 60; 75 | printf( " static const char *tags[] = {"); 76 | for( i = 0; tags[i]; i++) 77 | { 78 | int len = strlen( tags[i]) + 4; 79 | 80 | if( j + len > 60) 81 | { 82 | printf( "\n "); 83 | j = 0; 84 | } 85 | printf( "\"%s\", ", tags[i]); 86 | j += len; 87 | } 88 | 89 | printf( "\n NULL };\n\n"); 90 | for( i = 0; tags[i]; i++) 91 | printf( "#define ADES_%-27s%4d\n", tags[i], (int)i + 1); 92 | return( 0); 93 | } 94 | -------------------------------------------------------------------------------- /watdefs.h: -------------------------------------------------------------------------------- 1 | /* watdefs.h: header file for inter-compiler compatibility 2 | Copyright (C) 2010, Project Pluto 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | 02110-1301, USA. */ 18 | 19 | #ifdef __WATCOMC__ 20 | #ifndef bool 21 | #define bool int 22 | #endif 23 | #ifndef true 24 | #define true 1 25 | #endif 26 | #ifndef false 27 | #define false 0 28 | #endif 29 | #ifdef __386__ 30 | #define BITS_32 31 | #endif 32 | #endif 33 | 34 | #ifdef __GNUC__ 35 | #define BITS_32 36 | #endif 37 | 38 | #ifdef _WIN32 39 | #define BITS_32 40 | #endif 41 | 42 | #ifdef BITS_32 43 | 44 | #ifndef FAR 45 | #define FAR 46 | #endif 47 | 48 | #ifndef _HUGE 49 | #define _HUGE 50 | #endif 51 | 52 | #ifndef NEAR 53 | #define NEAR 54 | #endif 55 | 56 | #ifndef PASCAL 57 | #define PASCAL 58 | #endif 59 | 60 | #define FMEMCPY memcpy 61 | #define FMEMCMP memcmp 62 | #define FMEMICMP memicmp 63 | #define FMEMMOVE memmove 64 | #define FMEMSET memset 65 | #define FSTRCPY strcpy 66 | #define FSTRSTR strstr 67 | #define FSTRCAT strcat 68 | #define FSTRNCPY strncpy 69 | #define FSTRICMP stricmp 70 | #define FSTRCMP strcmp 71 | #define FSTRLEN strlen 72 | #define FMALLOC malloc 73 | #define FCALLOC calloc 74 | #define FFREE free 75 | #define FREALLOC realloc 76 | #define STRUPR strupr 77 | 78 | #ifdef __WATCOMC__ 79 | #define _ftime ftime 80 | #define _timeb timeb 81 | #define _videoconfig videoconfig 82 | #define _timezone timezone 83 | #define _tzset tzset 84 | #define _swab swab 85 | #define _unlink unlink 86 | /* int _stricmp( char *s1, char *s2); */ 87 | /* int _memicmp( char *s1, char *s2, int n); */ 88 | #endif 89 | #endif 90 | 91 | #ifndef BITS_32 92 | 93 | #define _FAR __far 94 | #define _HUGE huge 95 | 96 | #ifndef FAR 97 | #define FAR far 98 | #endif 99 | 100 | #ifndef NEAR 101 | #define NEAR near 102 | #endif 103 | 104 | #ifndef PASCAL 105 | #define PASCAL pascal 106 | #endif 107 | 108 | #define FMEMCPY _fmemcpy 109 | #define FMEMCMP _fmemcmp 110 | #define FMEMICMP _fmemicmp 111 | #define FMEMMOVE _fmemmove 112 | #define FMEMSET _fmemset 113 | #define FSTRCPY _fstrcpy 114 | #define FSTRSTR _fstrstr 115 | #define FSTRCAT _fstrcat 116 | #define FSTRNCPY _fstrncpy 117 | #define FSTRLEN _fstrlen 118 | #define FSTRICMP _fstricmp 119 | #define FSTRCMP _fstrcmp 120 | #define FMALLOC _fmalloc 121 | #define FCALLOC _fcalloc 122 | #define FFREE _ffree 123 | #define FREALLOC _frealloc 124 | #define STRUPR _strupr 125 | #endif 126 | 127 | #ifdef _WIN32 128 | #define DLL_FUNC __stdcall 129 | #else 130 | #define DLL_FUNC 131 | #endif 132 | 133 | #define DLLPTR 134 | 135 | /* __restrict is defined in MinGW and Digital Mars, no matter what; and 136 | in Watcom for C, but not C++. It's not in Visual C++ at all. */ 137 | 138 | #if defined( __WATCOMC__) && defined( __cplusplus) 139 | #define __restrict 140 | #elif defined( _MSC_VER) 141 | #define __restrict 142 | #endif 143 | 144 | /* A useful trick to suppress 'unused parameter' warnings, modified from 145 | 146 | https://stackoverflow.com/questions/1486904/how-do-i-best-silence-a-warning-about-unused-variables 147 | */ 148 | 149 | #define INTENTIONALLY_UNUSED_PARAMETER( param) (void)(param) 150 | -------------------------------------------------------------------------------- /rckin.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | /* rckin.cpp: processes/reformats JPL 'rckin' files 4 | 5 | Copyright (C) 2010, Project Pluto 6 | 7 | This program is free software; you can redistribute it and/or 8 | modify it under the terms of the GNU General Public License 9 | as published by the Free Software Foundation; either version 2 10 | of the License, or (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program; if not, write to the Free Software 19 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 20 | 02110-1301, USA. */ 21 | 22 | #include 23 | #include 24 | 25 | /* Code to convert files such as 'rckin.ura091.txt', etc. from 26 | ftp://ssd.jpl.nasa.gov/pub/eph/satellites/rckin 27 | into the form used in 'rocks.cpp'. 28 | 29 | Of late, JPL hasn't been updating these files. I gather this is 30 | because they are using integrated ephemerides for almost all "rocks". 31 | So this may prove to be of historical interest only. (Although when 32 | I asked, Bob Jacobson kindly provided updates to some of the files.) 33 | */ 34 | 35 | int main( const int argc, const char **argv) 36 | { 37 | FILE *ifile = fopen( argv[1], "rb"); 38 | char buff[200]; 39 | char rock_name[80]; 40 | 41 | if( !ifile) 42 | { 43 | printf( "%s not opened\n", argv[1]); 44 | return( -1); 45 | } 46 | 47 | while( fgets( buff, sizeof( buff), ifile)) 48 | { 49 | char *tptr = strchr( buff + 19, '\''); 50 | 51 | if( tptr) 52 | *tptr = '\0'; 53 | tptr = strchr( buff + 19, ','); 54 | if( tptr) 55 | *tptr = '\0'; 56 | tptr = buff + 19; 57 | if( !memcmp( buff, " RCKNAM", 8)) 58 | { 59 | int i; 60 | 61 | strcpy( rock_name, tptr); 62 | for( i = 1; rock_name[i]; i++) 63 | rock_name[i] = tolower( rock_name[i]); 64 | } 65 | if( !memcmp( buff, " RCKNUM", 8)) 66 | printf( "\n { %d, /* %s %s*/\n", atoi( buff + 17), 67 | rock_name, (argc < 3 ? " " : argv[2])); 68 | if( !memcmp( buff, " RCKEP", 7)) 69 | { 70 | strcat( tptr, ","); 71 | printf( " %-38s/* element epoch Julian date */\n", tptr); 72 | } 73 | if( !memcmp( buff, " RCKELT", 8)) 74 | { 75 | const int field_no = atoi( buff + 9); 76 | const char *comment[10] = { NULL, 77 | "a = semi-major axis (km) ", 78 | "h = e sin(periapsis longitude)", 79 | "k = e cos(periapsis longitude)", 80 | "l = mean longitude (deg) ", 81 | "p = tan(i/2) sin(node) ", 82 | "q = tan(i/2) cos(node) ", 83 | "apsis rate (deg/sec) ", 84 | "mean motion (deg/sec) ", 85 | "node rate (deg/sec) " }; 86 | 87 | if( field_no == 4 || field_no == 7 || field_no == 8 || field_no == 9) 88 | strcat( tptr, " * PI / 180."); 89 | strcat( tptr, ","); 90 | printf( " %-38s/* %s*/\n", tptr, 91 | comment[atoi( buff + 9)]); 92 | } 93 | if( !memcmp( buff, " CTRRA", 7)) 94 | { 95 | strcat( tptr, " * PI / 180.,"); 96 | printf( " %-38s/* Laplacian plane pole ra (deg) */\n", tptr); 97 | } 98 | if( !memcmp( buff, " CTRDEC", 8)) 99 | { 100 | strcat( tptr, " * PI / 180. },"); 101 | printf( " %-38s/* Laplacian plane pole dec (deg)*/\n", tptr); 102 | } 103 | } 104 | fclose( ifile); 105 | return( 0); 106 | } 107 | -------------------------------------------------------------------------------- /vsopson.cpp: -------------------------------------------------------------------------------- 1 | /* vsopson.cpp: functions for medium-precision planetary coordinates 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include "watdefs.h" 25 | #include "lunar.h" 26 | #include "get_bin.h" 27 | 28 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923 29 | #define TWO_PI (PI + PI) 30 | 31 | /* This function, given a pointer to a buffer containing the data from 32 | VSOP.BIN, can compute planetary positions in heliocentric ecliptic 33 | coordinates. 'planet' can run from 0=sun, 1=mercury, ... 8=neptune. 34 | (VSOP doesn't handle the moon or Pluto.) 'value' can be either 35 | 0=ecliptic longitude, 1=ecliptic latitude, 2=distance from sun. 36 | (These are ecliptic coordinates _of date_, by the way!) 37 | 38 | t = (JD - 2451545.) / 36525. = difference from J2000, in Julian 39 | centuries. 'prec' ('precision') can be used to tell the code to ignore 40 | small terms in the VSOP expansion. Once upon a time, when math 41 | coprocessors were rare, I occasionally made use of this fact. Nowadays, 42 | almost all my code sets prec=0 (i.e., include all terms.) 43 | 44 | This function relies on direct reading of binary data. See 45 | 'get_bin.h' for details on this. */ 46 | 47 | double DLL_FUNC calc_vsop_loc( const void FAR *data, const int planet, 48 | const int value, double t, double prec) 49 | { 50 | int16_t FAR *loc; 51 | int i, j; 52 | double sum, rval = 0., power = 1.; 53 | double FAR *tptr; 54 | 55 | if( !planet) 56 | return( 0.); /* the sun */ 57 | 58 | assert( planet > 0 && planet < 9); 59 | assert( value >= 0 && value <= 2); 60 | assert( data); /* now check VSOP data is correct */ 61 | assert( ((char *)data)[2] == '&'); /* verify a few bytes at random */ 62 | assert( ((char *)data)[20] == 'x'); 63 | assert( ((char *)data)[0xea0a] == 'q'); 64 | assert( get16bits( (char *)data + 0x10c) == 0x93e); 65 | t /= 10.; /* convert to julian millennia */ 66 | loc = (int16_t FAR *)data + (planet - 1) * 18 + value * 6; 67 | for( i = 6; i; i--, loc++) 68 | { 69 | const int16_t loc0 = get16bits( loc); 70 | const int16_t loc1 = get16bits( loc + 1); 71 | 72 | assert( loc0 >= 0); 73 | assert( loc1 >= loc0); 74 | assert( loc1 <= 0x97e); 75 | sum = 0.; 76 | if( prec < 0.) 77 | prec = -prec; 78 | tptr = (double FAR *)((int16_t FAR *)data + 8 * 18 + 1) + loc0 * 3U; 79 | 80 | for( j = loc1 - loc0; j; j--, tptr += 3) 81 | { 82 | const double amplitude = get_double( tptr); 83 | 84 | if( amplitude > prec || amplitude < -prec) 85 | { 86 | const double argument = 87 | get_double( tptr + 1) + get_double( tptr + 2) * t; 88 | 89 | sum += amplitude * cos( argument); 90 | } 91 | } 92 | rval += sum * power; 93 | power *= t; 94 | if( t != 0.) 95 | prec /= t; 96 | } 97 | 98 | if( ((char FAR *)data)[2] == 38) 99 | rval *= 1.e-8; 100 | if( value == 0) /* ensure 0 < lon < 2 * pi */ 101 | { 102 | rval = fmod( rval, TWO_PI); 103 | if( rval < 0.) 104 | rval += TWO_PI; 105 | } 106 | return( rval); 107 | } 108 | 109 | -------------------------------------------------------------------------------- /get_out.txt: -------------------------------------------------------------------------------- 1 | ; Test cases for 'get_time': 2 | format 6 (day/month/year: 0009-aug-07) 3 | 1 Sep 2009 0:00:00.000 0 se 2009 4 | 7 Oct 2009 0:00:00.000 0 7 oct 5 | 29 Dec 2009 0:00:00.000 0 12 29 6 | 28 Nov 2009 0:00:00.000 0 28 11 7 | 28 Oct 1912 0:00:00.000 0 oct 1912 8 | 7 Dec 1941 3:14:00.000 0 7 dec 1941 3:14 9 | 22 Nov 1963 18:19:22.000 0 22 1963 nov18:19:22 10 | 25 Dec 2008 18:19:22.000 0 081225 : 11 | 4 Jul 1776 12:00:00.000 0 17760704 12:00 12 | 1 Jan 2000 12:00:00.000 1 2451545 13 | 1 Nov 2008 0:00:00.000 0 2008 n 14 | 11 Sep 2001 0:00:00.000 0 se 11 2001 15 | 10 Sep 2001 21:00:00.000 0 -3h 16 | 15 Sep 2001 21:00:00.000 0 +5d 17 | 15 Sep 2001 17:00:00.000 0 17: 18 | 15 Sep 2001 17:07:00.000 0 :7 19 | 19 Feb 2008 6:00:00.000 0 2008/50.25 20 | 19 Dec 2008 6:00:00.000 0 d : 21 | 19 Dec 2008 3:14:15.926 0 3:14:15.92653 22 | 2 Dec -443 0:00:00.000 0 -443 2 12 23 | 6 May 1997 12:30:23.334 0 1997.06.05 12:30:23.3348 24 | 9 Oct -414 10:33:00.000 0 BC 415o9 12:33 -2h 25 | 3 Feb 2100 3:14:00.000 0 21000203 03:14 26 | 25 Feb 1965 16:00:00.000 0 650225 16:00 27 | 25 Feb 1965 3:14:15.900 0 3:14:15.9 28 | 11 Feb 1965 3:14:15.900 0 11/2 : 29 | 12 Mar 1965 0:00:00.000 0 12 3 30 | 11 Feb 1965 6:00:00.000 0 11.25-2 31 | 13 Mar 1965 9:36:00.000 0 3-13.4 32 | 1 Jan 2000 12:00:00.000 1 j2451545 33 | 1 Apr 2000 12:00:00.000 0 Ap : 34 | 18 Jun 2004 0:00:00.000 0 6/18/2004 35 | 18 Jun 2004 0:17:12.300 0 :17:12.3 36 | 1 Jan 2000 12:00:00.000 1 JD 2451545. 37 | 14 Mar 2008 15:26:53.500 0 2008-03-14T15:26:53.5 38 | 6 Jul 1998 0:00:00.000 1 mjd 51000 39 | 19 Feb 2008 3:14:09.540 0 50 2008 3:14.159 40 | 4 May 1952 4:26:24.000 0 y1952.34 41 | 19 Feb 2008 18:00:00.000 0 50.75 2008 42 | 4 May 1952 4:26:24.000 0 1952.34 43 | 4 May 1952 4:08:24.000 0 :8.4 44 | 13 May 1952 10:08:24.000 0 +9.25 45 | format 806 (year/day/month: following should be 0003-may-4, jun-7) 46 | 4 May 3 0:00:00.000 0 3 4 5 47 | 7 Jun 3 0:00:00.000 0 7 6 48 | format 1806 (year/month/day: following should be 0001-feb-6, sep-11) 49 | 6 Feb 1 0:00:00.000 0 1.2.6 50 | 11 Sep 1 0:00:00.000 0 9 11 51 | format 6 (day/month/year: 0009-aug-07) 52 | 7 Aug 9 0:00:00.000 0 7 8 9 53 | format 1006 (month/day/year: 0012-oct-11) 54 | 11 Oct 12 0:00:00.000 0 10 11 12 55 | 15 Feb 2008 0:00:00.000 0 15 2 2008 56 | 16 Mar 2009 0:00:00.000 0 3 16 2009 57 | 4 Jul -10 0:00:00.000 0 7 4 bc11 58 | 15 Feb 2008 4:00:00.000 0 2008.15.2 4: 59 | 16 Jul 2009 0:00:00.000 0 2009 7 16 60 | ; If a field has a decimal point in it, it should be recognized as a day: 61 | 3 Apr 1941 4:48:00.000 0 1941 4 3.2 62 | 5 Oct 2009 12:00:00.000 0 5.5 10 2009 63 | 6 Aug 2002 6:00:00.000 0 2002-6.25-8 64 | 1 Apr 1997 7:12:00.000 0 1.3 1997 4 65 | ; Next line _should_ change between runs... 66 | 26 Feb 2024 19:37:49.000 0 now-4d 67 | ; ...but nothing else should! 68 | 5 Oct 2015 9:36:00.000 0 10/5.4/2015 69 | 7 Mar 1917 18:00:00.000 0 3 1917 7.75 70 | 9 May 1917 3:00:00.000 0 9.125 5 71 | 7 Feb 1917 6:00:00.000 0 2 7.25 72 | ; find time three days before new moon... 73 | 18 Feb 1917 18:08:14.187 1 nm-3d 74 | 3 Oct -1456 12:34:00.000 0 1457 oct 3 BC 12:34 75 | ; Start from 2011 dec 13, back up four weeks, find the time of the 76 | ; nearest Third Quarter phase, then add two days: 77 | 20 Nov 2011 15:09:17.518 1 2011 dec 13 -4w 3Q +2d 78 | ; Similar efforts: 79 | 24 Dec 1842 23:59:39.702 1 15o1843-300d1q+16d-22.43h 80 | 1 Mar 1843 6:00:07.258 1 +60d nm 81 | 1 Mar 1843 3:00:00.000 0 1q 3:00 82 | 1 Mar 1843 16:56:07.000 0 4:56:07 p.m. 83 | 4 May 37 16:10:00.000 0 5 4 37 6:10 pm -2h 84 | 3 Aug 37 3:01:00.000 0 8/3 3:01 A.M. 85 | 14 Sep 37 12:17:00.000 0 14/9 12:17 pm 86 | 11 Sep 37 0:51:00.000 0 s11 12:51am 87 | 1 Oct 2009 21:41:23.800 0 2009-10-01T21:41:23.8 88 | format 6 (day/month/year: 0009-aug-07) 89 | 4 Mar 1997 3:14:16.000 0 1997-03-04T03:14:16 90 | ; Added 2019 Jul 21 : 91 | 21 Jul 2069 0:37:33.000 0 unix3141592653 92 | 24 Jul 2019 13:14:12.000 0 gps20633+13h+14.2m 93 | ; Added 2024 Mar 01 : the following should cause errores to be returned 94 | 28 Jan 2019 0:00:00.000 -4 z28 95 | 3 Jan 2021 17:00:00.000 -5 3Ock2021 17:00 96 | 21 Jan 2022 0:00:00.000 -5 2022 Maz 21 97 | 15 Jan 2022 3:17:00.000 -6 Jan 15 z 3:17 98 | -------------------------------------------------------------------------------- /lunar.h: -------------------------------------------------------------------------------- 1 | /* lunar.h: header file for basic astrometric functions 2 | Copyright (C) 2010, Project Pluto 3 | 4 | This program is free software; you can redistribute it and/or 5 | modify it under the terms of the GNU General Public License 6 | as published by the Free Software Foundation; either version 2 7 | of the License, or (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 17 | 02110-1301, USA. */ 18 | 19 | #ifndef LUNAR_H_INCLUDED 20 | #define LUNAR_H_INCLUDED 21 | 22 | #define N_FUND 9 23 | 24 | #ifdef __cplusplus 25 | extern "C" { 26 | #endif 27 | 28 | #ifndef AU_IN_KM 29 | #define AU_IN_KM 1.495978707e+8 30 | #endif 31 | 32 | #ifndef AU_IN_METERS 33 | #define AU_IN_METERS (AU_IN_KM * 1000.) 34 | #endif 35 | 36 | #ifndef SPEED_OF_LIGHT 37 | #define SPEED_OF_LIGHT 299792.458 38 | #endif 39 | 40 | #ifndef AU_PER_DAY 41 | #define AU_PER_DAY (86400. * SPEED_OF_LIGHT / AU_IN_KM) 42 | #endif 43 | 44 | double DLL_FUNC lunar_lat( const void FAR *data, const double DLLPTR *fund, 45 | const long precision); 46 | int DLL_FUNC lunar_lon_and_dist( const void FAR *data, const double DLLPTR *fund, 47 | double DLLPTR *lon, double DLLPTR *r, const long precision); 48 | 49 | int DLL_FUNC unload_ps1996_series( void *p); 50 | int DLL_FUNC get_ps1996_position( const double jd, const void *iptr, 51 | double *state_vect, const int compute_velocity); 52 | #ifdef SEEK_CUR 53 | void * DLL_FUNC load_ps1996_series( FILE *ifile, double jd, int planet_no); 54 | int DLL_FUNC compute_elp_xyz( FILE *ifile, const double t_cen, const double prec, 55 | double *ecliptic_xyz_2000); 56 | int DLL_FUNC calc_big_vsop_loc( FILE *ifile, const int planet, 57 | double *ovals, double t, const double prec0); 58 | #endif 59 | 60 | int DLL_FUNC lunar_fundamentals( const void FAR *data, const double t, 61 | double DLLPTR *fund); 62 | long double DLL_FUNC find_nearest_lunar_phase_time( 63 | const int phase_idx, const long double t2k); 64 | double DLL_FUNC mean_obliquity( const double t_cen); 65 | int DLL_FUNC calc_pluto_loc( const void FAR *data, double DLLPTR *loc, 66 | const double t, const long precision); 67 | int DLL_FUNC calc_jsat_loc( const double jd, double DLLPTR *jsats, 68 | const int sats_wanted, const long precision); 69 | int DLL_FUNC calc_ssat_loc( const double t, double DLLPTR *ssat, 70 | const int sat_wanted, const long precision); 71 | void DLL_FUNC calc_triton_loc( const double jd, double *vect); 72 | double DLL_FUNC calc_vsop_loc( const void FAR *data, const int planet, 73 | const int value, double t, double prec); 74 | int DLL_FUNC nutation( const double t, double DLLPTR *d_lon, 75 | double DLLPTR *d_obliq); 76 | int DLL_FUNC compute_planet( const char FAR *vsop_data, const int planet_no, 77 | const double t_c, double DLLPTR *ovals); 78 | int DLL_FUNC calc_planet_orientation( const int planet_no, const int system_no, 79 | const double jd, double *matrix); 80 | int DLL_FUNC planet_radii( const int planet_no, double *radii_in_km); 81 | double DLL_FUNC planet_rotation_rate( const int planet_no, const int system_no); 82 | int DLL_FUNC load_cospar_file( const char *filename); 83 | int DLL_FUNC evaluate_rock( const double jd, const int jpl_id, 84 | double *output_vect); 85 | double planet_radius_in_meters( const int planet_idx); /* mpc_code.cpp */ 86 | double planet_axis_ratio( const int planet_idx); /* mpc_code.cpp */ 87 | 88 | #ifdef __cplusplus 89 | } 90 | #endif 91 | 92 | #endif /* #ifndef LUNAR_H_INCLUDED */ 93 | -------------------------------------------------------------------------------- /mpcorb2.cpp: -------------------------------------------------------------------------------- 1 | /* mpcorb2.cpp: functions to get basic data on 'mpcorb.dat' files 2 | (Not really very relevant to anything, as it's turned out!) 3 | 4 | Copyright (C) 2010, Project Pluto 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 | 02110-1301, USA. */ 20 | 21 | #include 22 | #include 23 | 24 | /* 'mpcorb.dat' files have some oddities that complicate automated 25 | handling. Each file has a dozen or so lines of "header" data. 26 | Following are a few hundred thousand lines of numbered objects, 27 | with each line being 203 bytes long (202 bytes of actual data 28 | plus a line-feed terminator). 29 | 30 | Then an additional line-feed is inserted, followed by more lines 31 | for unnumbered multi-opposition objects, plus another line-feed and 32 | more lines for single-opposition objects (all unnumbered). Hence, 33 | you can't just seek to (header_size + 203 * record_number) and 34 | read 202 bytes. Well, you can do that for numbered objects... 35 | but for unnumbered multi-opp ones, you need to go an additional 36 | byte, to account for that !*#% line feed; and for single-opp 37 | data, you need to go yet another byte. So knowing ahead of time 38 | the header length and how many objects there are of each type 39 | could be useful. 40 | 41 | As it turned out, I never actually needed the following (I worked 42 | away around the need). So it's not as thoroughly tested as it might be. 43 | User beware. 44 | 45 | data[0] = header length, in bytes; 46 | data[1] = number of numbered asteroids / start of multi-opps; 47 | data[2] = start of single-opp objects; 48 | data[3] = total number of objects */ 49 | 50 | #define MPCORB_RECLEN 203 51 | 52 | int get_mpcorb_info( FILE *ifile, long *data) 53 | { 54 | char buff[210]; 55 | int lines_read = 0, i; 56 | 57 | fseek( ifile, 0L, SEEK_SET); 58 | data[0] = 0; /* assume no header */ 59 | data[1] = data[2] = data[3] = 0; 60 | while( lines_read < 50 && fgets( buff, sizeof( buff), ifile)) 61 | { 62 | lines_read++; 63 | if( *buff == '-') /* we've read the entire header */ 64 | { 65 | lines_read = 1000; 66 | data[0] = ftell( ifile); 67 | } 68 | } 69 | fseek( ifile, 0L, SEEK_END); 70 | data[3] = (ftell( ifile) - data[0]) / MPCORB_RECLEN; 71 | for( i = 1; i <= 3; i++) 72 | { 73 | long step, loc1; 74 | 75 | for( step = 0x800000; step; step >>= 1) 76 | { 77 | loc1 = data[i] + step; 78 | if( !fseek( ifile, data[0] + loc1 * MPCORB_RECLEN, SEEK_SET)) 79 | if( fread( buff, 10, 1, ifile)) 80 | { 81 | if( buff[0] == 10 && loc1 > data[2]) 82 | data[2] = loc1; 83 | else if( buff[0] != 10 && buff[1] != 10 && loc1 > data[1]) 84 | data[1] = loc1; 85 | } 86 | } 87 | } 88 | data[1]++; 89 | return( 0); 90 | } 91 | 92 | int main( const int argc, const char **argv) 93 | { 94 | FILE *ifile = fopen( "mpcorb.dat", "rb"); 95 | long data[4]; 96 | char tbuff[80]; 97 | 98 | if( ifile) 99 | { 100 | get_mpcorb_info( ifile, data); 101 | printf( "%ld %ld %ld %ld\n", data[0], data[1], data[2], data[3]); 102 | } 103 | else 104 | printf( "mpcorb.dat not opened\n"); 105 | if( argc > 1) 106 | { 107 | long rec_num = atol( argv[1]); 108 | long offset = data[0] + rec_num * MPCORB_RECLEN; 109 | 110 | if( rec_num >= data[2]) 111 | offset += 2; 112 | else if( rec_num >= data[1]) 113 | offset++; 114 | fseek( ifile, offset, SEEK_SET); 115 | fread( tbuff, 80, 1, ifile); 116 | tbuff[79] = '\0'; 117 | printf( "%s", tbuff); 118 | } 119 | return( 0); 120 | } 121 | -------------------------------------------------------------------------------- /superga2.cpp: -------------------------------------------------------------------------------- 1 | /* superga2.cpp: code to compute a supergalactic-to-J2000 matrix 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | #include 20 | #include 21 | 22 | /* Running the following code produces a J2000 to supergalactic 23 | coordinate matrix, which looks as follows: 24 | 25 | 0.37501548 0.34135896 0.86188018 26 | -0.89832046 -0.09572714 0.42878511 27 | 0.22887497 -0.93504565 0.27075058 28 | 29 | Written in reply to an inquiry from Christopher Watson; see 30 | 31 | https://groups.io/g/amastro/message/13921 32 | 33 | The code in 'supergal.cpp' gets a similar result, using equatorial values 34 | for the position of the supergalactic plane. However, the RA/dec values 35 | given are not exact (given to one-second precision, or 15-arcsec precision, 36 | in RA.) This method ought to be "exact". 37 | 38 | At the end, it gives the coordinates for the SG north pole and zero 39 | point in J2000 to full precision, in decimal and base-60, as 40 | 41 | 2.82067484 02h 49m 14.4294s (RA of zero point, SGL = SGB = 0) 42 | 59.52834978 +59 31' 42.0592" (dec of zero point, SGL = SGB = 0) 43 | 18.91693936 18h 55m 0.9817s (RA of SG north pole, SGB = 90) 44 | 15.70893553 +15 42' 32.1679" (dec of SG north pole) 45 | */ 46 | 47 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923 48 | #define NORTH_POLE_LAT (6.32 * PI / 180.) 49 | #define NORTH_POLE_LON (47.37 * PI / 180.) 50 | #define ZERO_POINT_LON (137.37 * PI / 180.) 51 | 52 | /* The following matrix comes from _The Hipparcos & Tycho */ 53 | /* Catalogues: Introduction & Guide to the Data_, p 92: */ 54 | static const double galactic_to_j2000[9] = { 55 | -.0548755604, -.8734370902, -.4838350155, 56 | .4941094279, -.4448296300, .7469822445, 57 | -.8676661490, -.1980763734, .4559837762 }; 58 | 59 | int main( const int unused_argc, const char **unused_argv) 60 | { 61 | double matrix[9], rotation[9]; 62 | int i, j; 63 | 64 | /* vector pointing toward (supergalactic) lat=lon=0: */ 65 | rotation[0] = cos( ZERO_POINT_LON); 66 | rotation[1] = sin( ZERO_POINT_LON); 67 | rotation[2] = 0.; 68 | 69 | /* vector pointing toward the north supergalactic pole: */ 70 | rotation[6] = cos( NORTH_POLE_LON) * cos( NORTH_POLE_LAT); 71 | rotation[7] = sin( NORTH_POLE_LON) * cos( NORTH_POLE_LAT); 72 | rotation[8] = sin( NORTH_POLE_LAT); 73 | 74 | rotation[3] = -cos( NORTH_POLE_LON) * sin( NORTH_POLE_LAT); 75 | rotation[4] = -sin( NORTH_POLE_LON) * sin( NORTH_POLE_LAT); 76 | rotation[5] = cos( NORTH_POLE_LAT); 77 | 78 | for( i = 0; i < 3; i++) 79 | for( j = 0; j < 3; j++) 80 | matrix[j + i * 3] = 81 | rotation[i * 3] * galactic_to_j2000[j] 82 | + rotation[i * 3 + 1] * galactic_to_j2000[j + 3] 83 | + rotation[i * 3 + 2] * galactic_to_j2000[j + 6]; 84 | 85 | printf( "%11.8lf %11.8lf %11.8lf\n", matrix[0], matrix[1], matrix[2]); 86 | printf( "%11.8lf %11.8lf %11.8lf\n", matrix[3], matrix[4], matrix[5]); 87 | printf( "%11.8lf %11.8lf %11.8lf\n", matrix[6], matrix[7], matrix[8]); 88 | printf( "\n"); 89 | 90 | for( i = 0; i < 4; i++) 91 | { 92 | double oval, tval, sec; 93 | int deg, min; 94 | 95 | j = (i / 2) * 6; 96 | if( i % 2 == 0) 97 | oval = atan2( -matrix[j + 1], -matrix[j]) * 12. / PI + 12.; 98 | else 99 | oval = asin( matrix[j + 2]) * 180. / PI; 100 | deg = (int)oval; 101 | tval = (oval - (double)deg) * 60.; 102 | min = (int)tval; 103 | sec = (tval - (double)min) * 60.; 104 | printf( "%12.8lf %02d %02d %7.4lf\n", oval, deg, min, sec); 105 | } 106 | return( 0); 107 | } 108 | -------------------------------------------------------------------------------- /big_vsop.txt: -------------------------------------------------------------------------------- 1 | Hi Mark, 2 | 3 | Following is "documentation", of a sort, for 'big_vsop.bin' 4 | and 'big_vsop.cpp'. I'll incorporate it into the latter at some 5 | point. The opening paragraphs are probably old news to you, 6 | but... here goes: 7 | 8 | BE WARNED that for many purposes, rather than using VSOP (in 9 | either its short or long forms), it's well to use either the 10 | PS-1996 series or DE ephemerides. Source code for both is 11 | available from my site. 12 | 13 | VSOP is based on the now-obsolete DE-200 ephemeris, doesn't 14 | include the moon or Pluto, and requires summing up a staggering 15 | number of terms to get full accuracy. Use of DE ephemerides or 16 | PS-1996 is much faster and more accurate. 17 | 18 | On the plus side, VSOP covers millennia into the past and 19 | future (PS-1996 only covers about a century or so into the past 20 | and future, depending on the planet in question), and can be 21 | packed into a small file size (the full DE ephemerides can 22 | consume up to 200 MBytes). You can sum up just a few VSOP terms 23 | and get results good to an arcminute or so, ample for 24 | low-precision uses. 25 | 26 | In both 'big_vsop.bin' and 'vsop.bin', for each of the eight 27 | planets (Mercury through Neptune), data is provided in the 28 | "usual" VSOP form, as a Poisson series (a mix of a Fourier-like 29 | series of trig terms and a Taylor-like power series.) Thus, for 30 | example, the ecliptic latitude of a planet would be computed as 31 | 32 | latitude = (sum of trig terms0) 33 | + (sum of trig terms1) * t 34 | + (sum of trig terms2) * t^2 35 | + (sum of trig terms3) * t^3 36 | + (sum of trig terms4) * t^4 37 | + (sum of trig terms5) * t^5 38 | 39 | ...with similar series given for ecliptic longitude and heliocentric 40 | radius. 41 | 42 | 't' = (jd - 2541545.0) / 365250, the difference in millennia 43 | between the time in question and 1.5 January 2000. The 'trig terms' 44 | are all of the form amplitude * cos( angle + rate * t). Almost all of 45 | 'big_vsop.bin' consists of the values for 'amplitude', 'angle' and 46 | 'rate', with a small header describing just where the 'amplitude', 47 | 'angle' and 'rate' data for a given series begins and ends. 48 | 49 | As you can see, each value requires summing up six series, then 50 | multiplying by some integer power of t. We've got six series per 51 | value, three values per planet, and eight planets... therefore, 52 | 6 * 3 * 8 = 144 series. Any given planet requires 18 series. 53 | 54 | The 'big_vsop' header could, in theory, give you the starting 55 | and ending location of each series, as short integer values. You'd 56 | then have 144 * 2, or 288, values in the header. In reality, all 57 | I did was store the beginning of each series; you figure out where 58 | it ends by looking at the beginning of the next series. That brings 59 | us down to 145 values in the header (the last value giving you where 60 | the final series actually ends.) 61 | 62 | Since each header entry is a short int, we're looking at 290 bytes. 63 | 64 | In a possibly misguided effort to save space (well, it _did_ make 65 | lots of sense back in 1993!), I store the header data needed for 66 | one particular planet in RAM at a given time. If someone asks for 67 | a "new planet" (in big_vsop.cpp, 'if( curr_planet != planet)'), 68 | then we dig through 'big_vsop.bin' for the required header data 69 | and store it in a static array. That requirement is for nineteen 70 | short (16-bit) integers: there are three values to be computed 71 | (lat/lon/r) and six series for each of them (1, t, t^2, ...t^5), 72 | and we need to know where the last of them ends. So the static 73 | array 'cache' is dimensioned for 19 shorts. 74 | 75 | We then use that data stored in 'cache' to go forth and grab 76 | VSOP data. For longitude, the coefficients for the (1, t, ...t^5) 77 | series are stored at offsets indicated by cache[0], cache[1], ... 78 | cache[5], with the latter ending at cache[6] (that is, the t^5 79 | series would have cache[6]-cache[5] terms.) For latitude, 80 | the coefficients would be at offsets indicated by cache[6...11], 81 | and for heliocentric radius, cache[12...17], with the last 82 | t^5 term having cache[18]-cache[17] terms. 83 | 84 | The actual file offset, in bytes, is going to be 24 bytes 85 | per term (each term consumes three double-precision floats) plus 86 | the 290 bytes for the header. That's why the actual 'fseek' call 87 | in 'big_vsop.cpp' reads as 88 | 89 | fseek( ifile, 290L + (long)loc[0] * 24L, SEEK_SET); 90 | 91 | -- Bill 92 | -------------------------------------------------------------------------------- /nanosecs.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | /* 'nanoseconds_since_1970( )' returns something close to the result of 19 | ctime( ), except a billion times larger and with added precision. 20 | Naturally, DOS/Windows, OS/X, and POSIX systems each use different 21 | methods. 22 | 23 | As currently coded, the actual precision provided is 10^-7 second 24 | in Windows; a millisecond with the WATCOM compiler; and 10^-6 second 25 | in everything else. But note that "true" nanosecond precision is 26 | possible, if actually desired (see the NOT_CURRENTLY_IN_USE code). 27 | 28 | The range of a 64-bit signed integer is large enough to enable 29 | this function to work until Friday, 2262 Apr 11 23:47:16.854775808. 30 | We can get an addition 292 years by using unsigned integers, but 31 | it may be wiser to switch to 128-bit integers. 32 | 33 | Note that the usual limitations apply: no leap seconds, and if 34 | the computer's time is adjusted by NTP or the user, the result may 35 | actually go backward. If you want to know what time it is, don't 36 | ask a computer. */ 37 | 38 | #ifdef _WIN32 39 | #include 40 | #endif 41 | 42 | #ifdef __WATCOMC__ 43 | #include 44 | #endif 45 | 46 | #include 47 | #include "watdefs.h" 48 | #include "afuncs.h" 49 | 50 | int64_t DLL_FUNC nanoseconds_since_1970( void); /* afuncs.c */ 51 | 52 | #ifdef _WIN32 53 | 54 | int64_t DLL_FUNC nanoseconds_since_1970( void) 55 | { 56 | FILETIME ft; 57 | const uint64_t jd_1601 = 2305813; /* actually 2305813.5 */ 58 | const uint64_t jd_1970 = 2440587; /* actually 2440587.5 */ 59 | const uint64_t ten_million = 10000000; 60 | const uint64_t diff = (jd_1970 - jd_1601) * ten_million * (uint64_t)seconds_per_day; 61 | uint64_t decimicroseconds_since_1970; /* i.e., time in units of 1e-7 seconds */ 62 | 63 | GetSystemTimeAsFileTime( &ft); 64 | decimicroseconds_since_1970 = ((uint64_t)ft.dwLowDateTime | 65 | ((uint64_t)ft.dwHighDateTime << 32)) - diff; 66 | return( decimicroseconds_since_1970 * (int64_t)100); 67 | } 68 | #else 69 | #ifdef __WATCOMC__ 70 | int64_t DLL_FUNC nanoseconds_since_1970( void) 71 | { 72 | struct timeb t; 73 | const int64_t one_million = 1000000; 74 | int64_t millisec; 75 | 76 | ftime( &t); 77 | millisec = (int64_t)t.millitm + (int64_t)1000 * (int64_t)t.time; 78 | return( millisec * (int64_t)one_million); 79 | } 80 | #else /* OS/X, BSD, and Linux */ 81 | #include 82 | #include 83 | 84 | int64_t DLL_FUNC nanoseconds_since_1970( void) 85 | { 86 | struct timeval now; 87 | const int rv = gettimeofday( &now, NULL); 88 | int64_t rval; 89 | const int64_t one_billion = (int64_t)1000000000; 90 | 91 | if( !rv) 92 | rval = (int64_t)now.tv_sec * one_billion 93 | + (int64_t)now.tv_usec * (int64_t)1000; 94 | else 95 | rval = 0; 96 | return( rval); 97 | } 98 | #endif 99 | #endif 100 | 101 | /* At one time, I was using the following in Linux. It gives a 102 | "real" precision of nanoseconds, instead of getting microseconds 103 | and multiplying by 1000 (or decimicroseconds and multiplying by 100). 104 | However, it does require the realtime library to be linked in... 105 | I leave it here in case we someday need nanosecond precision. */ 106 | 107 | #ifdef NOT_CURRENTLY_IN_USE 108 | int64_t DLL_FUNC nanoseconds_since_1970( void) 109 | { 110 | struct timespec t; 111 | 112 | clock_gettime( CLOCK_REALTIME, &t); 113 | return( t.tv_sec * (int64_t)1000000000 + t.tv_nsec); 114 | } 115 | #endif /* NOT_CURRENTLY_IN_USE */ 116 | 117 | double DLL_FUNC current_jd( void) 118 | { 119 | static const double jan_1970 = 2440587.5; 120 | const double jd = jan_1970 + 121 | (double)nanoseconds_since_1970( ) * 1e-9 / seconds_per_day; 122 | 123 | return( jd); 124 | } 125 | -------------------------------------------------------------------------------- /jsattest.cpp: -------------------------------------------------------------------------------- 1 | /* jsats.cpp: functions for Galilean satellite posns 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | 20 | /* NOTE that 'ssattest' now provides testing of Galilean satellite 21 | ephems, as well as Saturnian satellite ephems. The following 22 | program is not entirely obsolete, but it's close to it. 23 | 24 | A little test program I wrote to test out my implementation of Lieske's E5 25 | theory of the Galilean satellites, as written in 'jsats.cpp'. It works by 26 | reading in an ASCII ephemeris of Jovicentric vectors for a given satellite, 27 | computing the position for that satellite at that time using E5, and showing 28 | the difference, both as an absolute XYZ in J2000 ecliptic coordinates and 29 | in terms of "along-track" and "radial" components. The latter allowed me to 30 | see a long-term quadratic drift for Ganymede and Callisto. (They were in 31 | opposite directions, so I'm confident that it's not a situation where I've 32 | got the whole system rotating somehow. My guess is that the mean longitudes 33 | for those satellites should include a small quadratic term, instead of 34 | being just linear functions of time.) */ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #include "watdefs.h" 42 | #include "lunar.h" 43 | #include "afuncs.h" 44 | 45 | #define JRADIUS_IN_KM 71418.0 46 | // #define JRADIUS_IN_KM 71406.0 47 | 48 | int main( const int argc, const char **argv) 49 | { 50 | char buff[100]; 51 | FILE *ifile; 52 | time_t t0 = time( NULL); 53 | const int sat_number = (argc == 2 ? atoi( argv[1]) : 0); 54 | 55 | if( sat_number < 1 || sat_number > 4) 56 | { 57 | printf( "'jsattest' needs a command-line argument from 1 to 4,\n"); 58 | printf( "corresponding to the number of the Galilean satellite\n"); 59 | printf( "that is being tested.\n"); 60 | return( -1); 61 | } 62 | snprintf( buff, 7, "j%s.txt", argv[1]); 63 | ifile = fopen( buff, "rb"); 64 | if( !ifile) 65 | { 66 | printf( "%s not opened\n", buff); 67 | return( -1); 68 | } 69 | printf( "All data in kilometers, in J2000 ecliptic coords\n"); 70 | printf( "Compiled %s %s; run %.24s\n", __DATE__, __TIME__, asctime( gmtime( &t0))); 71 | printf( " JDE dx dy dz "); 72 | printf( "x y z radial along\n"); 73 | while( fgets( buff, sizeof( buff), ifile)) 74 | if( strlen( buff) > 56 && !memcmp( buff + 37, "00:00:00.0000 (CT)", 18)) 75 | { 76 | const double jd = atof( buff ); 77 | double loc[15], *tptr = loc + (sat_number - 1) * 3; 78 | double precess_matrix[9]; 79 | double j2000_loc[3], x, y, z, r; 80 | 81 | if( !fgets( buff, sizeof( buff), ifile)) 82 | { 83 | printf( "Read error"); 84 | return( -2); 85 | } 86 | x = atof( buff); 87 | y = atof( buff + 24); 88 | z = atof( buff + 47); 89 | setup_ecliptic_precession( precess_matrix, 2000. + (jd - 2451545.) / 365., 2000.); 90 | calc_jsat_loc( jd, loc, 15, 0L); 91 | precess_vector( precess_matrix, tptr, j2000_loc); 92 | j2000_loc[0] *= JRADIUS_IN_KM; 93 | j2000_loc[1] *= JRADIUS_IN_KM; 94 | j2000_loc[2] *= JRADIUS_IN_KM; 95 | j2000_loc[0] -= x; 96 | j2000_loc[1] -= y; 97 | j2000_loc[2] -= z; 98 | r = sqrt( x * x + y * y); 99 | printf( "%10.2f %10.3f%10.3f%10.3f %11.2f%11.2f%11.2f %10.2f %10.2f\n", jd, 100 | j2000_loc[0], 101 | j2000_loc[1], 102 | j2000_loc[2], x, y, z, 103 | (j2000_loc[0] * x + j2000_loc[1] * y) / r, 104 | (j2000_loc[1] * x - j2000_loc[0] * y) / r); 105 | } 106 | fclose( ifile); 107 | return( 0); 108 | } 109 | -------------------------------------------------------------------------------- /watmake: -------------------------------------------------------------------------------- 1 | # Basic astronomical functions library. Use 2 | # wmake -f watmake 3 | # to build a version that is either 32 or 64 bit; 4 | # and which either builds the library as a DLL or statically 5 | 6 | EXES= astcheck.exe astephem.exe calendar.exe cosptest.exe dist.exe & 7 | easter.exe get_test.exe htc20b.exe jd.exe jevent.exe & 8 | jpl2b32.exe jsattest.exe lun_test.exe marstime.exe oblitest.exe & 9 | persian.exe phases.exe prectest.exe ps_1996.exe & 10 | relativi.exe ssattest.exe tables.exe & 11 | testprec.exe test_ref.exe uranus1.exe utc_test.exe 12 | 13 | all: $(EXES) 14 | 15 | LIB_OBJS= ades2mpc.obj alt_az.obj astfuncs.obj big_vsop.obj & 16 | brentmin.obj cgi_func.obj classel.obj com_file.obj & 17 | conbound.obj & 18 | cospar.obj date.obj de_plan.obj delta_t.obj dist_pa.obj & 19 | eart2000.obj elp82dat.obj eop_prec.obj & 20 | getplane.obj get_time.obj jsats.obj lunar2.obj & 21 | miscell.obj moid.obj mpc_code.obj mpc_fmt.obj & 22 | mpc_fmt2.obj nanosecs.obj & 23 | nutation.obj obliquit.obj pluto.obj precess.obj & 24 | refract.obj refract4.obj rocks.obj showelem.obj sof.obj & 25 | snprintf.obj spline.obj ssats.obj triton.obj & 26 | unpack.obj vislimit.obj vsopson.obj 27 | 28 | LINK=wcl386 -zq -k10000 29 | 30 | BASE_FLAGS=-w4 -oxt -4r -s -j -zq 31 | LIBNAME=wafuncs 32 | RM=-rm 33 | 34 | !ifdef DLL 35 | COMMON_FLAGS = $(BASE_FLAGS) -EHsc -LD -DNDEBUG 36 | !else 37 | COMMON_FLAGS = $(BASE_FLAGS) 38 | !endif 39 | 40 | $(EXES) : $(LIBNAME).lib 41 | 42 | %.exe : %.obj 43 | $(LINK) $< $(LIBNAME).lib 44 | 45 | .cpp.obj: 46 | wcc386 $(COMMON_FLAGS) -za99 $< 47 | 48 | .c.obj: 49 | wcc386 $(COMMON_FLAGS) -za99 $< 50 | 51 | $(LIBNAME).lib : $(LIB_OBJS) 52 | %write wlunar.lrf $(LIB_OBJS) 53 | wlib -q -n -t $@ @wlunar.lrf 54 | $(RM) wlunar.lrf 55 | 56 | clean: 57 | $(RM) *.obj 58 | $(RM) *.exe 59 | $(RM) *.err 60 | $(RM) *.map 61 | $(RM) *.exp 62 | $(RM) $(LIBNAME).lib 63 | $(RM) $(LIBNAME).dll 64 | 65 | astcheck.exe: astcheck.obj eart2000.obj mpcorb.obj $(LIBNAME).lib 66 | $(LINK) astcheck.obj eart2000.obj mpcorb.obj $(LIBNAME).lib 67 | 68 | astephem.exe: astephem.obj eart2000.obj mpcorb.obj $(LIBNAME).lib 69 | $(LINK) astephem.obj eart2000.obj mpcorb.obj $(LIBNAME).lib 70 | 71 | calendar.exe: calendar.obj $(LIBNAME).lib 72 | $(LINK) calendar.obj $(LIBNAME).lib 73 | 74 | cosptest.exe: cosptest.obj $(LIBNAME).lib 75 | $(LINK) cosptest.obj $(LIBNAME).lib 76 | 77 | dist.exe: dist.obj 78 | $(LINK) dist.obj 79 | 80 | easter.exe: easter.cpp 81 | $(LINK) -DTEST_CODE $(BASE_FLAGS) easter.cpp 82 | 83 | get_test.exe: get_test.obj $(LIBNAME).lib 84 | $(LINK) get_test.obj $(LIBNAME).lib 85 | 86 | htc20b.exe: htc20b.cpp 87 | $(LINK) -DTEST_MAIN $(BASE_FLAGS) htc20b.cpp 88 | 89 | jevent.exe: jevent.obj $(LIBNAME).lib 90 | $(LINK) jevent.obj $(LIBNAME).lib 91 | 92 | jd.exe: jd.obj $(LIBNAME).lib 93 | $(LINK) jd.obj $(LIBNAME).lib 94 | 95 | jpl2b32.exe: jpl2b32.obj 96 | $(LINK) jpl2b32.obj 97 | 98 | jsattest.exe: jsattest.obj $(LIBNAME).lib 99 | $(LINK) jsattest.obj $(LIBNAME).lib 100 | 101 | lun_test.exe: lun_test.obj lun_tran.obj riseset3.obj $(LIBNAME).lib 102 | $(LINK) lun_test.obj lun_tran.obj riseset3.obj $(LIBNAME).lib 103 | 104 | marstime.exe: marstime.cpp 105 | $(LINK) -DTEST_PROGRAM $(BASE_FLAGS) marstime.cpp snprintf.obj 106 | 107 | oblitest.exe: oblitest.obj obliqui2.obj spline.obj $(LIBNAME).lib 108 | $(LINK) oblitest.obj obliqui2.obj spline.obj $(LIBNAME).lib 109 | 110 | persian.exe: persian.obj solseqn.obj $(LIBNAME).lib 111 | $(LINK) persian.obj solseqn.obj $(LIBNAME).lib 112 | 113 | phases.exe: phases.obj $(LIBNAME).lib 114 | $(LINK) phases.obj $(LIBNAME).lib 115 | 116 | prectest.exe: prectest.obj $(LIBNAME).lib 117 | $(LINK) prectest.obj $(LIBNAME).lib 118 | 119 | ps_1996.exe: ps_1996.obj $(LIBNAME).lib 120 | $(LINK) ps_1996.obj $(LIBNAME).lib 121 | 122 | relativi.exe: relativi.obj $(LIBNAME).lib 123 | $(LINK) relativi.obj $(LIBNAME).lib 124 | 125 | relativi.obj: 126 | wcc386 $(BASE_FLAGS) -DTEST_CODE relativi.cpp 127 | 128 | ssattest.exe: ssattest.obj $(LIBNAME).lib 129 | $(LINK) ssattest.obj $(LIBNAME).lib 130 | 131 | tables.exe: tables.obj riseset3.obj $(LIBNAME).lib 132 | $(LINK) tables.obj riseset3.obj $(LIBNAME).lib 133 | 134 | testprec.exe: testprec.obj $(LIBNAME).lib 135 | $(LINK) testprec.obj $(LIBNAME).lib 136 | 137 | test_ref.exe: test_ref.obj refract.obj refract4.obj 138 | $(LINK) test_ref.obj refract.obj refract4.obj 139 | 140 | uranus1.exe: uranus1.obj gust86.obj 141 | $(LINK) uranus1.obj gust86.obj 142 | 143 | utc_test.exe: utc_test.obj $(LIBNAME).lib 144 | $(LINK) utc_test.obj $(LIBNAME).lib 145 | -------------------------------------------------------------------------------- /mpc_time.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include "watdefs.h" 8 | #include "mpc_func.h" 9 | #include "date.h" 10 | #include "afuncs.h" 11 | 12 | /* 13 | The obsID field in ADES starts with eight mutant-hex (base 62) 14 | digits that give the time the observation was received at MPC. 15 | Mike Rudenko pointed me to 16 | 17 | https://minorplanetcenter.net/decode_obsid.py 18 | 19 | from which I learned that : 20 | 21 | The first three digits, when decoded, give the year, month, 22 | and day of submission, packed as 23 | 24 | value(0,1,2) = (year - 1800) * 12 * 31 + (month - 1) * 31 + (day-1) 25 | 26 | The next three digits, when decoded, give 27 | 28 | value(3,5) = seconds since 00:00 UT 29 | 30 | and therefore ranges from 0 to 86399 (MTX in base 62). And 31 | finally, the last two digits give 32 | 33 | value(6,7) = milliseconds 34 | 35 | and is therefore from 0 to 999 (G7 in base 62). Valid times can 36 | run from 37 | 38 | 00000000 = 1800-Jan-01 00:00:00.000 39 | zzzMTXG7 = 2440-Aug-31 23:59:59.999 40 | 41 | unless that day has a leap second (it _is_ at the end of a 42 | month, and we'll be having leap seconds monthly by then, so 43 | that will probably happen.) In that case, the scheme can be 44 | extended by one second : 45 | 46 | zzzMTYG7 = 2440-Aug-31 24:00:00.999 47 | 48 | The need to handle leap second madness may be why MPC went with 49 | this scheme, instead of the straightforward 'milliseconds since 50 | an epoch' one I'd expected. 51 | 52 | Some test cases : 53 | 54 | < Date >sb 55 | K6yCeR0100005WG401000000A 2007-10-30T13:30:35.001_00005WG4_01 56 | LP6CWP340000E5ZY010000QZe 2021-03-07T13:22:17.190_0000E5ZY_01 57 | LQBB0Q8k0000EAnd0100006Ne 2021-05-12T11:45:10.542_0000EAnd_01 58 | 59 | David Bell provided some additional info : 60 | 61 | 1-8 - ISO date to millisecond in base-62 62 | 63 | 9-16 - base62 counter that increases for each submission 64 | 65 | 17-18 - base62 sub-batch number within the main batch, usually “01” 66 | unless a single submission included multiple header blocks (different 67 | telescopes, different observers for each subbatch, etc.) 68 | 69 | 19-25 - base62 counter for the observation number within the sub-batch */ 70 | 71 | static int show_usage( void) 72 | { 73 | printf( "usage : ./mpc_time (obsID)\n" 74 | "Can be full obsID or, if you just want the submission time,\n" 75 | "supply the first eight characters of the obsID.\n"); 76 | return( -1); 77 | } 78 | 79 | int main( const int argc, const char **argv) 80 | { 81 | const char *id = (argc == 2 ? argv[1] : " "); 82 | const int ymd = get_mutant_hex_value( id, 3); 83 | const int hms = get_mutant_hex_value( id + 3, 3); 84 | const int millisec = get_mutant_hex_value( id + 6, 2); 85 | const int year = ymd / (31 * 12) + 1800; 86 | const int month = (ymd / 31) % 12 + 1; 87 | const int day = ymd % 31 + 1; 88 | const int n_days = days_in_month( month, year, CALENDAR_GREGORIAN); 89 | char buff[80]; 90 | 91 | if( argc != 2) 92 | return( show_usage( )); 93 | snprintf( buff, sizeof( buff), "%04d-%02d-%02d %02d:%02d:%02d.%03d", 94 | year, month, day, 95 | hms / 3600, (hms / 60) % 60, hms % 60, 96 | millisec); 97 | printf( "%s = JD %f\n", buff, 98 | get_time_from_string( 0., buff, FULL_CTIME_YMD, NULL)); 99 | if( strlen( id) >= 16) 100 | printf( "Submission counter: %.8s (mutant hex)\n", id + 8); 101 | if( strlen( id) >= 18) 102 | printf( "Sub-batch number within main batch counter: %.2s (mutant hex)\n", id + 16); 103 | if( strlen( id) >= 25) 104 | printf( "Observation number within the sub-batch: %.7s (mutant hex)\n", id + 18); 105 | if( day > n_days) 106 | printf( "WARNING: There are only %d days in that month\n", n_days); 107 | if( millisec >= 1000) 108 | printf( "WARNING: milliseconds should be 999 or less\n"); 109 | if( hms > 86400) /* allow for one possible leap second */ 110 | printf( "WARNING: time of day is out of range\n"); 111 | if( hms == 86400) 112 | { 113 | if( (month % 6) || day != n_days) 114 | printf( "WARNING: This is an invalid leap second. It's not on the\n" 115 | "last day of June or December.\n"); 116 | else 117 | printf( "WARNING: This is a leap second. Theoretically, it's allowed,\n" 118 | "but my code and MPC's will probably break if this submission\n" 119 | "time is used.\n"); 120 | } 121 | /* Further checking could be done. Times in the future or 122 | before the time of the actual observation should be flagged. */ 123 | return( 0); 124 | } 125 | -------------------------------------------------------------------------------- /adestest.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "mpc_func.h" 6 | #include "watdefs.h" 7 | #include "date.h" 8 | 9 | static void error_exit( ) 10 | { 11 | fprintf( stderr, 12 | "\n" 13 | "Given the name of a file containing XML or PSV ADES data as a command\n" 14 | "line argument, 'adestest' will read it and output 80-column MPC-like\n" 15 | "astrometry. This can be used to make XML ADES slightly more readable\n" 16 | "(and PSV ADES data slightly _less_ readable), but its main purpose\n" 17 | "was to let me test my code for parsing ADES data. It also serves\n" 18 | "as an example of how to use the 'ades2mpc.cpp' ADES-parsing functions.\n" 19 | "\n" 20 | "Note that the 80-column output contains various extensions to the MPC\n" 21 | "format. RA/decs are stored in decimal degrees, both to match what\n" 22 | "we get from ADES and to allow greater precision. Uncertainties (which\n" 23 | "the 80-column format knows nothing about) are stored in COM (comment)\n" 24 | "lines. Dates/times are stored in a compacted form to allow millisecond\n" 25 | "precision (the usual MPC format allows only 10^-6 day = 86.4 ms\n" 26 | "precision). The resulting '80-column data' will work with all of my\n" 27 | "tools, but probably not with anyone else's.\n" 28 | "\n" 29 | " Add a '-m' command line switch to get 'real' 80-column data, with\n" 30 | "times in decimal days and RA/decs in base-60 form.\n"); 31 | exit( -1); 32 | } 33 | 34 | void ades_artsat_desigs( void *ades_context, const bool ignore_artsat_desigs); 35 | 36 | int main( const int argc, const char **argv) 37 | { 38 | FILE *ifile; 39 | char buff[400]; 40 | void *ades_context = init_ades2mpc( ); 41 | int i, rval, show_data = 0; 42 | bool make_mpc80 = false, comments = true; 43 | 44 | if( argc < 2) 45 | { 46 | fprintf( stderr, "No file of ADES astrometry supplied on command line\n"); 47 | error_exit( ); 48 | } 49 | ifile = fopen( argv[1], "rb"); 50 | if( !ifile) 51 | { 52 | fprintf( stderr, "Couldn't open '%s' : ", argv[1]); 53 | perror( NULL); 54 | error_exit( ); 55 | } 56 | assert( ades_context); 57 | for( i = 2; i < argc; i++) 58 | if( argv[i][0] == '-') 59 | switch( argv[i][1]) 60 | { 61 | case 'd': 62 | show_data = 1; 63 | break; 64 | case 'm': 65 | make_mpc80 = true; 66 | break; 67 | case 'c': 68 | comments = false; 69 | break; 70 | case 'a': 71 | ades_artsat_desigs( ades_context, true); 72 | break; 73 | default: 74 | fprintf( stderr, "'%s' not recognized\n", argv[i]); 75 | error_exit( ); 76 | break; 77 | } 78 | while( fgets_with_ades_xlation( buff, sizeof( buff), ades_context, ifile)) 79 | { 80 | if( show_data || make_mpc80) 81 | { 82 | unsigned time_format; 83 | const double jd = extract_date_from_mpc_report( buff, &time_format); 84 | double ra, dec; 85 | 86 | if( jd) 87 | { 88 | int ra_format, dec_format; 89 | double ra_prec, dec_prec; 90 | const double PI = 3.1415926535897932384626433832795028841971693993751058209749445923; 91 | 92 | get_ra_dec_from_mpc_report( buff, &ra_format, &ra, &ra_prec, 93 | &dec_format, &dec, &dec_prec); 94 | 95 | if( show_data) 96 | printf( "MJD %f RA %f dec %f\n", jd - 2400000.5, ra, dec); 97 | if( make_mpc80) 98 | { /* switch date, RA, dec to MPC80 format */ 99 | char tbuff[40]; 100 | int format = FULL_CTIME_YMD | FULL_CTIME_LEADING_ZEROES 101 | | FULL_CTIME_MONTHS_AS_DIGITS | FULL_CTIME_FORMAT_DAY; 102 | 103 | format |= FULL_CTIME_6_PLACES; 104 | full_ctime( tbuff, jd, format); 105 | memcpy( buff + 15, tbuff, 17); 106 | if( buff[14] != 'v') 107 | { 108 | output_angle_to_buff( tbuff, ra * 12. / PI, 3); 109 | memcpy( buff + 32, tbuff, 12); 110 | output_signed_angle_to_buff( tbuff, dec * 180. / PI, 2); 111 | memcpy( buff + 44, tbuff, 12); 112 | } 113 | } 114 | } 115 | } 116 | if( comments || memcmp( buff, "COM ", 4)) 117 | printf( "%s\n", buff); 118 | } 119 | rval = free_ades2mpc_context( ades_context); 120 | fclose( ifile); 121 | printf( "rval = %d\n", rval); 122 | return( 0); 123 | } 124 | -------------------------------------------------------------------------------- /brentmin.h: -------------------------------------------------------------------------------- 1 | #ifndef BRENTMIN_H_INCLUDED 2 | #define BRENTMIN_H_INCLUDED 3 | 4 | /* brentmin.h: header file for Brent minimization without derivatives 5 | 6 | Copyright (C) 2018, Project Pluto 7 | 8 | This program is free software; you can redistribute it and/or 9 | modify it under the terms of the GNU General Public License 10 | as published by the Free Software Foundation; either version 2 11 | of the License, or (at your option) any later version. 12 | 13 | This program is distributed in the hope that it will be useful, 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 | GNU General Public License for more details. 17 | 18 | You should have received a copy of the GNU General Public License 19 | along with this program; if not, write to the Free Software 20 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 21 | 02110-1301, USA. */ 22 | 23 | #ifdef __cplusplus 24 | extern "C" { 25 | #endif /* #ifdef __cplusplus */ 26 | 27 | typedef struct 28 | { 29 | double x[5], y[5]; /* lowest values thus far */ 30 | double xmin, xmax; /* bracketing values */ 31 | double next_x; 32 | double gold_ratio; /* variable; see brentmin.cpp */ 33 | double tolerance, ytolerance; 34 | double prev_range, prev_range2; 35 | int step_type, n_iterations; 36 | } brent_min_t; 37 | 38 | void brent_min_init( brent_min_t *b, const double x1, const double y1, 39 | const double x2, const double y2, 40 | const double x3, const double y3); 41 | double brent_min_next( brent_min_t *b); 42 | int brent_min_add( brent_min_t *b, const double next_y); 43 | double fit_parabola( const double *x, const double *y, double *b, double *c); 44 | 45 | /* This is a somewhat modified version of Brent's algorithm for finding the 46 | minimum of a single-variable function. brent_min_init( ) takes three points 47 | with distinct x values, such that the middle x value has the lowest y value; 48 | i.e., it's a bracketed minimum. (The points need not be passed in any 49 | particular order). 50 | 51 | One then enters a loop wherein one calls brent_min_next( ) to get the 52 | next suggested point to check; you evaluate the function there and call 53 | brent_min_add( ) to update the algorithm. Repeat until xmax-xmin is below 54 | a desired threshhold. 55 | 56 | Brent's method combines "golden search" (a not very fast method, but 57 | with guaranteed linear convergence) and parabolic interpolation : find 58 | the quadratic fitting through the three lowest points seen thus far, and 59 | look at the point that is the minimum of that quadratic. The latter 60 | method is much faster, _if_ the function really resembles a parabola 61 | within the bracket. Some bookkeeping is required to detect cases where 62 | convergence is slow; if that happens, we switch back to the reliable 63 | golden section method for a step or two. Thus, even in worst-case 64 | scenarios, the algorithm _will_ still converge linearly. 65 | 66 | I've made the following modifications : 67 | 68 | -- This code keeps track of the _four_ lowest points and fits a _cubic_ 69 | polynomial to them, and determines a minimum from that. 70 | 71 | -- Convergence to the minimum tends to be extremely fast for sufficiently 72 | "well-behaved" functions. But even with those, you can have problems because 73 | you've reduced the (say) left-hand side of the bracket a thousandfold, but the 74 | right-hand side is as large as ever. In such cases, we're probably very close 75 | to the minimum, and don't have to go far into the larger side to find a point 76 | that is, most likely, past the maximum. This "shrink" step can easily reduce 77 | xmax-xmin a hundredfold, and more than that in the final steps where the 78 | function is effectively a parabola or cubic. 79 | 80 | At present, if the large side of the bracket is more than ten times 81 | the size of the small side of the bracket, we take a look at a point that 82 | is at xmin - (xsmall - xmin) * 3, where xmin is our minimum point and 83 | xsmall is the point at the small end of the bracket. In other words, 84 | we take the small end's size, triple it, and look that far into the 85 | larger bracket. 86 | 87 | If we're lucky (as we usually are), this drastically reduces the size 88 | of the larger side of the bracket. If not, the smaller side is tripled 89 | in size (and the larger size shrinks accordingly). 90 | 91 | This is the result of some empirical testing, and should be examined 92 | more carefully. I'd like to have something on a more solid theoretical 93 | ground. One possibility is to compute both the cubic and parabolic minima; 94 | the difference between them could be a gauge of the error to which we've 95 | determined the minimum. Or perhaps the magnitude of the leading coefficient 96 | of the cubic polynomial gives us a clue as to how far the function departs 97 | from being a parabola. 98 | */ 99 | 100 | #ifdef __cplusplus 101 | } 102 | #endif /* #ifdef __cplusplus */ 103 | #endif /* #ifndef BRENTMIN_H_INCLUDED */ 104 | -------------------------------------------------------------------------------- /text_ca2.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include "watdefs.h" 6 | #include "date.h" 7 | #include "lunar.h" 8 | 9 | /* Small program-let to generate the ASCII calendar with lunar phases 10 | shown in interactive Find_Orb when you hit 'c'. (See the file 11 | 'calendar.txt' in the Find_Orb repository.) Compile with 12 | 13 | gcc -Wextra -Wall -O3 -pedantic text_ca2.c -o text_ca2 liblunar.a -lm 14 | 15 | See 'boxize.c' in the 'junk' repo for code to turn the output from 16 | + - | dividers into Unicode box characters. 17 | 18 | make_base_line( ) will produce one of the following four lines, 19 | for line = 0, 1, 2, 3, except with the width depending on the value 20 | of 'cols'. 21 | 22 | 0: (all spaces) 23 | 1: +---------+---------+---------+---------+---------+---------+---------+ 24 | 2: | Sunday | Monday | Tuesday |Wednesday| Thursday| Friday | Saturday| 25 | 3: | | | | | | | | 26 | */ 27 | 28 | static void make_base_line( char *txt, const int cols, const int line) 29 | { 30 | int i; 31 | 32 | memset( txt, (line != 1 ? ' ' : '-'), cols * 7); 33 | txt[cols * 7 + 1] = '\0'; 34 | if( !line) 35 | return; 36 | for( i = 0; i < 8; i++) 37 | txt[i * cols] = (line != 1 ? '|' : '+'); 38 | if( line == 2) 39 | for( i = 0; i < 7; i++) 40 | { 41 | const char *days[7] = { "Sunday", "Monday", "Tuesday", "Wednesday", 42 | "Thursday", "Friday", "Saturday" }; 43 | int len = (int)strlen( days[i]); 44 | 45 | if( len > cols - 1) 46 | len = cols - 1; 47 | memcpy( txt + i * cols + (cols - len + 1) / 2, days[i], len); 48 | } 49 | } 50 | 51 | static int lines_per_week = 4; 52 | 53 | static void show_calendar( const long year, const int month, const int cols) 54 | { 55 | int i, day, n_output_lines = 4 + 5 * lines_per_week; 56 | const long jd0 = dmy_to_day( 0, month, year, CALENDAR_GREGORIAN); 57 | const int loc0 = (int)( (jd0 + 2) % 7) - 1; 58 | char **text; 59 | const char *month_names[12] = { "January", "February", "March", 60 | "April", "May", "June", "July", "August", "September", 61 | "October", "November", "December" }; 62 | 63 | text = (char **)calloc( n_output_lines, sizeof( char *)); 64 | text[0] = (char *)malloc( n_output_lines * (7 * cols + 2)); 65 | for( i = 1; i < n_output_lines; i++) 66 | text[i] = text[i - 1] + 7 * cols + 2; 67 | for( i = 0; i < 3; i++) 68 | make_base_line( text[i], cols, i); 69 | for( i = 0; i <= 5 * lines_per_week; i++) 70 | make_base_line( text[i + 3], cols, (i % lines_per_week ? 3 : 1)); 71 | for( day = days_in_month( month, year, CALENDAR_GREGORIAN); day; day--) 72 | { 73 | const unsigned col = cols * ((unsigned)(day + loc0) % 7u) + 2u; 74 | unsigned line = (unsigned)((day + loc0) / 7u) % 5u; 75 | const long t2k = (double)jd0 + (double)day - 2451545.; 76 | int phase; 77 | 78 | line = line * (unsigned)lines_per_week + 4u; 79 | if( day >= 10) 80 | text[line][col] = '0' + day / 10u; 81 | text[line][col + 1] = '0' + day % 10u; 82 | for( phase = 0; phase < 4; phase++) 83 | if( (long)( find_nearest_lunar_phase_time( phase, (long double)t2k) + .5) == t2k) 84 | { 85 | const char *phases[4] = { "New Moon", "1st Qtr", "Full Moon", "3rd Qtr" }; 86 | 87 | memcpy( text[line + 1] + col - 1, phases[phase], strlen( phases[phase])); 88 | } 89 | } 90 | sprintf( text[0] + (cols * 7 - strlen( month_names[month - 1])) / 2 - 2, 91 | "%s %ld", month_names[month - 1], year); 92 | for( i = 0; i < 4 + 5 * lines_per_week; i++) 93 | printf( "%s\n", text[i]); 94 | free( text[0]); 95 | free( text); 96 | printf( "\n"); 97 | } 98 | 99 | static void usage_exit( void) 100 | { 101 | fputs( "usage: text_ca2 year n_years [-c cols] [-l lines]\n", stderr); 102 | exit( -1); 103 | } 104 | 105 | int main( const int argc, const char **argv) 106 | { 107 | long year = (argc > 1 ? atoi( argv[1]) : 0); 108 | long n_years = (argc > 2 ? atoi( argv[2]) : 0); 109 | int cols = 11; 110 | 111 | if( !n_years || !year) 112 | usage_exit( ); 113 | for( int i = 3; i < argc - 1; i++) 114 | if( argv[i][0] == '-') 115 | { 116 | switch( argv[i][1]) 117 | { 118 | case 'l' : 119 | lines_per_week = atoi( argv[i + 1]); 120 | break; 121 | case 'c' : 122 | cols = atoi( argv[i + 1]); 123 | break; 124 | default: 125 | fprintf( stderr, "Unrecognized argument '%s'\n", argv[i]); 126 | usage_exit( ); 127 | break; 128 | } 129 | i++; 130 | } 131 | else 132 | usage_exit( ); 133 | while( n_years--) 134 | { 135 | int month; 136 | 137 | for( month = 1; month <= 12; month++) 138 | show_calendar( year, month, cols); 139 | year++; 140 | } 141 | return( 0); 142 | } 143 | -------------------------------------------------------------------------------- /lunar64.def: -------------------------------------------------------------------------------- 1 | LIBRARY lunar64 2 | EXPORTS 3 | acose @1 4 | asine @2 5 | calc_big_vsop_loc @3 6 | calc_classical_elements @4 7 | calc_dist_and_posn_ang @5 8 | calc_jsat_loc @6 9 | calc_planet_orientation @8 10 | calc_pluto_loc @9 11 | calc_ssat_loc @10 12 | calc_vsop_loc @11 13 | comet_posn @12 14 | comet_posn_and_vel @13 15 | compute_elp_xyz @14 16 | compute_extinction @15 17 | compute_limiting_mag @16 18 | compute_planet @17 19 | compute_sky_brightness @18 20 | day_to_dmy @19 21 | decipher_var_desig @20 22 | deprecess_vector @21 23 | derive_quantities @22 24 | dmy_to_day @23 25 | evaluate_rock @24 26 | extract_periodic_name @25 27 | full_alt_az_to_ra_dec @26 28 | full_ctime @27 29 | full_ra_dec_to_alt_az @28 30 | galactic_to_ra_dec @29 31 | get_chinese_intercalary_month @30 32 | ; get_comet_file @31 33 | get_ps1996_position @32 34 | green_sidereal_time @33 35 | invert_orthonormal_matrix @34 36 | j2000_to_galactic_matrix @35 37 | load_ps1996_series @36 38 | lunar_fundamentals @37 39 | lunar_lat @38 40 | lunar_lon_and_dist @39 41 | make_var_desig @40 42 | mean_obliquity @41 43 | nutation @42 44 | polar3_to_cartesian @43 45 | precess_pt @44 46 | precess_ra_dec @45 47 | precess_vector @46 48 | pre_spin_matrix @47 49 | ra_dec_to_galactic @48 50 | refraction @49 51 | reset_td_minus_dt_string @50 52 | reverse_refraction @51 53 | reverse_saasta_refraction @52 54 | rotate_vector @53 55 | saasta_refraction @54 56 | setup_ecliptic_precession @55 57 | setup_elems_from_ast_file @56 58 | setup_precession @57 59 | set_brightness_params @58 60 | set_chinese_calendar_data @59 61 | set_identity_matrix @60 62 | set_month_name @61 63 | spin_matrix @62 64 | td_minus_ut @63 65 | unload_ps1996_series @64 66 | elements_in_mpc_format @65 67 | decimal_day_to_dmy @66 68 | td_minus_utc @67 69 | j2000_to_supergalactic_matrix @68 70 | supergalactic_to_ra_dec @69 71 | ra_dec_to_supergalactic @70 72 | integrated_refraction @71 73 | reverse_integrated_refraction @72 74 | reverse_dist_and_posn_ang @73 75 | split_time @74 76 | get_time_from_string @75 77 | equatorial_to_ecliptic @76 78 | ecliptic_to_equatorial @77 79 | vector3_length @78 80 | calc_triton_loc @79 81 | vector_cross_product @80 82 | full_ctimel @81 83 | get_time_from_stringl @82 84 | setup_precession_with_nutation @83 85 | setup_precession_with_nutation_eops @84 86 | get_earth_orientation_params @85 87 | load_earth_orientation_params @86 88 | load_cospar_file @87 89 | tdb_minus_tdt @88 90 | split_timel @89 91 | set_day_of_week_name @90 92 | extract_date_from_mpc_report @91 93 | extract_sof_data @92 94 | get_mpc_code_info @93 95 | get_ra_dec_from_mpc_report @94 96 | lat_alt_to_parallax @95 97 | planet_axis_ratio @96 98 | point_to_ellipse @97 99 | is_valid_mpc_code @98 100 | byte_code_to_net_name @99 101 | net_name_to_byte_code @100 102 | create_mpc_packed_desig @101 103 | init_ades2mpc @102 104 | free_ades2mpc_context @103 105 | xlate_ades2mpc @104 106 | xlate_ades2mpc_in_place @105 107 | fgets_with_ades_xlation @106 108 | find_moid_full @107 109 | -------------------------------------------------------------------------------- /mpc_func.h: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #ifndef MPC_FUNC_H_INCLUDED 19 | #define MPC_FUNC_H_INCLUDED 20 | 21 | #ifndef DLL_FUNC 22 | #include "watdefs.h" 23 | #endif 24 | 25 | #ifdef __cplusplus 26 | extern "C" { 27 | #endif 28 | 29 | bool is_valid_mpc_code( const char *mpc_code); /* mpc_fmt.cpp */ 30 | double extract_date_from_mpc_report( const char *buff, unsigned *format); 31 | int get_ra_dec_from_mpc_report( const char *ibuff, /* mpc_fmt.cpp */ 32 | int *ra_format, double *ra, double *ra_precision, 33 | int *dec_format, double *dec, double *dec_precision); 34 | 35 | char net_name_to_byte_code( const char *net_name); 36 | const char *byte_code_to_net_name( const char byte_code); 37 | int extract_region_data_for_lat_lon( FILE *ifile, char *buff, 38 | const double lat_in_degrees, const double lon_in_degrees); 39 | 40 | typedef struct 41 | { 42 | double lat, lon; /* in radians */ 43 | double alt; /* in metres */ 44 | double rho_cos_phi, rho_sin_phi; /* in planet radii */ 45 | int planet, prec1, prec2, format; 46 | const char *name; 47 | char code[5]; 48 | } mpc_code_t; 49 | 50 | #define MPC_CODE_PARALLAXES 1 51 | #define MPC_CODE_LAT_LON_ALT 2 52 | #define MPC_CODE_SATELLITE 3 53 | 54 | int DLL_FUNC text_search_and_replace( char *str, const char *oldstr, 55 | const char *newstr); 56 | int get_mpc_code_info( mpc_code_t *cinfo, const char *buff); 57 | int get_xxx_location_info( mpc_code_t *cinfo, const char *buff); 58 | int get_lat_lon_info( mpc_code_t *cinfo, const char *buff); 59 | double get_ra_from_string( const char *buff, int *bytes_read); 60 | double get_dec_from_string( const char *buff, int *bytes_read); 61 | void output_angle_to_buff( char *obuff, double angle, int precision); 62 | void output_signed_angle_to_buff( char *obuff, const double angle, 63 | const int precision); 64 | 65 | double point_to_ellipse( const double a, const double b, 66 | const double x, const double y, double *dist); 67 | int lat_alt_to_parallax( const double lat, const double ht_in_meters, 68 | double *rho_cos_phi, double *rho_sin_phi, 69 | const double major_axis_in_meters, 70 | const double minor_axis_in_meters); /* mpc_code.cpp */ 71 | int create_mpc_packed_desig( char *packed_desig, const char *obj_name); 72 | 73 | void *init_ades2mpc( void); 74 | int xlate_ades2mpc( void *context, char *obuff, const char *buff); 75 | int xlate_ades2mpc_in_place( void *context, char *buff); 76 | int free_ades2mpc_context( void *context); 77 | int fgets_with_ades_xlation( char *buff, const size_t len, 78 | void *ades_context, FILE *ifile); 79 | int mutant_hex_char_to_int( const char c); 80 | char int_to_mutant_hex_char( const int ival); 81 | int get_mutant_hex_value( const char *buff, size_t n_digits); 82 | int encode_value_in_mutant_hex( char *buff, size_t n_digits, int value); 83 | int unpack_mpc_desig( char *obuff, const char *packed); 84 | int unpack_unaligned_mpc_desig( char *obuff, const char *packed); 85 | 86 | #define OBJ_DESIG_ASTEROID_PROVISIONAL 0 87 | #define OBJ_DESIG_ASTEROID_NUMBERED 1 88 | #define OBJ_DESIG_COMET_PROVISIONAL 2 89 | #define OBJ_DESIG_COMET_NUMBERED 3 90 | #define OBJ_DESIG_NATSAT_PROVISIONAL 4 91 | #define OBJ_DESIG_NATSAT_NUMBERED 5 92 | #define OBJ_DESIG_ARTSAT 6 93 | #define OBJ_DESIG_OTHER -1 94 | 95 | /* The offset between a satellite observation and the earth or sun 96 | is stored in a second line, as described at 97 | 98 | https://www.minorplanetcenter.net/iau/info/SatelliteObs.html 99 | 100 | These are sometimes -- nay, frequently -- mangled (decimal points 101 | in odd places, etc.) get_satellite_offset() will do its best to 102 | recover from such things, but may fail. */ 103 | 104 | #define SATELL_COORD_ERR_NO_ERROR 0 105 | #define SATELL_COORD_ERR_BAD_SIGN -1 106 | #define SATELL_COORD_ERR_BAD_NUMBER -2 107 | #define SATELL_COORD_ERR_NO_DECIMAL -3 108 | #define SATELL_COORD_ERR_DECIMAL_MISPLACED -4 109 | #define SATELL_COORD_ERR_UNKNOWN_OFFSET -5 110 | #define SATELL_COORD_ERR_EXACTLY_ZERO -6 111 | #define SATELL_COORD_ERR_INSIDE_EARTH -7 112 | 113 | #define N_SATELL_COORD_ERRORS 8 114 | 115 | int DLL_FUNC get_satellite_offset( const char *iline, double xyz[3]); 116 | 117 | #ifdef __cplusplus 118 | } 119 | #endif 120 | 121 | #endif 122 | -------------------------------------------------------------------------------- /cgicheck.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include "cgi_func.h" 22 | #include "watdefs.h" 23 | #include "stringex.h" 24 | 25 | /* Code to invoke the 'astcheck' routine from an HTML form. 26 | You'll see a _lot_ of overlap between this and 'sat_id2.cpp', 27 | the code to do satellite checking from an HTML form, and the 28 | 'fo_serve.cpp' code to run Find_Orb from an HTML form... 29 | there's a lot of recycling going on. 30 | 31 | In setting up cgicheck on your server, you'll need to make 32 | sure that 'cgicheck.htm' is present, of course, along with a copy 33 | of ObsCodes.html for parallax data. You should have either mpcorb.dat 34 | or the Lowell astorb.dat files, or both, present (note that the code 35 | expects the lowercase filenames). The results are similar with either 36 | database of orbital elements, except that 'astorb' gives you current 37 | ephemeris uncertainties. 38 | */ 39 | 40 | int astcheck_main( const int argc, const char **argv); /* astcheck.c */ 41 | 42 | int main( const int unused_argc, const char **unused_argv) 43 | { 44 | const char *argv[20]; 45 | const size_t max_buff_size = 40000; /* room for 500 obs */ 46 | char *buff; 47 | char boundary[100], field[30]; 48 | const char *temp_obs_filename = "temp_obs.txt"; 49 | int argc = 2; 50 | FILE *lock_file = fopen( "lock.txt", "w"); 51 | size_t bytes_written = 0; 52 | #ifndef _WIN32 53 | extern char **environ; 54 | #endif 55 | extern int verbose; 56 | double search_radius = 2.; /* default to looking two degrees */ 57 | 58 | INTENTIONALLY_UNUSED_PARAMETER( unused_argv); 59 | INTENTIONALLY_UNUSED_PARAMETER( unused_argc); 60 | #ifndef _WIN32 /* If things take more than 60 seconds, */ 61 | avoid_runaway_process( 60); /* assume failure and give an error msg */ 62 | #endif /* _WIN32 to that effect */ 63 | printf( "Content-type: text/html\n\n"); 64 | printf( "
\n");
 65 |    if( !lock_file)
 66 |       {
 67 |       printf( "Server is busy.  (At least as currently written,  we can only run\n");
 68 |       printf( "a single batch of observations at a time.  However,  a given batch of\n");
 69 |       printf( "observations usually doesn't take all that long... come back in\n");
 70 |       printf( "a minute or two and try again.)\n");
 71 |       printf( "
"); 72 | return( 0); 73 | } 74 | fprintf( lock_file, "We're in\n"); 75 | #ifndef _WIN32 76 | for( size_t i = 0; environ[i]; i++) 77 | fprintf( lock_file, "%s\n", environ[i]); 78 | #endif 79 | if( !fgets( boundary, sizeof( boundary), stdin)) 80 | { 81 | printf( " No info read from stdin"); 82 | printf( "This isn't supposed to happen.\n"); 83 | return( 0); 84 | } 85 | buff = (char *)malloc( max_buff_size + 100); 86 | while( get_multipart_form_data( boundary, field, buff, NULL, max_buff_size) >= 0) 87 | { 88 | if( !strcmp( field, "TextArea") || !strcmp( field, "upfile")) 89 | { 90 | if( strlen( buff) > 70) 91 | { 92 | FILE *ofile = fopen( temp_obs_filename, 93 | (bytes_written ? "ab" : "wb")); 94 | 95 | bytes_written += fwrite( buff, 1, strlen( buff), ofile); 96 | fclose( ofile); 97 | } 98 | } 99 | else if( !strcmp( field, "radius")) 100 | { 101 | const char *verbosity = strchr( buff, 'v'); 102 | 103 | search_radius = atof( buff); 104 | if( verbosity) 105 | verbose = atoi( verbosity + 1) + 1; 106 | } 107 | else if( !strcmp( field, "catalog")) 108 | { 109 | if( buff[0] == '1') /* use MPCORB */ 110 | argv[argc++] = "-M"; 111 | } 112 | else if( !strcmp( field, "uncertainties")) 113 | argv[argc++] = "-e"; 114 | else if( !strcmp( field, "unn_only")) 115 | argv[argc++] = "-u"; 116 | } 117 | free( buff); 118 | if( verbose) 119 | printf( "Searching to %f degrees; %u bytes read from input\n", 120 | search_radius, (unsigned)bytes_written); 121 | argv[0] = "cgicheck"; 122 | argv[1] = temp_obs_filename; 123 | snprintf_err( field, sizeof( field), "-r%.2f", search_radius * 3600.); /* cvt degrees to arcsec */ 124 | argv[argc++] = field; 125 | argv[argc] = NULL; 126 | astcheck_main( argc, argv); 127 | printf( "
"); 128 | return( 0); 129 | } 130 | -------------------------------------------------------------------------------- /utc_algo.cpp: -------------------------------------------------------------------------------- 1 | /* Copyright (C) 2018, Project Pluto 2 | 3 | This program is free software; you can redistribute it and/or 4 | modify it under the terms of the GNU General Public License 5 | as published by the Free Software Foundation; either version 2 6 | of the License, or (at your option) any later version. 7 | 8 | This program is distributed in the hope that it will be useful, 9 | but WITHOUT ANY WARRANTY; without even the implied warranty of 10 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 | GNU General Public License for more details. 12 | 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 16 | 02110-1301, USA. */ 17 | 18 | #include 19 | #include 20 | #include 21 | #include "watdefs.h" 22 | #include "date.h" 23 | 24 | /* Code to test a (relatively) simple, quick way to determine in which half 25 | year a given MJD falls. This is of use in 'delta_t.cpp' in figuring out 26 | guesstimates of when future leap seconds should be inserted. See the 27 | 'td_minus_utc()' function. 28 | 29 | Having been written and used to test the handling of future leap seconds, 30 | this code is really of only historical use. I'm leaving it around in order 31 | to document how this rather strange algorithm works. 32 | 33 | The basic idea is this. 400 Gregorian years will contain 400*365 "regular" 34 | days, plus 397 leap days, for a total of 146097 days. Therefore, given a 35 | number of days past "year zero", the year will be approximately 36 | 37 | year = day * 400 / 146097 38 | 39 | Note that, in what follows, the above math is promoted to 64-bit ints 40 | to avoid overflow. 1 Jan 0 (first day of the year zero) is JD 1721057.5. 41 | Round this up, and one finds that day = mjd + 2400000 - 1721058. Using 42 | this, the above formula can sometimes yield a year that is one too high 43 | for dates in late December; hence the computation of 'low' as the MJD of 44 | the corresponding year and the test to see "if( mjd < low)". 45 | 46 | So now we know what year corresponds to the given MJD. Next problem is, 47 | are we before or after 1 July of that year? To find this out, we compute 48 | the MJD for 1 January of the following year, then compute the MJD of the 49 | preceding 1 July. There can't be leap days over that span, so all we 50 | need do is to subtract 31 + 31 + 30 + 31 + 30 + 31 = 183 days to back up 51 | from 1 Jan to 1 July. 52 | 53 | We then know in which half-year we are. In the actual Delta-T code, 54 | we can then average the MJDs of the ends of that time span to get the MJD 55 | for the _middle_ of the time span, compute Delta-T at that point, and come 56 | up with a UTC offset that'll keep |UTC-UT| < .5 second; i.e., keep UTC 57 | and UT as close together as possible. 58 | 59 | This is admittedly something of a kludge. But anything done to estimate 60 | future leap seconds has to be a kludge; there's no "good" way to do it. 61 | 62 | See 'delta_t.cpp' for an explanation of the following macro. */ 63 | 64 | #define BASE_YEAR 19999999999L 65 | #define JAN_1( YEAR) (((YEAR) * 365L + ((YEAR) + BASE_YEAR) / 4L - ((YEAR) + BASE_YEAR) / 100L \ 66 | + ((YEAR) + BASE_YEAR) / 400L) - 678940L \ 67 | - ((BASE_YEAR + 1L) / 400L) * 97L) 68 | 69 | // unsigned day = mjd + 1931367u + 2400000u; 70 | // int year = (int)( day * 400u / 146097u) - 10000; 71 | 72 | int main( const int argc, const char **argv) 73 | { 74 | int mjd = atoi( argv[1]); 75 | 76 | if( argc == 2) 77 | { 78 | int day = mjd + 2400000 - 1721058; 79 | int year = (int)( (int64_t)day * (int64_t)400 / (int64_t)146097); 80 | int low, high, july_1; 81 | 82 | printf( "Year = %d\n", year); 83 | low = JAN_1( year); 84 | printf( "MJD 1 Jan %d = %ld\n", year, JAN_1( year)); 85 | if( mjd < low) 86 | { 87 | year--; 88 | low = JAN_1( year); 89 | printf( "MJD 1 Jan %d = %ld\n", year, JAN_1( year)); 90 | } 91 | high = JAN_1( year + 1); 92 | printf( "MJD 1 Jan %d = %d\n", year + 1, high); 93 | /* jul aug sep oct nov dec */ 94 | july_1 = high - (31 + 31 + 30 + 31 + 30 + 31); 95 | printf( "MJD 1 Jul %d = %d\n", year, july_1); 96 | if( mjd < july_1) 97 | printf( "In first half of %d\n", year); 98 | else 99 | printf( "In second half of %d\n", year); 100 | } 101 | else /* Test to see: over a given range of */ 102 | { /* MJDs, how often does the above year */ 103 | int n_less = 0, n_more = 0; /* determination land "spot on"? How */ 104 | /* often must we go to the next year? */ 105 | while( mjd < atoi( argv[2])) 106 | { 107 | int day = mjd + 2400000 - 1721058; 108 | int year = (int)( (int64_t)day * (int64_t)400 / (int64_t)146097); 109 | 110 | if( JAN_1( year) > mjd) 111 | n_more++; 112 | if( JAN_1( year + 1) <= mjd) 113 | n_less++; 114 | mjd++; 115 | } 116 | printf( "%d cases went over; %d went under\n", n_more, n_less); 117 | } 118 | return( 0); 119 | } 120 | -------------------------------------------------------------------------------- /mms.cpp: -------------------------------------------------------------------------------- 1 | /* Code to read in files of the form 2 | 3 | https://lasp.colorado.edu/mms/sdc/public/data/ancillary/mms1/predeph/MMS1_PREDEPH_2019155_2019171.V00 4 | 5 | and spit out ephemeris files of the sort readable by 'eph2tle' (q.v., 6 | in the Find_Orb repository). The files give times in days since 7 | 1958 Jan 1 = JD 2436204.5 TAI. TAI differs from TDT (the ephemeris 8 | time scale we actually want) by a solidly fixed 32.184 seconds. 9 | 10 | This is somewhat analogous to 'themis.cpp' (q.v.), written to 11 | produce accurate TLEs for an object where Space-Track is not entirely 12 | effectual. However, while the TLEs generated in this manner are 13 | really good and would enable us to determine which of the four MMS 14 | satellites we're looking at, the Space-Track TLEs appear to be good 15 | enough for the general problem of at least being able to say : "you 16 | got one of the four MMS sats; how much do we really care which one 17 | you got?" 18 | 19 | If we decide that _really_ matters, I'll set this up to generate 20 | TLEs for all four MMS sats, as 'themis' currently does for 21 | THEMIS-A, D, and E. But that's not a priority at present. */ 22 | 23 | #define TDT_MINUS_TAI 32.184 24 | #define JAN_1_1958 (2436204.5 + TDT_MINUS_TAI / 86400.) 25 | 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include "watdefs.h" 31 | #include "date.h" 32 | 33 | static void error_exit( const char *message) 34 | { 35 | if( message) 36 | fprintf( stderr, "%s\n", message); 37 | fprintf( stderr, "'mms' requires the name of an MMS ephemeris file as\n" 38 | "a command-line argument. Output defaults to 'mms.eph'.\n"); 39 | exit( -1); 40 | } 41 | 42 | /* I really should use getopt() or a portable variant. However, this has 43 | been sufficiently effective thus far... */ 44 | 45 | static const char *get_arg( const int argc, const char **argv, const int idx) 46 | { 47 | if( argv[idx][2] || idx == argc - 1) 48 | return( argv[idx] + 2); 49 | else 50 | return( argv[idx + 1]); 51 | } 52 | 53 | static double mms_ephem_jd( const char *buff) 54 | { 55 | if( strlen( buff) > 150 && buff[4] == '-' && buff[8] == '/' 56 | && buff[11] == ':') 57 | return( atof( buff + 23) + JAN_1_1958); 58 | else 59 | return( 0.); 60 | } 61 | 62 | int main( const int argc, const char **argv) 63 | { 64 | double jd_start = 0.; 65 | char buff[300]; 66 | FILE *ifile, *ofile = stdout; 67 | int n_lines = 0, out_freq = 72, i; 68 | int mms_number = 0; 69 | 70 | if( argc < 2) 71 | error_exit( NULL); 72 | ifile = fopen( argv[1], "rb"); 73 | if( !ifile) 74 | { 75 | fprintf( stderr, "Couldn't open '%s' ", argv[1]); 76 | perror( NULL); 77 | error_exit( NULL); 78 | } 79 | if( argc > 2 && argv[2][0] != '-') 80 | { 81 | ofile = fopen( argv[2], "wb"); 82 | if( !ifile) 83 | { 84 | fprintf( stderr, "Couldn't open '%s' ", argv[2]); 85 | perror( NULL); 86 | error_exit( NULL); 87 | } 88 | } 89 | for( i = 2; i < argc; i++) 90 | if( argv[i][0] == '-') 91 | { 92 | const char *arg = get_arg( argc, argv, i); 93 | 94 | assert( arg); 95 | switch( argv[i][1]) 96 | { 97 | case 'f': 98 | out_freq = atoi( arg); 99 | if( !out_freq || (720 % out_freq)) 100 | error_exit( "The output frequency must be a factor of 720.\n"); 101 | break; 102 | default: 103 | fprintf( stderr, "Unrecognized parameter '%s ", argv[i]); 104 | error_exit( NULL); 105 | } 106 | } 107 | while( fgets( buff, sizeof( buff), ifile)) 108 | { 109 | const double jd = mms_ephem_jd( buff); 110 | 111 | if( jd) 112 | { 113 | n_lines++; 114 | if( !jd_start) 115 | jd_start = jd; 116 | } 117 | if( !memcmp( buff, "Spacecraft = MMS", 16)) 118 | mms_number = buff[16]; 119 | } 120 | assert( mms_number >= '1' && mms_number <= '4'); 121 | fseek( ifile, 0L, SEEK_SET); 122 | /* '0,149597870.7,86400' = coords are J2000 equatorial, 123 | in km and km/s. */ 124 | fprintf( ofile, "%.6f %.6f %d 0,149597870.7,86400 (500) Geocentric: MMS%c = 2015-011%c\n", 125 | jd_start, (double)out_freq / 720., n_lines / out_freq, 126 | mms_number, mms_number + 'A' - '1'); 127 | 128 | n_lines = 0; 129 | while( fgets( buff, sizeof( buff), ifile)) 130 | { 131 | const double jd = mms_ephem_jd( buff); 132 | 133 | if( jd) 134 | { 135 | buff[184] = '\0'; 136 | if( n_lines % out_freq == 0) 137 | fprintf( ofile, "%.6f %s\n", jd, buff + 44); 138 | n_lines++; 139 | } 140 | } 141 | fclose( ifile); 142 | fprintf( ofile, "\nCreated from 'mms.cpp' (q.v.)\n"); 143 | full_ctime( buff, jd_start, CALENDAR_JULIAN_GREGORIAN); 144 | fprintf( ofile, "Ephemeris start: %s\n", buff); 145 | 146 | full_ctime( buff, jd_start + (n_lines / out_freq) * out_freq / 720., CALENDAR_JULIAN_GREGORIAN); 147 | fprintf( ofile, "Ephemeris end: %s\n", buff); 148 | if( ofile != stdout) 149 | fclose( ofile); 150 | return( 0); 151 | } 152 | -------------------------------------------------------------------------------- /lunar.def: -------------------------------------------------------------------------------- 1 | LIBRARY lunar 2 | EXPORTS 3 | acose @1 4 | asine @2 5 | calc_big_vsop_loc @3 6 | calc_classical_elements @4 7 | calc_dist_and_posn_ang @5 8 | calc_jsat_loc @6 9 | calc_planet_orientation @8 10 | calc_pluto_loc @9 11 | calc_ssat_loc @10 12 | calc_vsop_loc @11 13 | comet_posn @12 14 | comet_posn_and_vel @13 15 | compute_elp_xyz @14 16 | compute_extinction @15 17 | compute_limiting_mag @16 18 | compute_planet @17 19 | compute_sky_brightness @18 20 | day_to_dmy @19 21 | decipher_var_desig @20 22 | deprecess_vector @21 23 | derive_quantities @22 24 | dmy_to_day @23 25 | evaluate_rock @24 26 | extract_periodic_name @25 27 | full_alt_az_to_ra_dec @26 28 | full_ctime @27 29 | full_ra_dec_to_alt_az @28 30 | galactic_to_ra_dec @29 31 | get_chinese_intercalary_month @30 32 | ; get_comet_file @31 33 | get_ps1996_position @32 34 | green_sidereal_time @33 35 | invert_orthonormal_matrix @34 36 | j2000_to_galactic_matrix @35 37 | load_ps1996_series @36 38 | lunar_fundamentals @37 39 | lunar_lat @38 40 | lunar_lon_and_dist @39 41 | make_var_desig @40 42 | mean_obliquity @41 43 | nutation @42 44 | polar3_to_cartesian @43 45 | precess_pt @44 46 | precess_ra_dec @45 47 | precess_vector @46 48 | pre_spin_matrix @47 49 | ra_dec_to_galactic @48 50 | refraction @49 51 | reset_td_minus_dt_string @50 52 | reverse_refraction @51 53 | reverse_saasta_refraction @52 54 | rotate_vector @53 55 | saasta_refraction @54 56 | setup_ecliptic_precession @55 57 | setup_elems_from_ast_file @56 58 | setup_precession @57 59 | set_brightness_params @58 60 | set_chinese_calendar_data @59 61 | set_identity_matrix @60 62 | set_month_name @61 63 | spin_matrix @62 64 | td_minus_ut @63 65 | unload_ps1996_series @64 66 | elements_in_mpc_format @65 67 | decimal_day_to_dmy @66 68 | td_minus_utc @67 69 | j2000_to_supergalactic_matrix @68 70 | supergalactic_to_ra_dec @69 71 | ra_dec_to_supergalactic @70 72 | integrated_refraction @71 73 | reverse_integrated_refraction @72 74 | reverse_dist_and_posn_ang @73 75 | split_time @74 76 | get_time_from_string @75 77 | equatorial_to_ecliptic @76 78 | ecliptic_to_equatorial @77 79 | vector3_length @78 80 | calc_triton_loc @79 81 | vector_cross_product @80 82 | full_ctimel @81 83 | get_time_from_stringl @82 84 | setup_precession_with_nutation @83 85 | setup_precession_with_nutation_eops @84 86 | get_earth_orientation_params @85 87 | load_earth_orientation_params @86 88 | load_cospar_file @87 89 | tdb_minus_tdt @88 90 | split_timel @89 91 | set_day_of_week_name @90 92 | extract_date_from_mpc_report @91 93 | extract_sof_data @92 94 | get_mpc_code_info @93 95 | get_ra_dec_from_mpc_report @94 96 | lat_alt_to_parallax @95 97 | planet_axis_ratio @96 98 | point_to_ellipse @97 99 | is_valid_mpc_code @98 100 | byte_code_to_net_name @99 101 | net_name_to_byte_code @100 102 | create_mpc_packed_desig @101 103 | init_ades2mpc @102 104 | free_ades2mpc_context @103 105 | xlate_ades2mpc @104 106 | xlate_ades2mpc_in_place @105 107 | fgets_with_ades_xlation @106 108 | find_moid_full @107 109 | mutant_hex_char_to_int @108 110 | int_to_mutant_hex_char @109 111 | unpack_mpc_desig @110 112 | -------------------------------------------------------------------------------- /themis.cpp: -------------------------------------------------------------------------------- 1 | /* Code to convert THEMIS ephemerides such as those at 2 | 3 | http://soleil.ssl.berkeley.edu/ground_systems/products/THEMIS/THEMIS_D/2019_041/THEMIS_D.2019_041.OEM_CARA 4 | 5 | into the sort of state vectors that Find_Orb would emit, in preparation 6 | for making TLEs using eph2tle (see my Find_Orb repo on GitHub). 7 | 8 | The conversion is fairly straightforward. The input files give an 'object 9 | ID' equal to the NORAD catalogue number, from which we can get the international 10 | (YYYY-NNNA) designation. We get a start and stop time in Gregorian calendar form. 11 | Positions are given at one-minute intervals; we take every 'out_freq' line and 12 | output it. 13 | 14 | The resulting TLEs tend to cover about 18 days; 'them_cat' can then be 15 | used to concatenate Themis TLE sets. */ 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include "watdefs.h" 22 | #include "date.h" 23 | 24 | static void error_exit( const char *message) 25 | { 26 | if( message) 27 | fprintf( stderr, "%s\n", message); 28 | fprintf( stderr, "'themis' requires the name of a THEMIS-A, D, or E ephemeris file as\n" 29 | "a command-line argument. Output defaults to stdout.\n"); 30 | exit( -1); 31 | } 32 | 33 | /* I really should use getopt() or a portable variant. However, this has 34 | been sufficiently effective thus far... */ 35 | 36 | static const char *get_arg( const int argc, const char **argv, const int idx) 37 | { 38 | if( argv[idx][2] || idx == argc - 1) 39 | return( argv[idx] + 2); 40 | else 41 | return( argv[idx + 1]); 42 | } 43 | 44 | /* JD 2454101.5 = 2007 Jan 1. The THEMIS satellites were launched */ 45 | /* early that year. We shouldn't see ephems before this date. */ 46 | #define MIN_JD 2454101.5 47 | 48 | int main( const int argc, const char **argv) 49 | { 50 | double jd_start = 0., jd_end = 0.; 51 | char buff[200]; 52 | FILE *ifile, *ofile = stdout; 53 | int output_line = 0, norad_id = 0, out_freq = 144, i; 54 | 55 | if( argc < 2) 56 | error_exit( NULL); 57 | ifile = fopen( argv[1], "rb"); 58 | if( !ifile) 59 | { 60 | fprintf( stderr, "Couldn't open '%s' ", argv[1]); 61 | perror( NULL); 62 | error_exit( NULL); 63 | } 64 | for( i = 2; i < argc; i++) 65 | if( argv[i][0] == '-') 66 | { 67 | const char *arg = get_arg( argc, argv, i); 68 | 69 | assert( arg); 70 | switch( argv[i][1]) 71 | { 72 | case 'f': 73 | out_freq = atoi( arg); 74 | if( !out_freq || (1440 % out_freq)) 75 | error_exit( "The output frequency must be a factor of 1440.\n"); 76 | break; 77 | case 'o': 78 | ofile = fopen( arg, "wb"); 79 | if( !ofile) 80 | { 81 | fprintf( stderr, "Couldn't open '%s ", arg); 82 | perror( NULL); 83 | error_exit( NULL); 84 | } 85 | break; 86 | default: 87 | fprintf( stderr, "Unrecognized parameter '%s ", argv[i]); 88 | error_exit( NULL); 89 | } 90 | } 91 | while( fgets( buff, sizeof( buff), ifile)) 92 | { 93 | if( !memcmp( buff, "OBJECT_ID", 9)) 94 | norad_id = atoi( buff + 23); 95 | if( !memcmp( buff, "START_TIM", 9)) 96 | jd_start = get_time_from_string( 0., buff + 23, FULL_CTIME_YMD, NULL); 97 | if( !memcmp( buff, "STOP_TIME", 9)) 98 | jd_end = get_time_from_string( 0., buff + 23, FULL_CTIME_YMD, NULL); 99 | if( buff[4] == '-' && buff[7] == '-' && buff[10] == 'T' && buff[13] == ':') 100 | { 101 | if( !output_line) 102 | { 103 | int intl_letter = 0; 104 | 105 | assert( jd_start > MIN_JD); 106 | assert( jd_end > MIN_JD); 107 | assert( norad_id); 108 | if( norad_id >= 30580 && norad_id <= 30582) 109 | intl_letter = 'A' + norad_id - 30580; 110 | if( norad_id == 30797 || norad_id == 30798) 111 | intl_letter = 'D' + norad_id - 30797; 112 | assert( intl_letter); 113 | /* '-1,149597870.7,86400' = coords are mean 114 | equatorial of date, in km and km/s. */ 115 | 116 | fprintf( ofile, "%f %f %d -1,149597870.7,86400 (500) Geocentric: ", 117 | jd_start, (double)out_freq / 1440., 118 | (int)( jd_end - jd_start) * 1440 / out_freq); 119 | fprintf( ofile, "NORAD %d = 2007-004%c = THEMIS %c\n", 120 | norad_id, intl_letter, intl_letter); 121 | } 122 | if( !(output_line % out_freq)) 123 | fprintf( ofile, "%f %s", jd_start + (double)output_line / 1440., buff + 24); 124 | output_line++; 125 | } 126 | } 127 | fclose( ifile); 128 | assert( jd_start > MIN_JD); 129 | assert( jd_end > MIN_JD); 130 | fprintf( ofile, "\nCreated from 'themis.cpp' (q.v.)\n"); 131 | full_ctime( buff, jd_start, CALENDAR_JULIAN_GREGORIAN); 132 | fprintf( ofile, "Ephemeris start: %s\n", buff); 133 | 134 | full_ctime( buff, jd_end, CALENDAR_JULIAN_GREGORIAN); 135 | fprintf( ofile, "Ephemeris end: %s\n", buff); 136 | if( ofile != stdout) 137 | fclose( ofile); 138 | return( 0); 139 | } 140 | -------------------------------------------------------------------------------- /pluto.cpp: -------------------------------------------------------------------------------- 1 | /* pluto.cpp: functions for Pluto coordinates from Meeus theory 2 | 3 | Copyright (C) 2010, Project Pluto 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 18 | 02110-1301, USA. */ 19 | 20 | #include 21 | #include 22 | #include 23 | #include "watdefs.h" 24 | #include "lunar.h" 25 | 26 | #define PI 3.1415926535897932384626433832795028841971693993751058209749445923 27 | #define N_COEFFS 36 28 | #define COEFFS struct coeffs 29 | 30 | #pragma pack( 1) 31 | COEFFS 32 | { 33 | signed char j, s, p, dummy_to_maintain_alignment; 34 | int16_t lon_a, lon_b, lat_a, lat_b, rad_a, rad_b; 35 | }; 36 | #pragma pack( ) 37 | 38 | /* 39 | Lifted from p 247, Meeus, Astro Algorithms. Note that this provides 40 | excellent accuracy for years 1885-2099, but is not really intended 41 | for use outside that range. NOTE that this will fail on big-Endian 42 | machines, and on some little-Endians that require byte alignment. 43 | Let me know if you have such a machine. The fix is simple, but I'm 44 | reluctant to try it without a means of verifying that it works. */ 45 | 46 | int DLL_FUNC calc_pluto_loc( const void FAR *data, double DLLPTR *loc, 47 | const double t, const long precision) 48 | { 49 | double lat, lon, r, j, s, p, cosine, sine, arg; 50 | int i, prec = (int)precision; 51 | COEFFS FAR *tptr; 52 | int32_t FAR *long_coeffs = (int32_t FAR *)((char FAR *)data + 58610U); 53 | COEFFS FAR *coeffs = (COEFFS FAR *)(long_coeffs + 42); 54 | 55 | /* assume t in julian centuries from J2000.0 */ 56 | j = 34.35 + 3034.9057 * t; /* jupiter's mean longitude */ 57 | s = 50.08 + 1222.1138 * t; /* saturn's mean longitude */ 58 | p = 238.96 + 144.9600 * t; /* pluto's mean longitude */ 59 | j *= PI / 180.; 60 | s *= PI / 180.; 61 | p *= PI / 180.; 62 | lon = 238.956785 + 144.96 * t; 63 | lat = -3.908202; 64 | r = 407.247248; /* temporarily in tenths of AUs; fixed at the end */ 65 | for( i = 0; i < 7; i++) 66 | { 67 | int32_t FAR *ltptr; 68 | 69 | if( i == 6) 70 | arg = j - p; 71 | else 72 | arg = (double)(i + 1) * p; 73 | cosine = cos( arg) * 1.e-6; 74 | sine = sin( arg) * 1.e-6; 75 | ltptr = long_coeffs + (i * 6); 76 | lon += (double)ltptr[0] * sine + (double)ltptr[1] * cosine; 77 | lat += (double)ltptr[2] * sine + (double)ltptr[3] * cosine; 78 | r += (double)ltptr[4] * sine + (double)ltptr[5] * cosine; 79 | } 80 | tptr = coeffs; 81 | for( i = 0; i < N_COEFFS; i++, tptr++) 82 | if( abs( tptr->lon_a) > prec || abs( tptr->lon_b) > prec || 83 | abs( tptr->lat_a) > prec || abs( tptr->lat_b) > prec || 84 | abs( tptr->rad_a) > prec || abs( tptr->rad_b) > prec) 85 | { 86 | if( !tptr->j) 87 | arg = 0.; 88 | else 89 | arg = ((tptr->j == 1) ? j : j * (double)tptr->j); 90 | if( tptr->s < 0) 91 | arg -= (tptr->s == -1) ? s : s + s; 92 | if( tptr->s > 0) 93 | arg += (tptr->s == 1) ? s : s + s; 94 | if( tptr->p) 95 | arg += p * (double)tptr->p; 96 | cosine = cos( arg) * 1.e-6; 97 | sine = sin( arg) * 1.e-6; 98 | lon += sine * (double)tptr->lon_a + cosine * (double)tptr->lon_b; 99 | lat += sine * (double)tptr->lat_a + cosine * (double)tptr->lat_b; 100 | r += sine * (double)tptr->rad_a + cosine * (double)tptr->rad_b; 101 | } 102 | *loc++ = lon * PI / 180.; /* cvt to radians */ 103 | *loc++ = lat * PI / 180.; 104 | *loc++ = r / 10.; /* convert back to units of AUs */ 105 | return( 0); 106 | } 107 | 108 | #ifdef TEST_PROGRAM 109 | 110 | /* Compile as, e.g., 111 | 112 | g++ -Wall -Wextra -pedantic -DTEST_PROGRAM -o pluto pluto.cpp */ 113 | 114 | #include 115 | #include 116 | #include 117 | 118 | int main( const int argc, const char **argv) 119 | { 120 | const size_t vsop_size = 60874; 121 | FILE *ifile = fopen( "vsop.bin", "rb"); 122 | char *buff = (char *)malloc( vsop_size); 123 | 124 | INTENTIONALLY_UNUSED_PARAMETER( argv); 125 | INTENTIONALLY_UNUSED_PARAMETER( argc); 126 | assert( ifile); 127 | assert( buff); 128 | if( fread( buff, 1, vsop_size, ifile) != vsop_size) 129 | fprintf( stderr, "Wrong vsop.bin file size\n"); 130 | else 131 | { 132 | double loc[3]; 133 | double t_cen = -0.0721834360; /* 1992 Oct 13.0 TD */ 134 | 135 | calc_pluto_loc( buff, loc, t_cen, 0); 136 | printf( "Computed : %10.6f %10.6f %10.7f\n", loc[0] * 180. / PI, 137 | loc[1] * 180. / PI, loc[2]); 138 | printf( "From Meeus: 232.74009 14.58789 29.711383\n"); 139 | } 140 | free( buff); 141 | fclose( ifile); 142 | return( 0); 143 | } 144 | #endif /* #ifdef TEST_PROGRAM */ 145 | -------------------------------------------------------------------------------- /uranus1.cpp: -------------------------------------------------------------------------------- 1 | /* uranus1.cpp: test code for Uranian satellite coordinate functions, 2 | linked "normally" (compare to uranus2.cpp) 3 | 4 | Copyright (C) 2010, Project Pluto 5 | 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | 11 | This program is distributed in the hope that it will be useful, 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | GNU General Public License for more details. 15 | 16 | You should have received a copy of the GNU General Public License 17 | along with this program; if not, write to the Free Software 18 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19 | 02110-1301, USA. */ 20 | 21 | /* 22 | ** Uranus.cpp 23 | ** Functions relating to Uranus and its satellites. Written by Chris 24 | ** Marriott for SkyMap, with some modifications by me (Bill J. Gray). 25 | ** 26 | ** Created: 17-JUL-98 27 | ** 28 | ** $History: Uranus.cpp $ 29 | ** 30 | ** ***************** Version 1 ***************** 31 | ** User: Chris Date: 2/10/98 Time: 6:55 32 | ** Created in $/SkyMap 4.0 33 | ** Moved from solar system DLL into main project. 34 | ** 35 | ** ***************** Version 2 ***************** 36 | ** User: Chris Date: 18/07/98 Time: 4:49p 37 | ** Updated in $/SkyMap 4.0/SolarSys 38 | ** New file to compute data relating to Uranus and its satellites. 39 | */ 40 | 41 | #include "gust86.h" 42 | 43 | #include 44 | #include 45 | #include 46 | 47 | 48 | // UranusSatellite 49 | // Compute the positions of Uranus's satellites. 50 | 51 | #define AU_IN_KM 1.495978707e+8 52 | 53 | static void subtract_test_data( double *ivals, const int satellite, 54 | const int is_velocity) 55 | { 56 | /* Following are state vectors for all five satellites */ 57 | /* for JDE 2451539.5 = 27 Dec 1999, as given by Horizons. */ 58 | 59 | #ifdef COMPARE_TO_HORIZONS 60 | static const double test_data[60] = { 61 | /* X Y Z vx vy vz */ 62 | 130609.219205, -63609.804468, 123914.883497, 63 | 332755.476940, 19395.593811, -339740.309375, 64 | 169031.741269, -89894.366595, 186084.712454, 65 | 299664.428730, 7278.709236, -267485.829018, 66 | -270571.386731, -33418.471015, 341847.941085, 67 | 237817.716674, -102816.931847, 177706.820567, 68 | 528174.319532, -51132.708805,-242110.833416, 69 | -100437.670099, 87763.820120, -237466.213432, 70 | -128420.756530, 15056.079281, 12341.354683, 71 | 33339.723882, -163288.106059, 552424.102310 }; 72 | #else 73 | /* ...and as given by this program. If you run */ 74 | /* 'uranus1 2451539.5', you should get the following. Run */ 75 | /* 'uranus1 2451539.5 z', and the following will be subtracted */ 76 | /* from the output, and you should get all zeroes. */ 77 | static const double test_data[60] = { 78 | 130608.740570, -63609.454817, 123914.157536, 79 | 332753.924857, 19395.739133, -339739.097154, 80 | 169031.139042, -89894.351535, 186085.561827, 81 | 299665.211058, 7278.266868, -267484.726136, 82 | -270565.130051, -33419.941877, 341847.964177, 83 | 237818.078944, -102815.738968, 177702.440261, 84 | 528175.409357, -51133.015840, -242110.654650, 85 | -100437.576682, 87763.875080, -237466.804419, 86 | -128422.243906, 15056.226282, 12341.164393, 87 | 33339.740820, -163282.893418, 552432.372423 }; 88 | #endif 89 | int i; 90 | 91 | for( i = 0; i < 3; i++) 92 | { 93 | double test_value = test_data[satellite * 6 + is_velocity * 3 + i]; 94 | 95 | test_value /= AU_IN_KM; /* cvt km to AU... */ 96 | if( is_velocity) 97 | test_value /= 86400.; /* and days to seconds */ 98 | ivals[i] -= test_value; 99 | } 100 | } 101 | 102 | int main( int argc, char **argv) 103 | { 104 | const int test_differences = (argc == 1 || argc == 3); 105 | const double jde = (argc == 1 ? 2451539.5 : atof( argv[1])); 106 | int nSat; // loop counter 107 | const char *sat_names[5] = { 108 | "Ariel", "Umbriel", "Titania", "Oberon", "Miranda" }; 109 | 110 | // Process each satellite in turn. 111 | 112 | for (nSat=0; nSat<5; nSat++) 113 | { 114 | double dRect[6]; // satellite coordinates 115 | 116 | // Retrieve the coordinates of the satellite relative to the 117 | // centre of Saturn. These are equatorial coordinates for the 118 | // mean ecliptic and epoch of J2000.0. Positions in AU, 119 | // velocities in AU/second. Printed out in km and km/s. 120 | 121 | gust86_posn( jde, nSat, dRect ); 122 | if( test_differences) 123 | subtract_test_data( dRect, nSat, 0); 124 | printf( "%d %-8s: %14.6f %14.6f %14.6f\n", nSat, sat_names[nSat], 125 | dRect[0] * AU_IN_KM, 126 | dRect[1] * AU_IN_KM, 127 | dRect[2] * AU_IN_KM); 128 | if( test_differences) 129 | subtract_test_data( dRect + 3, nSat, 1); 130 | printf( " %14.6f %14.6f %14.6f\n", 131 | dRect[3] * AU_IN_KM, 132 | dRect[4] * AU_IN_KM, 133 | dRect[5] * AU_IN_KM); 134 | } 135 | return( 0); 136 | } 137 | --------------------------------------------------------------------------------