// Copyright (C) 1999-2018 // Smithsonian Astrophysical Observatory, Cambridge, MA, USA // For conditions of distribution and use, see copyright notice in "copyright" #include <fstream> #include "fdstream.hpp" #include <libxml/xmlreader.h> #include "context.h" #include "framebase.h" #include "fitsimage.h" static int xmlRead (void * context, char * buffer, int len) { istream* str=(istream*)context; str->read(buffer,len); return str->gcount(); } static int xmlClose (void * context) { return 1; } void Base::xmlParse(istream& str) { xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, (void*)(&str), "", NULL, 0); if (!reader) { cerr << "Unable to create xmlReader" << endl; return; } char** cols=NULL; int colcnt=0; int id[128]; char* unit[128]; char* ref[128]; char* axis[128]; char* dir[128]; for (int ii=0; ii<128; ii++) { id[ii]=0; unit[ii]=NULL; ref[ii]=NULL; axis[ii] =NULL; dir[ii]=NULL; } int cnt=0; int state=0; int ret = xmlTextReaderRead(reader); while (ret == 1) { int nodeType = xmlTextReaderNodeType(reader); char* key = (char*)xmlTextReaderConstName(reader); if (!strncmp(key,"VOTABLE",7) && (nodeType==1)) { } else if (!strncmp(key,"VOTABLE",7) && (nodeType==15)) { } else if (!strncmp(key,"DEFINITIONS",11) && (nodeType==1)) { } else if (!strncmp(key,"DEFINITIONS",11) && (nodeType==15)) { } else if (!strncmp(key,"COOSYS",6) && (nodeType==1)) { } else if (!strncmp(key,"COOSYS",6) && (nodeType==15)) { } else if (!strncmp(key,"RESOURCE",8) && (nodeType==1)) { } else if (!strncmp(key,"RESOURCE",8) && (nodeType==15)) { } else if (!strncmp(key,"TABLE",5) && (nodeType==1)) { } else if (!strncmp(key,"TABLE",5) && (nodeType==15)) { } else if (!strncmp(key,"FIELD",5) && (nodeType==1)) { xmlParseFIELD(reader,id,unit,ref,axis,dir,colcnt); state = 2; colcnt++; } else if (!strncmp(key,"FIELD",5) && (nodeType==15)) { state = 0; } else if (!strncmp(key,"DATA",4) && (nodeType==1)) { state = 0; } else if (!strncmp(key,"DATA",4) && (nodeType==15)) { } else if (!strncmp(key,"TABLEDATA",9) && (nodeType==1)) { state = 0; } else if (!strncmp(key,"TABLEDATA",9) && (nodeType==15)) { } else if (!strncmp(key,"TR",2) && (nodeType==1)) { if (cols) { for (int ii=0; ii<colcnt; ii++) if (cols[ii]) delete [] cols[ii]; delete [] cols; } cols = new char*[colcnt]; for (int ii=0; ii<colcnt; ii++) cols[ii] = NULL; cnt=0; } else if(!strncmp(key,"TR",2) && (nodeType==15)) { xmlParseTR(cols,id,unit,ref,axis,dir,colcnt); } else if (!strncmp(key,"TD",2) && (nodeType==1)) { state=1; } else if (!strncmp(key,"TD",2) && (nodeType==15)) { state=0; cnt++; } else if (!strncmp(key,"#text",5) && (nodeType==3)) { switch (state) { case 0: break; case 1: // td cols[cnt] = dupstr((char*)xmlTextReaderConstValue(reader)); break; case 2: // field break; } } ret = xmlTextReaderRead(reader); } xmlFreeTextReader(reader); if (ret != 0) cerr << "Failed to parse xml" << endl; xmlCleanupParser(); xmlMemoryDump(); if (cols) { for (int ii=0; ii<colcnt; ii++) if (cols[ii]) delete [] cols[ii]; delete [] cols; } for (int ii=0; ii<128; ii++) { if (unit[ii]) delete unit[ii]; if (ref[ii]) delete ref[ii]; if (axis[ii]) delete axis[ii]; if (dir[ii]) delete dir[ii]; } } void Base::xmlParseFIELD(void* rr, int* id, char** unit, char** ref, char** axis, char** dir, int colcnt) { xmlTextReaderPtr reader = (xmlTextReaderPtr)rr; char* colname = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("name")); if (!colname) colname = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("NAME")); if (!colname) return; if (STRCMP(colname,"shape",5)) id[colcnt] = XMLSHAPE; else if (STRCMP(colname,"x",1)) id[colcnt] = XMLX; else if (STRCMP(colname,"y",1)) id[colcnt] = XMLY; else if (STRCMP(colname,"xv",2)) id[colcnt] = XMLXV; else if (STRCMP(colname,"yv",2)) id[colcnt] = XMLYV; else if (STRCMP(colname,"r",1)) id[colcnt] = XMLR; else if (STRCMP(colname,"r2",2)) id[colcnt] = XMLR2; else if (STRCMP(colname,"rv",2)) id[colcnt] = XMLRV; else if (STRCMP(colname,"rv2",3)) id[colcnt] = XMLRV2; else if (STRCMP(colname,"ang",3)) id[colcnt] = XMLANG; else if (STRCMP(colname,"angv",4)) id[colcnt] = XMLANGV; else if (STRCMP(colname,"tile",4)) id[colcnt] = XMLTILE; else if (STRCMP(colname,"color",5)) id[colcnt] = XMLCOLOR; else if (STRCMP(colname,"width",5)) id[colcnt] = XMLWIDTH; else if (STRCMP(colname,"text",4)) id[colcnt] = XMLTEXT; else if (STRCMP(colname,"font",4)) id[colcnt] = XMLFONT; else if (STRCMP(colname,"select",6)) id[colcnt] = XMLSELECT; else if (STRCMP(colname,"highlite",8)) id[colcnt] = XMLHIGHLITE; else if (STRCMP(colname,"edit",4)) id[colcnt] = XMLEDIT; else if (STRCMP(colname,"move",4)) id[colcnt] = XMLMOVE; else if (STRCMP(colname,"rotate",6)) id[colcnt] = XMLROTATE; else if (STRCMP(colname,"delete",6)) id[colcnt] = XMLDELETE; else if (STRCMP(colname,"fixed",5)) id[colcnt] = XMLFIXED; else if (STRCMP(colname,"include",7)) id[colcnt] = XMLINCLUDE; else if (STRCMP(colname,"source",6)) id[colcnt] = XMLSOURCE; else if (STRCMP(colname,"dash",4)) id[colcnt] = XMLDASH; else if (STRCMP(colname,"dashlist",8)) id[colcnt] = XMLDASHLIST; else if (STRCMP(colname,"tag",3)) id[colcnt] = XMLTAG; else if (STRCMP(colname,"param",5)) id[colcnt] = XMLPARAM; else if (STRCMP(colname,"param2",6)) id[colcnt] = XMLPARAM2; else if (STRCMP(colname,"param3",6)) id[colcnt] = XMLPARAM3; else if (STRCMP(colname,"param4",6)) id[colcnt] = XMLPARAM4; else if (STRCMP(colname,"param5",6)) id[colcnt] = XMLPARAM5; else if (STRCMP(colname,"comment",7)) id[colcnt] = XMLCOMMENT; unit[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("unit")); if (!unit[colcnt]) unit[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("UNIT")); ref[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("ref")); if (!ref[colcnt]) ref[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("REF")); axis[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("axis")); if (!axis[colcnt]) axis[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("AXIS")); dir[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("dir")); if (!dir[colcnt]) dir[colcnt] = (char*)xmlTextReaderGetAttribute(reader,(const xmlChar*)("DIR")); if (colname) free(colname); } void Base::xmlParseTR(char** cols, int* id, char** unit, char** ref, char** axis, char**dir, int colcnt) { // init region char* shape =NULL; char shapedef[] = "point"; shape = shapedef; // x,y char* x =NULL; char xdef[] = "0"; x = xdef; char* y =NULL; char ydef[] = "0"; y = ydef; Coord::CoordSystem sys =Coord::PHYSICAL; Coord::SkyFrame sky =Coord::FK5; Coord::SkyFormat format =Coord::DEGREES; // xv,yv char* xv =NULL; char xvdef[] = "0"; xv = xvdef; char* yv =NULL; char yvdef[] = "0"; yv = yvdef; Coord::CoordSystem vsys =Coord::PHYSICAL; Coord::SkyFrame vsky =Coord::FK5; Coord::SkyFormat vformat =Coord::DEGREES; // r,r2 char* r =NULL; char rdef[] = "0"; r = rdef; char* r2 =NULL; char r2def[] = "0"; r2 = r2def; Coord::CoordSystem rsys =Coord::PHYSICAL; Coord::SkyFrame rsky =Coord::FK5; Coord::DistFormat rdist =Coord::ARCMIN; // rv,rv2 char* rv =NULL; char rvdef[] = "0"; rv = rvdef; char* rv2 =NULL; char rv2def[] = "0"; rv2 = rv2def; Coord::CoordSystem rvsys =Coord::PHYSICAL; Coord::SkyFrame rvsky =Coord::FK5; Coord::DistFormat rvdist =Coord::ARCMIN; // ang char* ang =NULL; char angdef[] = "0"; ang = angdef; Coord::AngleFormat angformat =Coord::DEG; Coord::CoordSystem angsys =Coord::PHYSICAL; Coord::SkyFrame angsky =Coord::FK5; int angsign =1; double angoffset =0; // angv char* angv =NULL; char angvdef[] = "0"; angv = angvdef; Coord::AngleFormat angvformat =Coord::DEG; Coord::CoordSystem angvsys =Coord::PHYSICAL; Coord::SkyFrame angvsky =Coord::FK5; int angvsign =1; double angvoffset =0; // props int tile =1; char* color =NULL; char colordef[] = "green"; color = colordef; int width =1; char* text =NULL; char* font =NULL; char fontdef[] = "helvetica 10 normal roman"; font = fontdef; unsigned short props = Marker::SELECT | Marker::HIGHLITE | Marker::EDIT | Marker::MOVE | Marker::ROTATE | Marker::DELETE | Marker::SOURCE | Marker::INCLUDE; int dash[2] = {8,3}; List<Tag> taglist; // params char* param =NULL; char* param2 =NULL; char* param3 =NULL; char* param4 =NULL; char* param5 =NULL; // comment char* comment=NULL; List<CallBack> cblist; // build it for (int ii=0; ii<colcnt; ii++) { if (cols[ii]) { switch (id[ii]) { case XMLSHAPE: shape = cols[ii]; break; case XMLX: // only check x col, y col better be the same x = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&sys,&sky); if (unit[ii]) coord.strToSkyFormat(unit[ii],&format); break; case XMLY: y = cols[ii]; break; case XMLXV: // only check x col, y col better be the same xv = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&vsys,&vsky); if (unit[ii]) coord.strToSkyFormat(unit[ii],&vformat); break; case XMLYV: yv = cols[ii]; break; case XMLR: // only check r col, r2 col better be the same r = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&rsys,&rsky); if (unit[ii]) coord.strToDistFormat(unit[ii],&rdist); break; case XMLR2: r2 = cols[ii]; break; case XMLRV: // only check rv col, r2 col better be the same rv = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&rvsys,&rvsky); if (unit[ii]) coord.strToDistFormat(unit[ii],&rvdist); break; case XMLRV2: rv2 = cols[ii]; break; case XMLANG: ang = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&angsys,&angsky); if (unit[ii]) coord.strToAngleFormat(unit[ii],&angformat); if (dir[ii]) { if (STRCMP(dir[ii],"cw",2)) angsign = -1; } if (axis[ii]) { if (STRCMP(dir[ii],"x",1)) { if (angsys == Coord::WCS) { switch (angsky) { case Coord::FK4: case Coord::FK5: case Coord::ICRS: angoffset = M_PI; break; default: // na break; } } } else if (STRCMP(dir[ii],"-x",2)) { if (angsys == Coord::WCS) { switch (angsky) { case Coord::FK4: case Coord::FK5: case Coord::ICRS: break; default: angoffset = M_PI; } } } else if (STRCMP(dir[ii],"y",1)) { angoffset = M_PI_2; } else if (STRCMP(dir[ii],"-y",2)) { angoffset = -M_PI_2; } } break; case XMLANGV: angv = cols[ii]; if (ref[ii]) coord.strToCoordSystem(ref[ii],wcsSystem_,&angvsys,&angvsky); if (unit[ii]) coord.strToAngleFormat(unit[ii],&angvformat); if (dir[ii]) if (STRCMP(dir[ii],"cw",2)) angvsign = -1; if (axis[ii]) { if (STRCMP(dir[ii],"x",1)) ; else if (STRCMP(dir[ii],"-x",2)) angvoffset = M_PI; else if (STRCMP(dir[ii],"y",1)) angvoffset = M_PI_2; else if (STRCMP(dir[ii],"-y",2)) angvoffset = -M_PI_2; } break; case XMLTILE: tile = atoi(cols[ii]); break; case XMLCOLOR: color = cols[ii]; break; case XMLWIDTH: width = atoi(cols[ii]); break; case XMLTEXT: text = cols[ii]; break; case XMLFONT: font = cols[ii]; break; case XMLSELECT: xmlSetProps(&props, Marker::SELECT, cols[ii]); break; case XMLHIGHLITE: xmlSetProps(&props, Marker::HIGHLITE, cols[ii]); break; case XMLEDIT: xmlSetProps(&props, Marker::EDIT, cols[ii]); break; case XMLMOVE: xmlSetProps(&props, Marker::MOVE, cols[ii]); break; case XMLROTATE: xmlSetProps(&props, Marker::ROTATE, cols[ii]); break; case XMLDELETE: xmlSetProps(&props, Marker::DELETE, cols[ii]); break; case XMLFIXED: xmlSetProps(&props, Marker::FIXED, cols[ii]); break; case XMLINCLUDE: xmlSetProps(&props, Marker::INCLUDE, cols[ii]); break; case XMLSOURCE: xmlSetProps(&props, Marker::SOURCE, cols[ii]); break; case XMLDASH: xmlSetProps(&props, Marker::DASH, cols[ii]); break; case XMLDASHLIST: { char* cc = dupstr(cols[ii]); char* tok = strtok(cc, ","); if (tok) dash[0] = atoi(tok); tok = strtok(NULL, ","); if (tok) dash[1] = atoi(tok); delete [] cc; } break; case XMLTAG: { char* cc = dupstr(cols[ii]); char* tok = strtok(cc, " "); while (tok) { // look for special #160 char* aa = dupstr(tok); char* dd = aa; char* ee = aa; while (*dd) if (*dd == -62) { *ee++ = ' '; dd +=2; } else *ee++ = *dd++; // NULL terminate if shortened *ee = *dd; taglist.append(new Tag(aa)); delete [] aa; tok = strtok(NULL, " "); } delete [] cc; } break; case XMLPARAM: param = cols[ii]; break; case XMLPARAM2: param2 = cols[ii]; break; case XMLPARAM3: param3 = cols[ii]; break; case XMLPARAM4: param4 = cols[ii]; break; case XMLPARAM5: param5 = cols[ii]; break; case XMLCOMMENT: comment = cols[ii]; break; } } } FitsImage* ptr = findFits(tile); // Basic Regions if (STRCMP(shape, "circle", 6)) { // will also capture circle3d int fill =0; if (param) fill = atoi(param); createCircleCmd(xmlPoint(ptr, x, y, sys, sky, format), ptr->mapLenToRef(atof(r), rsys, rdist), fill, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "ellipse", 7)) { int fill =0; if (param) fill = atoi(param); createEllipseCmd(xmlPoint(ptr, x, y, sys, sky, format), ptr->mapLenToRef(Vector(atof(r),atof(r2)), rsys, rdist), xmlAngle(ang, angsign, angoffset, angformat, sys, sky), fill, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "box", 3) || STRCMP(shape, "rotbox", 6)) { int fill =0; if (param) fill = atoi(param); createBoxCmd(xmlPoint(ptr, x, y, sys, sky, format), ptr->mapLenToRef(Vector(atof(r),atof(r2)), rsys, rdist), xmlAngle(ang, angsign, angoffset, angformat, sys, sky), fill, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "rectang", 6) || STRCMP(shape, "rotrec", 6)) { int fill =0; if (param) fill = atoi(param); Vector v1 = xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 0); Vector v2 = xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 1); Vector d = v2-v1; Vector c = d/2 + v1; createBoxCmd(c,d, xmlAngle(ang, angsign, angoffset, angformat, sys, sky), fill, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "polygon", 7)) { int fill =0; if (param) fill = atoi(param); List<Vertex>* list = xmlVertex(ptr, xv, yv, vsys, vsky, vformat); createPolygonCmd(*list, fill, color, dash, width, font, text, props, comment, taglist, cblist); if (list) delete list; } else if (STRCMP(shape, "line", 4)) { int arrow1 =1; int arrow2 =1; if (param) arrow1 = atoi(param); if (param2) arrow2 = atoi(param2); createLineCmd(xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 0), xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 1), arrow1, arrow2, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "vector", 6)) { int arrow =1; if (param) arrow = atoi(param); createVectCmd(xmlPoint(ptr, x, y, sys, sky, format), ptr->mapLenToRef(atof(r), rsys, rdist), xmlAngle(ang, angsign, angoffset, angformat, sys, sky), arrow, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "projection", 10)) { createProjectionCmd(xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 0), xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 1), ptr->mapLenToRef(atof(r), rsys, rdist), color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "segment", 7)) { List<Vertex>* list = xmlVertex(ptr, xv, yv, vsys, vsky, vformat); createSegmentCmd(*list, color, dash, width, font, text, props, comment, taglist, cblist); if (list) delete list; } else if (STRCMP(shape, "text", 4)) { int rotate = 1; if (param) rotate = atoi(param); createTextCmd(xmlPoint(ptr, x, y, sys, sky, format), xmlAngle(ang, angsign, angoffset, angformat, sys, sky), rotate, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "point", 5)) { const char* def = "circle"; Point::PointShape shape = Point::CIRCLE; if (!param) param = (char*)def; int size = 11; if (param2) size = atoi(param2); if (STRCMP(param, "circle", 6)) shape = Point::CIRCLE; else if (STRCMP(param, "box", 3)) shape = Point::BOX; else if (STRCMP(param, "diamond", 7)) shape = Point::DIAMOND; else if (STRCMP(param, "cross", 5)) shape = Point::CROSS; else if (STRCMP(param, "x", 1)) shape = Point::EX; else if (STRCMP(param, "arrow", 5)) shape = Point::ARROW; else if (STRCMP(param,"boxcircle",9)) shape = Point::BOXCIRCLE; createPointCmd(xmlPoint(ptr, x, y, sys, sky, format), shape, size, color, dash, width, font, text, props, comment, taglist, cblist); } // Measurement Regions else if (STRCMP(shape, "ruler", 5)) { Coord::CoordSystem rsys; Coord::SkyFrame rsky; coord.strToCoordSystem(param, wcsSystem_, &rsys, &rsky); Coord::CoordSystem dsys; Coord::DistFormat ddist; coord.strToDistSystem(param2, wcsSystem_, &dsys, &ddist); const char* def3 = ""; if (!param3) param3 = (char*)def3; createRulerCmd(xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 0), xmlPoint(ptr, xv, yv, vsys, vsky, vformat, 1), rsys, rsky, dsys, ddist, param3, color, dash, width, font, text, props, comment, taglist, cblist); } else if (STRCMP(shape, "compass", 7)) { Coord::CoordSystem csys; Coord::SkyFrame csky; coord.strToCoordSystem(param, wcsSystem_, &csys, &csky); const char* param2def = "N"; if (!param2) param2 = (char*)param2def; const char* param3def = "E"; if (!param3) param3 = (char*)param3def; int arrow1 =1; if (param4) arrow1 = atoi(param4); int arrow2 =1; if (param5) arrow2 = atoi(param5); createCompassCmd(xmlPoint(ptr, x, y, sys, sky, format), ptr->mapLenToRef(atof(r), rsys, rdist), param2, param3, arrow1, arrow2, csys, csky, color, dash, width, font, text, props, comment, taglist, cblist); } // Annulus Regions else if (STRCMP(shape, "annulus", 7)) { int num = xmlCount(rv); double* rr = xmlDistance(ptr, rv, num, rvsys, rvdist); createAnnulusCmd(xmlPoint(ptr, x, y, sys, sky, format), num, rr, color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; } else if (STRCMP(shape, "ellipseannulus", 14)) { int num = xmlCount(rv); Vector* rr =xmlDistance(ptr, rv, rv2, num, rvsys, rvdist); createEllipseAnnulusCmd(xmlPoint(ptr, x, y, sys, sky, format), num, rr, xmlAngle(ang, angsign, angoffset, angformat, sys, sky), color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; } else if (STRCMP(shape, "boxannulus", 10)) { int num = xmlCount(rv); Vector* rr = xmlDistance(ptr, rv, rv2, num, rvsys, rvdist); createBoxAnnulusCmd(xmlPoint(ptr, x, y, sys, sky, format), num, rr, xmlAngle(ang, angsign, angoffset, angformat, sys, sky), color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; } // Panda Regions else if (STRCMP(shape, "panda", 5) || STRCMP(shape, "pie", 3)) { int anum = xmlCount(angv); int rnum = xmlCount(rv); double* rr = xmlDistance(ptr, rv, rnum, rvsys, rvdist); double* aa = xmlAngles(angv, angvsign, angvoffset, anum, angvformat, sys, sky); createCpandaCmd(xmlPoint(ptr, x, y, sys, sky, format), anum, aa, rnum, rr, color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; if (aa) delete [] aa; } else if (STRCMP(shape, "epanda", 6)) { int anum = xmlCount(angv); int rnum = xmlCount(rv); Vector* rr = xmlDistance(ptr, rv, rv2, rnum, rvsys, rvdist); double* aa = xmlAngles(angv, angvsign, angoffset, anum, angvformat, sys, sky); createEpandaCmd(xmlPoint(ptr, x, y, sys, sky, format), anum, aa, rnum, rr, xmlAngle(ang, angsign, angoffset, angformat, sys, sky), color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; if (aa) delete [] aa; } else if (STRCMP(shape, "bpanda", 6)) { int anum = xmlCount(angv); int rnum = xmlCount(rv); Vector* rr = xmlDistance(ptr, rv, rv2, rnum, rvsys, rvdist); double* aa = xmlAngles(angv, angvsign, angvoffset, anum, angvformat, sys, sky); createBpandaCmd(xmlPoint(ptr, x, y, sys, sky, format), anum, aa, rnum, rr, xmlAngle(ang, angsign, angoffset, angformat, sys, sky), color, dash, width, font, text, props, comment, taglist, cblist); if (rr) delete [] rr; if (aa) delete [] aa; } } void Base::xmlSetProps(unsigned short* props, unsigned short prop, char* str) { if (atoi(str)) *props |= prop; else *props &= ~prop; } int Base::xmlCount(const char* col) { int cnt=0; char* cc = dupstr(col); char* tok = strtok(cc, " "); while (tok) { cnt++; tok = strtok(NULL, " "); } delete [] cc; return cnt; } Vector Base::xmlPoint(FitsImage* ptr, const char* xstr, const char* ystr, Coord::CoordSystem sys, Coord::SkyFrame sky, Coord::SkyFormat format, int which) { if (!xstr || !ystr) return Vector(); char* x =NULL; char* y =NULL; char* xcc =NULL; char* ycc =NULL; if (which>0) { xcc = dupstr(xstr); x = strtok(xcc, " "); for (int ii=0; ii<which; ii++) x = strtok(NULL, " "); ycc = dupstr(ystr); y = strtok(ycc, " ,"); for (int ii=0; ii<which; ii++) y = strtok(NULL, " "); } else { x = (char*)xstr; y = (char*)ystr; } Vector rr; switch (sys) { case Coord::IMAGE: case Coord::PHYSICAL: case Coord::DETECTOR: case Coord::AMPLIFIER: rr = ptr->mapToRef(Vector(atof(x),atof(y)), sys); break; default: if (ptr->hasWCSCel(sys)) { switch (format) { case Coord::DEGREES: rr = ptr->mapToRef(Vector(atof(x),atof(y)), sys, sky); break; case Coord::SEXAGESIMAL: { double xx=parseSEXStr(x); double yy=parseSEXStr(y); switch (sky) { case Coord::FK4: case Coord::FK5: case Coord::ICRS: xx = xx/24.*360.; break; case Coord::GALACTIC: case Coord::ECLIPTIC: break; } rr = ptr->mapToRef(Vector(xx,yy), sys, sky); } } } else rr = ptr->mapToRef(Vector(atof(x),atof(y)), sys); } if (which>0) { if (xcc) delete [] xcc; if (ycc) delete [] ycc; } return rr; } List<Vertex>* Base::xmlVertex(FitsImage* ptr, const char* x, const char* y, Coord::CoordSystem sys, Coord::SkyFrame sky, Coord::SkyFormat format) { List<Vertex>* list = new List<Vertex>; int cnt= xmlCount(x); for (int ii=0; ii<cnt; ii++) { Vector vv = xmlPoint(ptr,x,y,sys,sky,format,ii); Vertex* n = new Vertex(vv); list->append(n); } return list; } double* Base::xmlDistance(FitsImage* ptr, const char* r, int cnt, Coord::CoordSystem sys, Coord::DistFormat dist) { double* rr = new double[cnt]; char* cc = dupstr(r); char* tok = strtok(cc, " "); for (int ii=0; ii<cnt; ii++) { if (tok) rr[ii] = atof(tok); tok = strtok(NULL, " "); } delete [] cc; for (int ii=0; ii<cnt; ii++) rr[ii] = ptr->mapLenToRef(rr[ii], sys, dist); return rr; } Vector* Base::xmlDistance(FitsImage* ptr, const char* r, const char* r2, int cnt, Coord::CoordSystem sys, Coord::DistFormat dist) { Vector* vv = new Vector[cnt]; { char* cc = dupstr(r); char* tok = strtok(cc, " "); for (int ii=0; ii<cnt; ii++) { if (tok) vv[ii][0] = atof(tok); tok = strtok(NULL, " "); } delete [] cc; } { char* cc = dupstr(r2); char* tok = strtok(cc, " "); for (int ii=0; ii<cnt; ii++) { if (tok) vv[ii][1] = atof(tok); tok = strtok(NULL, " "); } delete [] cc; } for (int ii=0; ii<cnt; ii++) vv[ii] = ptr->mapLenToRef(vv[ii], sys, dist); return vv; } double Base::xmlAngle(const char* angle, int sign, double offset, Coord::AngleFormat format, Coord::CoordSystem sys, Coord::SkyFrame sky) { switch (format) { case Coord::DEG: return mapAngleToRef(sign*zeroTWOPI(degToRad(atof(angle)))+offset,sys,sky); case Coord::RAD: return mapAngleToRef(sign*atof(angle)+offset, sys, sky); default: return 0; } } double* Base::xmlAngles(const char* angle, int sign, double offset, int cnt, Coord::AngleFormat format, Coord::CoordSystem sys, Coord::SkyFrame sky) { double* ang = new double[cnt]; char* cc = dupstr(angle); char* tok = strtok(cc, " "); for (int ii=0; ii<cnt; ii++) { if (tok) switch (format) { case Coord::DEG: ang[ii] = mapAngleToRef(sign*zeroTWOPI(degToRad(atof(tok)))+offset,sys,sky); break; case Coord::RAD: ang[ii] = mapAngleToRef(sign*atof(tok)+offset, sys, sky); break; } tok = strtok(NULL, " "); } delete [] cc; return ang; } void Base::markerListXMLHeader(ostream& str, Coord::CoordSystem sys, Coord::SkyFrame sky, Coord::SkyFormat format) { str << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" << endl << "<VOTABLE version=\"1.1\">" << endl << "<DEFINITIONS>" << endl << "<COOSYS ID=\"fk5\" system=\"eq_FK5\" equinox=\"J2000\"/>" << endl << "<COOSYS ID=\"fk4\" system=\"eq_FK4\" equinox=\"B1950\"/>" << endl << "</DEFINITIONS>" << endl << "<RESOURCE>" << endl << "<TABLE>" << endl << "<DESCRIPTION>DS9 version 4.1</DESCRIPTION>" << endl; str << "<FIELD ID=\"shape\" name=\"shape\" datatype=\"char\" arraysize=\"*\"/>" << endl; switch (sys) { case Coord::IMAGE: case Coord::PHYSICAL: case Coord::DETECTOR: case Coord::AMPLIFIER: str << "<FIELD ID=\"x\" name=\"x\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"y\" name=\"y\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"xv\" name=\"xv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"yv\" name=\"yv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"r\" name=\"r\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"r2\" name=\"r2\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"rv\" name=\"rv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"rv2\" name=\"rv2\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"ang\" name=\"ang\" datatype=\"float\" precision=\"8\" unit=\"deg\" ref=\"" << coord.coordSystemStr(sys) << "\" axis=\"x\" dir=\"ccw\"/>" << endl; str << "<FIELD ID=\"angv\" name=\"angv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"deg\" ref=\"" << coord.coordSystemStr(sys) << "\" axis=\"x\" dir=\"ccw\"/>" << endl; break; default: if (keyContext->fits->hasWCS(sys)) { if (keyContext->fits->hasWCSCel(sys)) { // determine ucd char* xucd=NULL; char* yucd=NULL; switch (sky) { case Coord::FK4: case Coord::FK5: case Coord::ICRS: xucd = dupstr("pos.eq.ra;meta.main"); yucd = dupstr("pos.eq.dec;meta.main"); break; case Coord::GALACTIC: xucd = dupstr("pos.galactic.lon;meta.main"); yucd = dupstr("pos.galactic.lat;meta.main"); break; case Coord::ECLIPTIC: xucd = dupstr("pos.ecliptic.lon;meta.main"); yucd = dupstr("pos.ecliptic.lat;meta.main"); break; } switch (format) { case Coord::DEGREES: str << "<FIELD ID=\"x\" name=\"x\" datatype=\"float\" precision=\"8\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\" ucd=\"" << xucd << "\"/>" << endl; str << "<FIELD ID=\"y\" name=\"y\" datatype=\"float\" precision=\"8\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\" ucd=\"" << yucd << "\"/>" << endl; str << "<FIELD ID=\"xv\" name=\"xv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"yv\" name=\"yv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; break; case Coord::SEXAGESIMAL: str << "<FIELD ID=\"x\" name=\"x\" datatype=\"char\" arraysize=\"*\" unit=\""h:m:s"\" ref=\"" << coord.skyFrameStr(sky) << "\" ucd=\"" << xucd << "\"/>" << endl; str << "<FIELD ID=\"y\" name=\"y\" datatype=\"char\" arraysize=\"*\" unit=\""d:m:s"\" ref=\"" << coord.skyFrameStr(sky) << "\" ucd=\"" << yucd << "\"/>" << endl; str << "<FIELD ID=\"xv\" name=\"xv\" datatype=\"char\" arraysize=\"*\" unit=\""h:m:s"\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"yv\" name=\"yv\" datatype=\"char\" arraysize=\"*\" unit=\""d:m:s"\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; break; } str << "<FIELD ID=\"r\" name=\"r\" datatype=\"float\" precision=\"8\" unit=\"arcsec\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"r2\" name=\"r2\" datatype=\"float\" precision=\"8\" unit=\"arcsec\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"rv\" name=\"rv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"arcsec\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"rv2\" name=\"rv2\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"arcsec\" ref=\"" << coord.skyFrameStr(sky) << "\"/>" << endl; str << "<FIELD ID=\"ang\" name=\"ang\" datatype=\"float\" precision=\"8\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\" axis=\"-x\" dir=\"ccw\"/>" << endl; str << "<FIELD ID=\"angv\" name=\"angv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"deg\" ref=\"" << coord.skyFrameStr(sky) << "\" axis=\"-x\" dir=\"ccw\"/>" << endl; if (xucd) delete [] xucd; if (yucd) delete [] yucd; } else { str << "<FIELD ID=\"x\" name=\"x\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"y\" name=\"y\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"xv\" name=\"xv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"yv\" name=\"yv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"r\" name=\"r\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"r2\" name=\"r2\" datatype=\"float\" precision=\"8\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"rv\" name=\"rv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"rv2\" name=\"rv2\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"pix\" ref=\"" << coord.coordSystemStr(sys) << "\"/>" << endl; str << "<FIELD ID=\"ang\" name=\"ang\" datatype=\"float\" precision=\"8\" unit=\"deg\" ref=\"" << coord.coordSystemStr(sys) << "\" axis=\"x\" dir=\"ccw\"/>" << endl; str << "<FIELD ID=\"angv\" name=\"angv\" datatype=\"float\" precision=\"8\" arraysize=\"*\" unit=\"deg\" ref=\"" << coord.coordSystemStr(sys) << "\" axis=\"x\" dir=\"ccw\"/>" << endl; } } } str << "<FIELD ID=\"tile\" name=\"tile\" datatype=\"int\"/>" << endl; str << "<FIELD ID=\"color\" name=\"color\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"width\" name=\"width\" datatype=\"int\"/>" << endl; str << "<FIELD ID=\"text\" name=\"text\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"font\" name=\"font\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"select\" name=\"select\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"highlite\" name=\"highlite\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"edit\" name=\"edit\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"move\" name=\"move\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"rotate\" name=\"rotate\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"delete\" name=\"delete\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"fixed\" name=\"fixed\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"include\" name=\"include\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"source\" name=\"source\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"dash\" name=\"dash\" datatype=\"boolean\"/>" << endl; str << "<FIELD ID=\"dashlist\" name=\"dashlist\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"tag\" name=\"tag\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"param\" name=\"param\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"param2\" name=\"param2\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"param3\" name=\"param3\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"param4\" name=\"param4\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"param5\" name=\"param5\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<FIELD ID=\"comment\" name=\"comment\" datatype=\"char\" arraysize=\"*\"/>" << endl; str << "<DATA>" << endl << "<TABLEDATA>" << endl; } void Base::markerListXMLFooter(ostream& str) { str << "</TABLEDATA>" << endl << "</DATA>" << endl << "</TABLE>" << endl << "</RESOURCE>" << endl << "</VOTABLE>" << endl; }