/* % Integer & Long ! Single IEEE 32-bit floating-point numbers # Double @ Currency $ String */ #include #include #include /* planisphere.cpp : Defines the entry point for the console application.; */ #include "stdafx.h" void darc (FILE* dxffile, double x, double y, double r, double ang1,double ang2); void dcircle (FILE* dxffile, double x, double y, double r); void dclose( FILE* dxffile ); void dline (FILE* dxffile, double x1, double y1, double x2, double y2); void dpoint (FILE* dxffile, double x, double y); void drect (FILE* dxffile, double x1, double y1, double x2, double y2); FILE* init (FILE* dxffile, char* dxfname); int parse_yale_dat( char* string, double* r, double* d, double* m ); int main(int argc, char* argv[]) { FILE* dxffile = NULL; char dxfname[256]; double i=0.0; double x=0.0, y=0.0, dayang=0.0, ang=0.0, x1=0.0, y1=0.0; FILE* yalefile = NULL; char yalefilename[] = "yale.dat"; #define LINE_SIZE 1024 char line[LINE_SIZE]; double r=0.0, d=0.0, m=0.0, polar=0.0, ra=0.0, magn=0.0; double tand=0.0, dec=0.0; /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Draws a planisphere in three files. Lowest latitude with current grid is 37.5N. Extend the polar angle range to reach lower latitudes. Issues remaining - constellations, asterisms and star chart grids Month tick marks on the days scale The whole issue of labelling - might take me back to CorrelScript */ /* constants */ const double PI = 4.0 * atan(1.0); const double RADS = PI / 180.0; const double DEGS = 180.0 / PI; const double PHI = 52.5 * RADS; /*Alter this value for different latitudes */ const double COTPHI = 1.0 / tan(PHI); strcpy( dxfname, "grid.dxf" ); dxffile = init(dxffile, dxfname); drect(dxffile, 0.0, 0.0, 300.0, 300.0); /* azimuthal projection - plot circles centred on celestial pole spaced equally by declination - distortion near horizon... */ for( i=10.0; i<=150.0; i+=10.0 ) { /*FOR i = 10 TO 150 STEP 10; */ dcircle(dxffile, 150.0, 150.0, i); } /* NEXT i */ /*draw the RA lines */ for( i=0.0; i<= 23.0; i+=1.0 ) { /*FOR i = 0 TO 23; */ x = 150.0 * cos(15.0 * RADS * i); y = 150.0 * sin(15.0 * RADS * i); dline(dxffile, 150.0, 150.0, 150.0 + x, 150.0 + y); } /*NEXT i */ /* Now add a circle showing the days on the outer rim of the grid; */ dcircle(dxffile, 150.0, 150.0, 147.0); dayang = 360.0 / 365.25; for( i=0.0; i<= 365.25; i+=1.0 ) { /*FOR i = 0 TO 365.25; */ ang = i * dayang * RADS; x1 = 147.0 * cos(ang); y1 = 147.0 * sin(ang); x = 150.0 * cos(ang); y = 150.0 * sin(ang); dline(dxffile, 150.0 + x1, 150.0 + y1, 150.0 + x, 150.0 + y); } /*NEXT i */ /*close the grid file */ dclose(dxffile); /*print the 'stars' layer */ strcpy( dxfname, "stars.dxf" ); dxffile = init(dxffile, dxfname); /*plot a box round drawing to make PSP import work OK */ drect(dxffile, 0.0, 0.0, 300.0, 300.0); /*plot a circle same size as the base grid circumference */ dcircle(dxffile, 150.0, 150.0, 150.0); /*plot a cross in the centre of the stars layer */ dline(dxffile, 148.0, 150.0, 152.0, 150.0); dline(dxffile, 150.0, 148.0, 150.0, 152.0); /*plot 907 stars read from a file called yale.dat */ if( (yalefile = fopen( yalefilename, "r" )) == NULL ) { fprintf( stderr, "The file %s was not opened\n", yalefilename ); dclose(dxffile); exit( -1 ); } while( !feof(yalefile) ) { /* DO WHILE NOT EOF(2); */ if( fgets( line, LINE_SIZE, yalefile ) == NULL) break; if( (parse_yale_dat(line,&r,&d,&m)) != 3 ) { fprintf( stderr, "Unable to parse line '%s' from %s\n", line, yalefilename ); fprintf( stderr, "Data appears to be: r=%lf, d=%lf, m=%lf",r, d, m ); dclose(dxffile); exit( -1 ); } polar = 90.0 - d; if( polar < 145.0 ) { /*IF polar < 145.0 THEN; */ ra = r * RADS * 15.0; x = -polar * cos(ra); /*fixes flipped map problem */ y = polar * sin(ra); /*what function is best for magnitude?? */ magn = 0.5 * sqrt(5.0 - m); dcircle(dxffile, 150.0 + x, 150.0 + y, magn); } /*END IF; */ } /*LOOP; */ fclose( yalefile ); /*complete the stars file */ dclose(dxffile); /*Now draw the horizon window file */ strcpy( dxfname, "horizon.dxf" ); dxffile = init(dxffile, dxfname); /*plot a point at extreme of drawing to make PSP import work OK */ drect(dxffile, 0.0, 0.0, 300.0, 300.0); /* plot a circle same size as the plate circumference, and one to act as inner ring for hours; */ dcircle(dxffile, 150.0, 150.0, 147.0); dcircle(dxffile, 150.0, 150.0, 143.0); /*plot a cross in the centre of the plate */ dline(dxffile, 145.0, 150.0, 155.0, 150.0); dline(dxffile, 150.0, 145.0, 150.0, 155.0); /* plot line segments that outline the horizon... set up the zeroth point */ tand = COTPHI * cos(RADS * 0); dec = atan(tand); polar = 90 - dec * DEGS; x = polar * cos(RADS * 0); y = polar * sin(RADS * 0); /*calculate the rest; */ for( i=0.0; i<=360.0; i+=1.0 ) { /*FOR i = 1 TO 360; */ tand = COTPHI * cos(RADS * i); dec = atan(tand); polar = 90 - dec * DEGS; x1 = polar * cos(RADS * i); y1 = polar * sin(RADS * i); dline(dxffile, 150.0 + x, 150.0 + y, 150.0 + x1, 150.0 + y1); x = x1; y = y1; } /*NEXT i */ /* Now add a circle showing the hours from midnight This could be done in the loop above, but its easier to see what's going on having a separate one... This circle is a little smaller than the base circle */ for( i=0.0; i<=23.0; i+=1.0 ) { /*FOR i = 0 TO 23; */ ang = RADS * 15 * i; x1 = 143 * cos(ang); y1 = 143 * sin(ang); x = 147 * cos(ang); y = 147 * sin(ang); dline(dxffile, 150.0 + x1, 150.0 + y1, 150.0 + x, 150.0 + y); } /*NEXT i */ /*finish the plate */ dclose(dxffile); } /* END; */ /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++ */ /* adds arc of radius r and centre (x,y), starting at ang1 in degrees and ending at ang2 degrees to current list of entities */ void darc (FILE* dxffile, double x, double y, double r, double ang1, double ang2) { fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "ARC" ); fprintf( dxffile, "%d\n", 10 ); fprintf( dxffile, "%lf\n", x ); fprintf( dxffile, "%d\n", 20 ); fprintf( dxffile, "%lf\n", y ); fprintf( dxffile, "%d\n", 30 ); fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%d\n", 40 ); fprintf( dxffile, "%lf\n", r ); fprintf( dxffile, "%d\n", 50 ); fprintf( dxffile, "%lf\n", ang1 ); fprintf( dxffile, "%d\n", 51 ); fprintf( dxffile, "%lf\n", ang2 ); } /* adds a circle of radius r and centre (x,y) to current list of entities */ void dcircle (FILE* dxffile, double x, double y, double r) { fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "CIRCLE" ); fprintf( dxffile, "%d\n", 10 ); fprintf( dxffile, "%lf\n", x ); fprintf( dxffile, "%d\n", 20 ); fprintf( dxffile, "%lf\n", y ); fprintf( dxffile, "%d\n", 30 ); fprintf( dxffile, "%lf\n", 0 ); fprintf( dxffile, "%d\n", 40 ); fprintf( dxffile, "%lf\n", r ); } /* closes the entities list (ENDSEC) and prints the end of file code (EOF), then closes the qbasic disc file. */ void dclose( FILE* dxffile ) { fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "ENDSEC" ); fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "EOF" ); fclose( dxffile ); } /* adds a line from (x1,y1) to (x2,y2) to list of entities */ void dline (FILE* dxffile, double x1, double y1, double x2, double y2) { fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "LINE" ); fprintf( dxffile, "%d\n", 8 ); fprintf( dxffile, "%s\n", "0" ); fprintf( dxffile, "%d\n", 10 ); fprintf( dxffile, "%lf\n", x1 ); fprintf( dxffile, "%d\n", 20 ); fprintf( dxffile, "%lf\n", y1 ); fprintf( dxffile, "%d\n", 30 ); fprintf( dxffile, "%lf\n", 0.0 ); fprintf( dxffile, "%d\n", 11 ); fprintf( dxffile, "%lf\n", x2 ); fprintf( dxffile, "%d\n", 21 ); fprintf( dxffile, "%lf\n", y2 ); fprintf( dxffile, "%d\n", 31 ); fprintf( dxffile, "%lf\n", 0.0 ); } /* adds a point to entities at absolute coordinates (x,y) */ void dpoint (FILE* dxffile, double x, double y) { fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "POINT" ); fprintf( dxffile, "%d\n", 10 ); fprintf( dxffile, "%lf\n", x ); fprintf( dxffile, "%d\n", 20 ); fprintf( dxffile, "%lf\n", y ); fprintf( dxffile, "%d\n", 30 ); fprintf( dxffile, "%d\n", 0 ); } /* adds a rectangle of bottom left corner x1, y1 and top right corner x2, y2 to current list of entities */ void drect (FILE* dxffile, double x1, double y1, double x2, double y2) { dline(dxffile, x1, y1, x1, y2); dline(dxffile, x1, y2, x2, y2); dline(dxffile, x2, y2, x2, y1); dline(dxffile, x2, y1, x1, y1); }; /* opens the file and sets up the first few lines of the dxf file */ FILE* init (FILE* dxffile, char* dxfname) { if( (dxffile = fopen( dxfname, "w+" )) == NULL ) { fprintf( stderr, "The file %s was not opened\n", dxfname ); exit( -1 ); } fprintf( dxffile, "%d\n", 0 ); fprintf( dxffile, "%s\n", "SECTION" ); fprintf( dxffile, "%d\n", 2 ); fprintf( dxffile, "%s\n", "ENTITIES" ); return( dxffile ); } /* gets r, d, and m from the provided string */ int parse_yale_dat( char* string, double* r, double* d, double* m ) { int count = 0; char seps[] = " ,\n"; char *token; /* Establish string and get the first token: */ token = strtok( string, seps ); for( count=1; count<=3; count++ ) { if( token == NULL ) { return( count ); } /* assign token to parameter */ switch( count ) { case 1: sscanf(token,"%lf",r); break; case 2: sscanf(token,"%lf",d); break; case 3: sscanf(token,"%lf",m); break; } /* Get next token: */ token = strtok( NULL, seps ); } return( count-1 ); }