int sphdpa( int nfield, double lng0, double lat0, const double lng[], const double lat[], double dist[], double pa[]) { int i; double eul[5]; /* Set the Euler angles for the coordinate transformation. */ eul[0] = lng0; eul[1] = 90.0 - lat0; eul[2] = 0.0; eul[3] = cosd(eul[1]); eul[4] = sind(eul[1]); /* Transform field points to the new system. */ sphs2x(eul, nfield, 0, 1, 1, lng, lat, pa, dist); for (i = 0; i < nfield; i++) { /* Angular distance is obtained from latitude in the new frame. */ dist[i] = 90.0 - dist[i]; /* Position angle is obtained from longitude in the new frame. */ pa[i] = -pa[i]; if (pa[i] < -180.0) pa[i] += 360.0; } return 0; }
int sphs2x_( const double eul[5], const int *nlng, const int *nlat, const int *sll, const int *spt, const double lng[], const double lat[], double phi[], double theta[]) { return sphs2x(eul, *nlng, *nlat, *sll, *spt, lng, lat, phi, theta); }
int cylfix(const int naxis[], struct wcsprm *wcs) { static const char *function = "cylfix"; unsigned short icnr, indx[NMAX], ncnr; int j, k, stat[4], status; double img[4][NMAX], lat, lng, phi[4], phi0, phimax, phimin, pix[4][NMAX], *pixj, theta[4], theta0, world[4][NMAX], x, y; struct wcserr **err; if (naxis == 0x0) return FIXERR_NO_CHANGE; if (wcs == 0x0) return FIXERR_NULL_POINTER; err = &(wcs->err); /* Initialize if required. */ if (wcs->flag != WCSSET) { if ((status = wcsset(wcs))) return status; } /* Check that we have a cylindrical projection. */ if (wcs->cel.prj.category != CYLINDRICAL) return FIXERR_NO_CHANGE; if (wcs->naxis < 2) return FIXERR_NO_CHANGE; /* Compute the native longitude in each corner of the image. */ ncnr = 1 << wcs->naxis; for (k = 0; k < NMAX; k++) { indx[k] = 1 << k; } phimin = 1.0e99; phimax = -1.0e99; for (icnr = 0; icnr < ncnr;) { /* Do four corners at a time. */ for (j = 0; j < 4; j++, icnr++) { pixj = pix[j]; for (k = 0; k < wcs->naxis; k++) { if (icnr & indx[k]) { *(pixj++) = naxis[k] + 0.5; } else { *(pixj++) = 0.5; } } } if (!(status = wcsp2s(wcs, 4, NMAX, pix[0], img[0], phi, theta, world[0], stat))) { for (j = 0; j < 4; j++) { if (phi[j] < phimin) phimin = phi[j]; if (phi[j] > phimax) phimax = phi[j]; } } } if (phimin > phimax) return status; /* Any changes needed? */ if (phimin >= -180.0 && phimax <= 180.0) return FIXERR_NO_CHANGE; /* Compute the new reference pixel coordinates. */ phi0 = (phimin + phimax) / 2.0; theta0 = 0.0; if ((status = prjs2x(&(wcs->cel.prj), 1, 1, 1, 1, &phi0, &theta0, &x, &y, stat))) { if (status == PRJERR_BAD_PARAM) { return wcserr_set(WCSFIX_ERRMSG(FIXERR_BAD_PARAM)); } return wcserr_set(WCSFIX_ERRMSG(FIXERR_NO_REF_PIX_COORD)); } for (k = 0; k < wcs->naxis; k++) { img[0][k] = 0.0; } img[0][wcs->lng] = x; img[0][wcs->lat] = y; if ((status = linx2p(&(wcs->lin), 1, 0, img[0], pix[0]))) { return wcserr_set(WCSFIX_ERRMSG(status)); } /* Compute celestial coordinates at the new reference pixel. */ if ((status = wcsp2s(wcs, 1, 0, pix[0], img[0], phi, theta, world[0], stat))) { if (wcs->err->status == WCSERR_BAD_PIX) { wcs->err->status = FIXERR_NO_REF_PIX_COORD; } return wcs->err->status; } /* Compute native coordinates of the celestial pole. */ lng = 0.0; lat = 90.0; (void)sphs2x(wcs->cel.euler, 1, 1, 1, 1, &lng, &lat, phi, theta); wcs->crpix[wcs->lng] = pix[0][wcs->lng]; wcs->crpix[wcs->lat] = pix[0][wcs->lat]; wcs->crval[wcs->lng] = world[0][wcs->lng]; wcs->crval[wcs->lat] = world[0][wcs->lat]; wcs->lonpole = phi[0] - phi0; return wcsset(wcs); }
int main() { int j, k, lat, lng, nFail = 0; double cel1[181][2], cel2[181][2], coslat, dlat, dlatmx, dlng, dlngmx, eul[5], lng1[361], lng2[361], lat1, lat2[361], ntv[181][2], phi[361], theta[361], zeta; const double tol = 1.0e-12; printf( "Testing closure of WCSLIB coordinate transformation routines (tsph.c)\n" "---------------------------------------------------------------------\n"); printf ("Reporting tolerance:%8.1e degrees of arc.\n", tol); dlngmx = 0.0; dlatmx = 0.0; for (k = 0; k < 3; k++) { /* Set reference angles. */ eul[0] = 90.0; eul[2] = -90.0; if (k < 2) { /* Special-case transformations. */ eul[1] = (k==0) ? 0.0 : 180.0; } else { eul[1] = 30.0; } printf("\n%s\n%s%10.4f%10.4f%10.4f\n", "Celestial longitude and latitude of the native pole, and native", "longitude of the celestial pole (degrees):", eul[0], eul[1], eul[2]); eul[3] = cosd(eul[1]); eul[4] = sind(eul[1]); /* Test points at constant latitude. */ for (lat = 90; lat >= -90; lat--) { lat1 = (double)lat; coslat = cosd(lat1); for (j = 0, lng = -180; lng <= 180; lng++, j++) { lng1[j] = (double)lng; } sphs2x(eul, 361, 1, 1, 1, lng1, &lat1, phi, theta); sphx2s(eul, 361, 0, 1, 1, phi, theta, lng2, lat2); /* Exact results are expected for special-case transformations. */ if (k == 0) { /* Identity transformation. */ for (j = 0; j <= 360; j++) { if (phi[j] != lng1[j] || theta[j] != lat1) { nFail++; printf(" Error: lng1 =%20.15f lat1 =%20.15f\n", lng1[j], lat1); printf(" phi =%20.15f theta =%20.15f\n", phi[j], theta[j]); } } } else if (k == 1) { /* Antipodal transformation. */ for (j = 0; j <= 360; j++) { if (phi[j] != -lng1[j] || theta[j] != -lat1) { nFail++; printf(" Error: lng1 =%20.15f lat1 =%20.15f\n", lng1[j], lat1); printf(" phi =%20.15f theta =%20.15f\n", phi[j], theta[j]); } } } /* Do another round trip, just for good measure. */ sphs2x(eul, 361, 0, 1, 1, lng2, lat2, phi, theta); sphx2s(eul, 361, 0, 1, 1, phi, theta, lng2, lat2); /* Check closure. */ for (j = 0; j <= 360; j++) { dlng = fabs(lng2[j] - lng1[j]); if (dlng > 180.0) dlng = fabs(dlng-360.0); dlng *= coslat; dlat = fabs(lat2[j] - lat1); if (dlng > dlngmx) dlngmx = dlng; if (dlat > dlatmx) dlatmx = dlat; if (dlng > tol || dlat > tol) { nFail++; printf("Unclosed: lng1 =%20.15f lat1 =%20.15f\n", lng1[j], lat1); printf(" phi =%20.15f theta =%20.15f\n", phi[j], theta[j]); printf(" lng2 =%20.15f lat2 =%20.15f\n", lng2[j], lat2[j]); } } } /* Test vector strides using points in spirals from south to north. */ for (lng = 0; lng <= 360; lng++) { for (j = 0, lat = -90; lat <= 90; j++, lat++) { cel1[j][0] = (double)((lng+j)%360 - 180); cel1[j][1] = (double)lat; } sphs2x(eul, 181, 0, 2, 2, &(cel1[0][0]), &(cel1[0][1]), &(ntv[0][0]), &(ntv[0][1])); sphx2s(eul, 181, 0, 2, 2, &(ntv[0][0]), &(ntv[0][1]), &(cel2[0][0]), &(cel2[0][1])); /* Exact results are expected for special-case transformations. */ if (k == 0) { /* Identity transformation. */ for (j = 0; j <= 180; j++) { if (ntv[j][0] != cel1[j][0] || ntv[j][1] != cel1[j][1]) { nFail++; printf(" Error: lng1 =%20.15f lat1 =%20.15f\n", cel1[j][0], cel1[j][1]); printf(" phi =%20.15f theta =%20.15f\n", ntv[j][0], ntv[j][1]); } } } else if (k == 1) { /* Antipodal transformation. */ for (j = 0; j <= 180; j++) { if (ntv[j][0] != -cel1[j][0] || ntv[j][1] != -cel1[j][1]) { nFail++; printf(" Error: lng1 =%20.15f lat1 =%20.15f\n", cel1[j][0], cel1[j][1]); printf(" phi =%20.15f theta =%20.15f\n", ntv[j][0], ntv[j][1]); } } } /* Check closure. */ for (j = 0; j <= 180; j++) { dlng = fabs(cel2[j][0] - cel1[j][0]); if (dlng > 180.0) dlng = fabs(dlng - 360.0); dlng *= cosd(cel1[j][1]); dlat = fabs(cel2[j][1] - cel1[j][1]); if (dlng > dlngmx) dlngmx = dlng; if (dlat > dlatmx) dlatmx = dlat; if (dlng > tol || dlat > tol) { nFail++; printf("Unclosed: lng1 =%20.15f lat1 =%20.15f\n", cel1[j][0], cel1[j][1]); printf(" phi =%20.15f theta =%20.15f\n", ntv[j][0], ntv[j][1]); printf(" lng2 =%20.15f lat2 =%20.15f\n", cel2[j][0], cel2[j][1]); } } } } /* Test closure at points close to the pole. */ for (j = -1; j <= 1; j += 2) { zeta = 1.0; lng1[0] = -180.0; for (lat = 0; lat < 12; lat++) { lat1 = (double)j*(90.0 - zeta); sphs2x(eul, 1, 1, 1, 1, lng1, &lat1, phi, theta); sphx2s(eul, 1, 1, 1, 1, phi, theta, lng2, lat2); dlng = fabs(lng2[0] - lng1[0]); if (dlng > 180.0) dlng = fabs(dlng - 360.0); dlng *= coslat; dlat = fabs(lat2[0] - lat1); if (dlng > dlngmx) dlngmx = dlng; if (dlat > dlatmx) dlatmx = dlat; if (dlng > tol || dlat > tol) { nFail++; printf("Unclosed: lng1 =%20.15f lat1 =%20.15f\n", lng1[0], lat1); printf(" phi =%20.15f theta =%20.15f\n", phi[0], theta[0]); printf(" lng2 =%20.15f lat2 =%20.15f\n", lng2[0], lat2[0]); } zeta /= 10.0; lng1[0] += 30.0; } } printf("\nsphs2x/sphx2s: Maximum closure residual = %.1e (lng), %.1e (lat) " "deg.\n", dlngmx, dlatmx); if (nFail) { printf("\nFAIL: %d closure residuals exceed reporting tolerance.\n", nFail); } else { printf("\nPASS: All closure residuals are within reporting tolerance.\n"); } return nFail; }