/* @(#)cextrco.c 17.1.1.1 (ESO-DMD) 01/25/02 17:40:32 */ /*=========================================================================== Copyright (C) 1995 European Southern Observatory (ESO) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Massachusetts Ave, Cambridge, MA 02139, USA. Correspondence concerning ESO-MIDAS should be addressed as follows: Internet e-mail: midas@eso.org Postal address: European Southern Observatory Data Management Division Karl-Schwarzschild-Strasse 2 D 85748 Garching bei Muenchen GERMANY ===========================================================================*/ /* ++++++++++++++++++++++++++++++++++++++++++++++++++ .COPYRIGHT: Copyright (c) 1987 European Southern Observatory, all rights reserved .LANGUAGE: C .AUTHOR: K. Banse ESO - Garching .IDENTIFICATION functions sexa2data, sexa2val, val2sexa, form_sexa, form1_sexa Convsng, Convcoo, XConvsng, XConvcoo .KEYWORDS coordinates .PURPOSE convert character coordinate string to real pixel no. of a BDF .ALGORITHM the MIDAS standard for input of coordinates is: real number = world coordinate or "@"integer number = pixel coordinate or "<" = first pixel coordinate (= 1) or ">" = last pixel coordinate the resulting pixel coordinates will be obtained according to these rules .RETURNS return status, = 0 o.k., else not o.k. .VERSIONS 2.10 increase size of internal buffers 3.00 changed from Fortran to C 2.20 930923 take out end > begin_coord check in Cextrco 001218 last modif -------------------------------------------------- */ #include #define MAXDIM 4 /* synchronize with wrldco.c */ static char subs[MAXDIM][30]; static int noax, linflag, npixls[MAXDIM]; static double starrt[MAXDIM], stepp[MAXDIM]; /* */ int sexa2data(ra,sexa_str,value,ihd,ihm,hs) int ra; /* IN: 1, if RA (=> hours are in `sexa_str'), 0, if DEC (=> degrees) */ char *sexa_str; /* IN: ab:cd:ef.gh or cd:ef.gh or ef.gh */ double *value; /* OUT: coord in decimal form (degrees) */ int *ihd; /* OUT: hours or degrees */ int *ihm; /* OUT: minutes */ double *hs; /* OUT: seconds all 3 parms above are returned as absolute values! */ { int stat, ix, iwa, minx; float rwa; double degs, mins, secs; char aux[40], *cptr; degs = mins = 0.0; cptr = sexa_str; /* point to beginning of string */ if (*cptr == '-') { minx = 1; cptr ++; } else minx = 0; ix = CGN_INDEXC(cptr,':'); if (ix == 0) return (-1); if (ix > 0) { (void) strncpy(aux,cptr,ix); aux[ix] = '\0'; if (CGN_CNVT(aux,4,1,&iwa,&rwa,°s) != 1) return (1); cptr += (ix+1); ix = CGN_INDEXC(cptr,':'); if (ix < 1) { mins = degs; degs = 0.0; } else { (void) strncpy(aux,cptr,ix); aux[ix] = '\0'; if (CGN_CNVT(aux,4,1,&iwa,&rwa,&mins) != 1) return (1); cptr += (ix+1); } } if (CGN_CNVT(cptr,4,1,&iwa,&rwa,&secs) != 1) return (1); *ihd = (int) degs; *ihm = (int) mins; *hs = secs; degs += ((mins/60.) + (secs/3600.)); if (ra == 1) degs *= 15.0; if (minx == 1) *value = -degs; else *value = degs; return (0); } /* */ int sexa2val(ra,sexa_str,value) int ra; /* IN: 1, if RA (=> hours), 0, if DEC (=> degrees) */ char *sexa_str; /* IN: ab:cd:ef.gh or cd:ef.gh or ef.gh */ double *value; /* OUT: coord in decimal form (degrees) */ { int stat, ix, iwa, minx; float rwa; double degs, mins, secs; char aux[40], *cptr; degs = mins = 0.0; cptr = sexa_str; /* point to beginning of string */ if (*cptr == ':') return (-1); if (*cptr == '-') { minx = 1; cptr ++; } else minx = 0; ix = CGN_INDEXC(cptr,':'); if (ix > 0) { (void) strncpy(aux,cptr,ix); aux[ix] = '\0'; if (CGN_CNVT(aux,4,1,&iwa,&rwa,°s) != 1) return (1); cptr += (ix+1); ix = CGN_INDEXC(cptr,':'); if (ix < 1) { mins = degs; degs = 0.0; } else { (void) strncpy(aux,cptr,ix); aux[ix] = '\0'; if (CGN_CNVT(aux,4,1,&iwa,&rwa,&mins) != 1) return (1); cptr += (ix+1); } } if (CGN_CNVT(cptr,4,1,&iwa,&rwa,&secs) != 1) return (1); degs += ((mins/60.) + (secs/3600.)); if (ra == 1) degs *= 15.0; if (minx == 1) *value = -degs; else *value = degs; return (0); } /* */ void val2sexa(ra,value,hdegs,hmins,hsecs,minflg) int ra; /* IN: 1, if Ra (=> hours), 0, if DEC (=> degrees) */ double value; /* IN: coord in decimal form (degrees) */ int *hdegs; /* OUT: hours/degrees (depends on `ra' */ int *hmins; /* OUT: minutes */ double *hsecs; /* OUT: seconds all 3 parms above are returned as absolute values! */ int *minflg; /* = 1 if value was negative, else = 0 */ { int imins, idegs; double degs, rdegs, mins, secs; if (value < 0.0) { *minflg = 1; value = -value; } else *minflg = 0; if (ra == 1) degs = value / 15.0; else degs = value; idegs = (int) degs; rdegs = (double)idegs; if (rdegs > degs) { idegs --; rdegs--; } secs = (degs - rdegs) * 3600.0; mins = secs / 60.0; imins = (int) mins; if ((double)imins > mins) imins --; /* take care of rounding... */ secs -= (double) (imins*60); *hdegs = idegs; *hmins = imins; *hsecs = secs; } /* */ void form_sexa(ra,value,sexa_str) int ra; /* IN: 1, if Ra (=> hours), 0, if DEC (=> degrees) */ double value; /* IN: coord in decimal form (degrees) */ char *sexa_str; /* OUT: ab:cd:ef.gh */ { int ix, minx, imins, idegs; double secs; char aux[16], *cptr; val2sexa(ra,value,&idegs,&imins,&secs,&minx); cptr = sexa_str; if (minx == 1) *cptr++ = '-'; (void) sprintf(cptr,"%d:%d:%2.2f",idegs,imins,secs); } /* */ int move_sxdc(direc,ra,in_str,out_str) int direc; /* IN: > 0, if from sexa -> dec string, < 0, if from dec -> sexa string */ int ra; /* IN: 1, if RA (=> hours), 0, if DEC (=> degrees) */ char *in_str; /* IN: ab:cd:ef.gh or cd:ef.gh or ef.gh <-> xy.zzzzz */ char *out_str; /* OUT: opposite of `in_str' */ { int stat; double value; if (direc > 0) { stat = sexa2val(ra,in_str,&value); if (stat == 0) (void) sprintf(out_str,"%10.8g",value); } else { int iwa; float rwa; stat = CGN_CNVT(in_str,4,1,&iwa,&rwa,&value); if (stat == 1) { form_sexa(ra,value,out_str); stat = 0; /* to have common return status */ } else stat = -1; } return stat; } /* */ void form1_sexa(ihd,ihm,hs,sexa_str) int ihd; /* IN: hours or degrees */ int ihm; /* IN: minutes */ double hs; /* IN: seconds */ char *sexa_str; /* OUT: ab:cd:ef.gh or cd:ef.gh or ef.gh */ { int minx, imins, idegs; double value, secs; char *cptr; minx = 0; if (ihd < 0) /* get absolute values */ { minx = 1; ihd = -ihd; } if (ihm < 0) { minx = 1; ihm = -ihm; } if (hs < 0.0) { minx = 1; hs = -hs; } value = (double) (ihd*3600 + ihm*60); value += hs; /* value in seconds */ cptr = sexa_str; if (minx == 1) *cptr++ = '-'; form_sexa(0,value,cptr); /* pass always positive value */ } /* */ static int Convsng(pixels) /* the static strings `subs' are used for input */ int *pixels; /* OUT: frame pixels */ { int stat, flgpix[6], k, n, iwa; float rr; double dd1[MAXDIM], dd2[MAXDIM]; char errbuf[80], pixlab[3]; for (n=0; n') /* handle ">" format */ pixels[n] = npixls[n] - 1; /* C indexing... */ else if ((subs[n][0] == 'C') || (subs[n][0] == 'c')) /* "Center" */ { if (npixls[n] > 1) pixels[n] = (npixls[n] / 2) - 1; else pixels[n] = 0; } else if (subs[n][0] == '@') /* handle "@" format */ { k = CGN_CNVT(&subs[n][1],1,1,&iwa,&rr,&dd1[n]); if (k > 0) { pixels[n] = iwa - 1; /* coord. string in Fortran notation */ if (iwa == 1) dd1[n] = starrt[n]; } else return (-3); } else { /* here we have world coordinates */ k = CGN_INDEXC(subs[n],':'); if (k > 0) /* test, if sexagesimal string */ { if (n == 0) k = 1; /* x-coord is always RA */ else k = 0; stat = sexa2val(k,subs[n],&dd1[n]); if (stat != 0) return (-3); } else { k = CGN_CNVT(subs[n],4,1,&iwa,&rr,&dd1[n]); if (k < 1) return (-3); } flgpix[n] = -1; /* remember it */ } } if (linflag == 0) /* we have non-linear coord_sys */ { for (n=0; n 0) { if (k != 2) /* 3rd dimension */ { (void) sprintf(errbuf, "Warning: non-linear WCS - mixed coordinate input might cause problems..."); SCTPUT(errbuf); } dd1[k] = starrt[k] + (pixels[k]*stepp[k]); /* approximate .. */ } } if (noax < 3) dd1[2] = starrt[2]; /* take care of art. cubes */ if (fp2wc(-1,0,dd1,dd2) != 0) /* convert wc -> fp */ return (-3); for (k=0; k 0) dd1[k] = starrt[k] + (pixels[k]*stepp[k]); /* approximate .. */ } if (noax < 3) dd1[2] = starrt[2]; /* take care of art. cubes */ if (fp2wc(-1,0,dd1,dd2) != 0) /* convert wc -> fp */ return (-3); for (k=0; k= npixls[n]) || (pixels[n] < 0) ) { pixlab[0] = 'x'; pixlab[1] = 'y'; pixlab[2] = 'z'; (void) sprintf(errbuf,"%c-pixel outside valid range ...",pixlab[n]); SCTPUT(errbuf); return (-1); } } return (0); } /* */ int Convcoo(twocoord,imno,string,pixdim,subdim,sublo,subhi) int twocoord; /* IN: 0 for single coord, 1 for interval */ int imno; /* IN: image no. if > -1, valid imno + init conversion scheme if < 0, use previous values */ char *string; /* IN: coord string in the format: either [c1,c2,c3] or c1,c2,c3 and [c1,c2,c3:d1,d2,d3] or c1,c2,c3:d1,d2,d3 */ int pixdim; /* IN: max. no. of axes wanted in subframe (1,2,3) */ int *subdim; /* OUT: dimension of subframe */ int *sublo; /* OUT: low pixels for `twocoord' = 1, the pixels for `twocoord' = 0 */ int *subhi; /* OUT: high pixels for `twocoord' = 1 */ { int bracket, begin, k, n, ls, off, newsep; char subst[80]; if (pixdim > MAXDIM) { SCTPUT("only MAXDIM dimensions supported..."); return (3); } if (string[0] == '[') bracket = 1; else bracket = 0; /* test imno + initialize conversion, if a valid image no. */ if (imno > -1) { double dd1[MAXDIM], dd2[MAXDIM]; int stat, iav, uni, nulo; stat = fp2wc(0,imno,dd1,dd2); /* prepare wc -> fp conversion */ if (stat > 0) return (stat); /* initialization gave problems */ linflag = stat; /* save linear coord_sys flag */ (void) SCDRDI(imno,"NPIX",1,MAXDIM,&iav,npixls,&uni,&nulo); starrt[2] = 0.0; /* to have a value ... */ (void) SCDRDD(imno,"START",1,MAXDIM,&iav,starrt,&uni,&nulo); (void) SCDRDD(imno,"STEP",1,MAXDIM,&iav,stepp,&uni,&nulo); } /* get substring with start coordinates */ if (twocoord == 0) { (void) strcpy(subst,&string[bracket]); if (bracket > 0) { k = CGN_INDEXC(subst,']'); subst[k] = '\0'; } else { register int nr; for (nr=(int)strlen(subst)-1; nr>0; nr--) { if (subst[nr] != ' ') { subst[nr+1] = '\0'; break; } } } } /* subst = c1,c2,c3 */ else { k = CGN_INDEXS(string,".."); if (k < 1) { newsep = 1; k = CGN_INDEXC(string,':'); } else newsep = 2; if (k < 1) { SCTPUT("invalid coord. interval ..."); return (5); } ls = k - bracket; (void) strncpy(subst,&string[bracket],ls); subst[ls] = '\0'; /* subst = c1,c2,c3 */ begin = k + newsep; /* point to end coords */ } /* isolate start coords + determine dimension of subframe */ for (n=0; n 0) noax = n + 1; else break; } *subdim = noax; if (noax == 0) goto sect_9000; k = Convsng(sublo); if (k != 0) goto sect_9090; if (twocoord == 0) return (0); /* was only one coord_pair */ /* for coord-interval, isolate substring with end coordinates */ if (bracket > 0) { ls = CGN_EXTRSS(string,156,']',&begin,subst,78); if (ls < 1) goto sect_9000; /* wrong syntax... */ } else ls = CGN_COPY(subst,&string[begin]); off = 0; for (n=0; n subhi[n]) { SCTPUT("interval start > end => empty coordinate interval ..."); return (4); } } return (0); sect_9000: SCTPUT("invalid syntax in coordinate string..."); return (1); sect_9090: return (2); } /* */ static int XConvsng(pixels) /* the static strings `subs' are used for input */ float *pixels; /* OUT: frame pixels */ { int stat, flgpix[6], k, n, iwa; float rr; double dd1[MAXDIM], dd2[MAXDIM]; char errbuf[80], pixlab[3]; for (n=0; n') /* handle ">" format */ pixels[n] = npixls[n] - 1.0; /* C indexing... */ else if ((subs[n][0] == 'C') || (subs[n][0] == 'c')) /* "Center" */ { if (npixls[n] > 1) pixels[n] = (npixls[n]/2) - 1.0; else pixels[n] = 0.0; } else if (subs[n][0] == '@') /* handle "@" format */ { k = CGN_CNVT(&subs[n][1],2,1,&iwa,&rr,&dd1[n]); if (k > 0) { pixels[n] = rr - 1.0; /* coord. string in Fortran notation */ if (CGN_NINT(rr) == 1) dd1[n] = starrt[n]; } else return (-3); } else { /* here we have world coordinates */ k = CGN_INDEXC(subs[n],':'); if (k > 0) /* test, if sexagesimal string */ { if (n == 0) k = 1; /* x-coord is always RA */ else k = 0; stat = sexa2val(k,subs[n],&dd1[n]); if (stat != 0) return (-3); } else { k = CGN_CNVT(subs[n],4,1,&iwa,&rr,&dd1[n]); if (k < 1) return (-3); } flgpix[n] = -1; /* remember it */ } } if (linflag == 0) /* we have non-linear coord_sys */ { for (n=0; n 0) { if (k != 2) /* 3rd dimension */ { (void) sprintf(errbuf, "Warning: non-linear WCS - mixed coordinate input might cause problems..."); SCTPUT(errbuf); } dd1[k] = starrt[k] + (pixels[k]*stepp[k]); /* approximate .. */ } } if (noax < 3) dd1[2] = starrt[2]; /* take care of art. cubes */ if (fp2wc(-1,0,dd1,dd2) != 0) /* convert wc -> fp */ return (-3); for (k=0; k 0) dd1[k] = starrt[k] + (pixels[k]*stepp[k]); /* approximate .. */ } if (noax < 3) dd1[2] = starrt[2]; /* take care of art. cubes */ if (fp2wc(-1,0,dd1,dd2) != 0) /* convert wc -> fp */ return (-3); for (k=0; k= npixls[n]) || (pixels[n] < 0.0) ) { pixlab[0] = 'x'; pixlab[1] = 'y'; pixlab[2] = 'z'; (void) sprintf(errbuf,"%c-pixel outside valid range ...",pixlab[n]); SCTPUT(errbuf); return (-1); } } return (0); } /* */ int XConvcoo(twocoord,imno,string,pixdim,subdim,sublo,subhi) int twocoord; /* IN: 0 for single coord, 1 for interval */ int imno; /* IN: image no. if > -1, valid imno + init conversion scheme if < 0, use previous values */ char *string; /* IN: coord string in the format: either [c1,c2,c3] or c1,c2,c3 and [c1,c2,c3:d1,d2,d3] or c1,c2,c3:d1,d2,d3 */ int pixdim; /* IN: max. no. of axes wanted in subframe (1,2,3) */ int *subdim; /* OUT: dimension of subframe */ float *sublo; /* OUT: low pixels for `twocoord' = 1, the pixels for `twocoord' = 0 */ float *subhi; /* OUT: high pixels for `twocoord' = 1 */ { int bracket, begin, k, n, ls, off, newsep; char subst[80]; if (pixdim > MAXDIM) { SCTPUT("only MAXDIM dimensions supported..."); return (3); } if (string[0] == '[') bracket = 1; else bracket = 0; /* test imno + initialize conversion, if a valid image no. */ if (imno > -1) { double dd1[MAXDIM], dd2[MAXDIM]; int stat, iav, uni, nulo; stat = fp2wc(0,imno,dd1,dd2); /* prepare wc -> fp conversion */ if (stat > 0) return (stat); /* initialization gave problems */ linflag = stat; /* save linear coord_sys flag */ (void) SCDRDI(imno,"NPIX",1,MAXDIM,&iav,npixls,&uni,&nulo); starrt[2] = 0.0; /* to have a value ... */ (void) SCDRDD(imno,"START",1,MAXDIM,&iav,starrt,&uni,&nulo); (void) SCDRDD(imno,"STEP",1,MAXDIM,&iav,stepp,&uni,&nulo); } /* get substring with start coordinates */ if (twocoord == 0) { (void) strcpy(subst,&string[bracket]); if (bracket > 0) { k = CGN_INDEXC(subst,']'); subst[k] = '\0'; } else { register int nr; for (nr=(int)strlen(subst)-1; nr>0; nr--) { if (subst[nr] != ' ') { subst[nr+1] = '\0'; break; } } } } /* subst = c1,c2,c3 */ else { k = CGN_INDEXS(string,".."); if (k < 1) { newsep = 1; k = CGN_INDEXC(string,':'); } else newsep = 2; if (k < 1) { SCTPUT("invalid coord. interval ..."); return (5); } ls = k - bracket; (void) strncpy(subst,&string[bracket],ls); subst[ls] = '\0'; /* subst = c1,c2,c3 */ begin = k + newsep; /* point to end coords */ } /* isolate start coords + determine dimension of subframe */ for (n=0; n 0) noax = n + 1; else break; } *subdim = noax; if (noax == 0) goto sect_9000; k = XConvsng(sublo); if (k != 0) goto sect_9090; if (twocoord == 0) return (0); /* was only one coord_pair */ /* for coord-interval, isolate substring with end coordinates */ if (bracket > 0) { ls = CGN_EXTRSS(string,156,']',&begin,subst,78); if (ls < 1) goto sect_9000; /* wrong syntax... */ } else ls = CGN_COPY(subst,&string[begin]); off = 0; for (n=0; n subhi[n]) { SCTPUT("interval start > end => empty coordinate interval ..."); return (4); } } return (0); sect_9000: SCTPUT("invalid syntax in coordinate string..."); return (1); sect_9090: return (2); }