//--------------------------------------------------------------------------- #include "global.h" #include "novas.h" #include "cgi-draw.h" #include "sweodef.h" #include /********************************************************************/ /* *********** altaz2xy ************** purpose: convert altitude and azimuth to image X and Y coordinates. This is the main transformation formula function. input: altitude and azimuth output x and y coordinates returns 0 if the star is not within the horizon return 1 if the star is within the horizon */ long altaz2xy(double zd,double az,long *x,long *y) { double dist,ang; ang=AzimuthModel.CalcRules(az); #ifdef simple_dist dist=AltitudeModel.CalcRules(zd); #else if (ang>=0 && ang<90) dist=((90-ang)*AltModel0.CalcRules(zd)+(ang-0)*AltModel90.CalcRules(zd))/90; if (ang>=90 && ang<180) dist=((180-ang)*AltModel90.CalcRules(zd)+(ang-90)*AltModel180.CalcRules(zd))/90; if (ang>=180 && ang<270) dist=((270-ang)*AltModel180.CalcRules(zd)+(ang-180)*AltModel270.CalcRules(zd))/90; if (ang>=270 && ang<360) dist=((360-ang)*AltModel270.CalcRules(zd)+(ang-270)*AltModel0.CalcRules(zd))/90; #endif if (ang_offset!=0) ang=az+ang_offset; dist=dist*dist_coefficient; if (ang<0) ang=360+ang; /* make sure to have a non negative angle */ if (zd<90 && dist>0) /* only if the star is not beyond the horizon */ { *x=(long)(MID_X-cos((90-ang)*(3.14159265/180))*dist); *y=(long)(MID_Y-sin((90-ang)*(3.14159265/180))*dist); return(1); } return(0); } /**************************************************************** */ /* ************************* xy2altaz *************************** calculate the azimuth and altitude of a (x,y) coordinates within the picture input: altitude and azimuth input x and y coordinates, pointers to the altitude and azimuth */ double FindAngle(long x, long y) { double angle; if (x==MID_X && y==MID_Y) return(0); /* prevent an error message */ angle=atan2(MID_X-x,MID_Y-y); angle=angle*(180/3.14159265); if (angle<0) angle+=360; return(angle); } void xy2altaz(long x,long y,double *alt,double *az) { double step,angle,cur_angle,dist,cur_dist; long x1,y1,temp_x,temp_y,same_count=0; /* find the azimuth */ angle=FindAngle(x,y); *az=180; step=90; altaz2xy(40,*az,&x1,&y1); cur_angle=FindAngle(x1,y1); while (fabs(angle-cur_angle)>0.2) { if (cur_angle>angle) *az=*az-step; else *az=*az+step; step=step/2; temp_x=x1; temp_y=y1; altaz2xy(40,*az,&x1,&y1); cur_angle=FindAngle(x1,y1); if (temp_x==x1 && temp_y==y1) same_count++; /* do not enter an infinite loop */ else same_count=0; if (same_count>4) break; } /* find the altitude */ dist=pow(pow(x-MID_X,2)+pow(y-MID_Y,2),0.5); *alt=45; step=22.5; altaz2xy(*alt,*az,&x1,&y1); cur_dist=pow(pow(x1-MID_X,2)+pow(y1-MID_Y,2),0.5); while (fabs(dist-cur_dist)>0.2) { if (cur_dist4) break; } } /* **************************************************************************************** /* *************************** altaz2radec *************************** purpose: transform Alt,Az to right ascencion and declination coordinates input: location - site_info: a pointer to a site_info structure that hold the latitudes and longitudes of the site. az - double: the azimuth. alt -double: the altitude. output: RA - double: the computed right ascention. DEC - double: the computed declination. */ void altaz2radec(site_info *location,double alt, double az, double *RA, double *DEC) { double cosRA,sinDEC; if (az==180) az=180.1; /* prevent an error */ sinDEC=cos(az*DEGTORAD)*cos(alt*DEGTORAD)*cos(location->latitude*DEGTORAD)+sin(alt*DEGTORAD)*sin(location->latitude*DEGTORAD); *DEC=asin(sinDEC); cosRA=(sin(alt*DEGTORAD)-sin(*DEC)*sin(location->latitude*DEGTORAD))/(cos(*DEC)*cos(location->latitude*DEGTORAD)); *RA=RADTODEG*acos(cosRA); if (sin(DEGTORAD*az)>0) *RA=360-*RA; *RA=julian2sidereal(current_date,location)-(*RA/15); if (*RA<0) *RA=*RA+24; *DEC=(RADTODEG*(*DEC)); } /******************************************************************************************/ /* ************************************** GetFileDate *********************************** */ /* purpose: returns the julian date by the file's name input: filename - string: the fits image file name. output: double: julian date as indicated by the file's name. e.g. wo21213ut457654.fits */ double GetFileDate(char *filename) { short year,month,day,a; double hour; char buffer[10]; if (strrchr(filename,'/')) filename=strrchr(filename,'/')+1; /* ignore the directory path */ for (a=0;a<10;a++) buffer[a]='\0'; /* clear the buffer */ if (strlen(filename)<16) return(0); /* julian date could not be extracted from the file's name */ /* get the year */ strncpy(buffer,&(filename[2]),2); /* copy the year */ year=(short)atoi(buffer); /* convert to integer */ if (year==0) return(0); /* failed to extract the year */ /* get the month */ strncpy(buffer,&(filename[4]),2); /* copy the month */ month=(short)atoi(buffer); /* convert to integer */ if (month==0) return(0); /* failed to extract the month */ /* get the day */ strncpy(buffer,&(filename[6]),2); /* copy the day */ day=(short)atoi(buffer); /* convert to integer */ if (day==0) return(0); /* failed to extract the day */ /* get the hours */ strncpy(buffer,&filename[10],2); /* copy the hour */ a=(short)atoi(buffer); /* convert to integer */ hour=a; /* add the the hour to the sum */ /* get the minutes */ strncpy(buffer,&filename[12],2); /* copy the minutes */ a=(short)atoi(buffer); /* convert to integer */ hour=hour+((double)a/(60)); /* add the minutes to the sum */ /* get the seconds */ strncpy(buffer,&filename[14],2); /* copy the seconds */ a=(short)atoi(buffer); /* convert to integer */ hour=hour+((double)a/(60*60)); /* add the seconds to the sum */ return(julian_date(year+2000,month,day,hour)); } /****************************************************** /* ****************** GetDate ********************** */ /* purpose: form a standard date using julian date */ /* input - jdt: julian date to be converted buffer: a pre-allocated memory buffer for the result. comments - the size of the buffer should be at least 30 bytes. the function does not perform any memory checkings. */ void GetDate(double jdt, char *buffer) { short year,month,day,hour,minute,second; double time; cal_date(jdt,&year,&month,&day,&time); hour=(short)(time); time=time-((double)hour); minute=(short)(time*60); time=time-((double)minute/(60)); second=(short)(time*60*60)+1; if (second>=60) { second=0; minute=minute+1; } if (minute>=60) { minute=0; hour=hour+1; } sprintf(buffer,"%d/%02d/%02d %02d:%02d:%02dUT",year,month,day,hour,minute,second); } /* *********************************************************************** /* **************************** Draw_RA_DEC ****************************** purpose: draw the RA and DEC lines on the bitmap. inputs: hBitmap - the bitmap to draw on location - the location where the image was taken tjd - julian date when the image was taken output: integer - 1 if succeeded. 0 if failed. */ int Draw_RA_DEC(BITMAP hBitmap, site_info *location, double tjd,FONT font) { double ra,dec,zd,az,rar,decr; double middle_ra,middle_ra_min_dist=10000; /* these variables are used for finding the RA line to write the DEC along it */ long x,y,last_x,last_y,res; unsigned char line_color[10],eq_color[10],*color; char label[20]; /* a buffer for the label to be printed */ /* set the color styles */ cd_setstyle(line_color,255,255,255,255,255,255,1,0); cd_setstyle(eq_color,0,0,255,255,255,255,1,0); /* draw right ascension lines */ ra=0; while (ra<24) { short first_drawn=0; dec=88; while (dec>-90) { equ2hor(tjd,DELTA_T,0,0,location,ra,dec,0,&zd,&az,&rar,&decr); res=altaz2xy(90-zd,az,&x,&y); if (res==1) { if (dec==0) /* draw the labels of the RA */ { sprintf(label,"%.0f",ra); /* convert the RA from double to string */ cd_drawtext(hBitmap,font,x+5,y-15,line_color,label,NO,NO,NO); /* draw the RA label */ if (fabs(x-MID_X)longitude)/360.0)*24.0; if (gst<0) gst=24+gst; if (gst>=24) gst=gst-24; return(gst); } /* ***************************************************************** /* ************************ FindClosestFile ************************ Find the fits image that its sidereal time is closest to filename /* purpose: find the text file with the peak information that is closest to the sidereal time of the file specified by "filename" parameter. input: filename: string: the name of the image that a clear image file is required for. targetfile: string: the output parameter. the name of the closest file that was found in the directory. output: a pointer to the string buffer "targetfile". comments: the function assumes the existence of a "dircont" file which contains the content of the directorie's files. this file is usually obtained by the command line "ls > content". */ char *FindClosestFile(char *filename,site_info *location,char *targetfile) { double sdt,tjd,min_dist; FILE *filenames_file; char image_name[200],closest_image_name[200],*base_file,all_files[32000],*p_all_files; long n; /* get only the file name - without the path */ if (strrchr(filename,'/')) strcpy(image_name,&(strrchr(filename,'/')[1])); else strcpy(image_name,filename); tjd=GetFileDate(image_name); sdt=julian2sidereal(tjd,location); /* get the fits image's sidereal time */ /* get all the files in the directory */ filenames_file=fopen("../data/clear/dircont","r"); /* open the file that is the output file of dir/b or ls */ if (!filenames_file) { printf("can not open file '../data/clear/dircont'\n"); return(NULL); } n=fread(all_files,1,sizeof(all_files),filenames_file); fclose(filenames_file); all_files[n]='\0'; p_all_files=strtok(all_files," \n"); /* now search all the files in the file */ min_dist=1000000; /* min_dist <- oo */ strcpy(closest_image_name,""); while (p_all_files) { if (strlen(p_all_files)>=22 && strstr(p_all_files,"p.fits")) /* verify it is a "normal" fits image */ { double image_sdt=-10000; /* initizlize so it won't get zero if the calculation fails */ tjd=GetFileDate(p_all_files); image_sdt=julian2sidereal(tjd,location); /* get the fits image's sidereal time */ if (fabs(image_sdt-sdt)3.0/60.0) return(NULL); /* no good file could be found (3 minutes difference at the most) */ return(strcpy(targetfile,closest_image_name)); } /* *************************************************************************** /* **************************** DrawStaticLabels ***************************** purpose: put the static labels on the image (observatory, time, etc...) inputs: bitmap - the bitmap to draw on input_image - the name of the input image file resize - the resizing amount (in percents) of the output image (the "S" switch value of the command line). observatroy - the index of the observatory. output: integer - 1 if succeeded. 0 if failed. */ int DrawStaticLabels(BITMAP bitmap, char *input_image, long resize,double exposure_time) { FONT font; long color,labelxpos; FILE *file; /* for opening the font */ unsigned char white_style[10]; char buffer[200]; /* load the fonts */ if (resize<15) return(0); /* do not write labels on very small images */ file=fopen("fonts/courierb14.bfnt","r"); if (!file) { printf("Could not open font file 'fonts/courier14.bfnt'\n"); /* font's file could not be open */ return(0); } font=cd_loadfont(file); fclose(file); cd_font_height[font]=12; color=current_location.color; cd_setstyle(white_style,(unsigned char)((color & 0x00FF0000)>> 16),(unsigned char)((color & 0x0000FF00) >> 8),(unsigned char)(color & 0x000000FF),255,255,255,1,0); /* white font color - for image name, time etc... */ /* draw the image name, time etc... */ // cd_drawtext(bitmap,font,10,cd_bitmapheight[bitmap]-40,white_style,input_image,NO,NO,NO); /* draw the image file name */ GetDate(current_date,buffer); if (strchr(buffer,' ')) *strchr(buffer,' ')='\n'; if (exposure_time>0) sprintf(buffer,"%s + %.0fS",buffer,exposure_time); /* add the exposure time of the picture */ cd_drawtext(bitmap,font,10,cd_bitmapheight[bitmap]-(cd_font_height[font]*2+10),white_style,buffer,NO,NO,NO); /* draw the date */ // GetObservatoryName(input_image,buffer); strcpy(buffer,current_location.name); cd_drawtext(bitmap,font,10,10,white_style,buffer,NO,NO,NO); /* draw the observatory name */ strcpy(buffer,"NightSkyLive.net"); cd_drawtext(bitmap,font,cd_bitmapwidth[bitmap]-140,10,white_style,buffer,NO,NO,NO); /* draw the "CONCAM" label */ strcpy(buffer,"NSF/NASA\nMichigan Tech"); labelxpos=120; cd_drawtext(bitmap,font,cd_bitmapwidth[bitmap]-labelxpos,cd_bitmapheight[bitmap]-(cd_font_height[font]*2+10),white_style,buffer,NO,NO,NO); /* draw the "NSF/NASA" label */ /* draw north east south and west labels */ cd_drawtext(bitmap,font,cd_bitmapwidth[bitmap]/2,10,white_style,"N",NO,NO,NO);/* draw the "north" label */ cd_drawtext(bitmap,font,cd_bitmapwidth[bitmap]/2,cd_bitmapheight[bitmap]-(cd_font_height[font]+10),white_style,"S",NO,NO,NO);/* draw the "south" label */ cd_drawtext(bitmap,font,10,cd_bitmapheight[bitmap]/2,white_style,"E",NO,NO,NO);/* draw the "east" label */ cd_drawtext(bitmap,font,cd_bitmapwidth[bitmap]-20,cd_bitmapheight[bitmap]/2,white_style,"W",NO,NO,NO);/* draw the "west" label */ return(1); } /* ******************************************************************** *********************** LoadObservatory **************************** purpose: load observatory (location) information from an external file. */ short LoadObservatory() { FILE *info_file; char line[256],*p_line; info_file=fopen("location","r"); if (!info_file) return(0); /* info file does not exist */ p_line=fgets(line,256,info_file); while (p_line) { p_line=strtok(p_line," =\n\t"); if (strcasecmp(p_line,"zenith_x")==0) locations[CUSTOM].MID_X=atoi(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"zenith_y")==0) locations[CUSTOM].MID_Y=atoi(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"latitude")==0) locations[CUSTOM].latitude=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"longitude")==0) locations[CUSTOM].longitude=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"height")==0) locations[CUSTOM].height=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"temperature")==0) locations[CUSTOM].temperature=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"pressure")==0) locations[CUSTOM].pressure=atoi(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"ang_offset")==0) locations[CUSTOM].ang_offset=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"dist_coefficient")==0) locations[CUSTOM].dist_coefficient=atof(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"color")==0) locations[CUSTOM].color=atoi(strtok(NULL," =\n\t")); if (strcasecmp(p_line,"name")==0) strcpy(locations[CUSTOM].name,strtok(NULL," =\n\t")); p_line=fgets(line,256,info_file); } fclose(info_file); printf("observatory information loaded from 'location' file\n"); return(1); } /* ******************************************************************** /* **************************** ShowHelp ****************************** purpose: print a short help manual to the default output stream */ void ShowHelp() { printf("\n-d: detect \"unexpected\" object but only draw star labels.\n"); printf("-m: draw stars labels.\n"); printf("-w: draw label on the target image without changing its content.\n"); printf("-i: use inverted images (white sky and black stars).\n"); printf("-c: draw constellations lines.\n"); printf("-t: generate photometry files.\n"); printf("-v: draw visibility levels.\n"); printf("-l: draw RA and DEC lines.\n"); printf("-h: show these lines.\n"); printf("-xN: set the center of the input image N pixels left (use negative N for moving right).\n"); printf("-yN: set the center of the input image N pixels down (use negative N for moving up).\n"); printf("-rN: draw the labels N pixels right of its position.\n "); printf("-bN: draw the label N pixels below its position.\n"); printf("-fFILENAME: draw objects from an extrenal file FILENAME.\n"); printf("-qN: set quality of the output image (0-100)\n"); printf("-sN: set size of the output image (0-100)\n"); printf("-g: Create a background fits image\n"); printf("-e: Create a image of emissivity map\n"); printf("-u: create photometry files for stars\n"); printf("-pN: unwrap the fisheye image. N - scale of the output image (1=normal size)\n"); printf("\nsupported observatories:\nwo - Wise\nrh - Rosemary Hill\nmw - Mt. Wilson\nmk - Mauna Kea\nci - Canary Island\nkp - Kitt Peak\nsd - Siding Spring\nsa - South Africa\nhl - Haleakala\ncp - Cerro Pachon\nsb - Sde Boker\nha - Hanle\n"); printf("\nFor observatories and locations that are not supported, edit a 'location' file and put it in wolf directory\n"); }