/*============================================================================
PGSBOX 4.3 - an implementation of the FITS WCS standard.
Copyright (C) 1997-2007, Mark Calabretta
This file is part of PGSBOX.
PGSBOX is free software: you can redistribute it and/or modify it under
the terms of the GNU Lesser General Public License as published by the
Free Software Foundation, either version 3 of the License, or (at your
option) any later version.
PGSBOX 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 Lesser General Public License for
more details.
You should have received a copy of the GNU Lesser General Public License
along with PGSBOX. If not, see .
Correspondence concerning PGSBOX may be directed to:
Internet email: mcalabre@atnf.csiro.au
Postal address: Dr. Mark Calabretta
Australia Telescope National Facility, CSIRO
PO Box 76
Epping NSW 1710
AUSTRALIA
Author: Mark Calabretta, Australia Telescope National Facility
http://www.atnf.csiro.au/~mcalabre/index.html
$Id: pgwcsl.c,v 4.3 2007/12/27 05:49:14 cal103 Exp $
*===========================================================================*/
#include
#include
#include
/* Fortran name mangling. */
#include
#define pgwcsl_ F77_FUNC(pgwcsl, PGWCSL)
void pgwcsl_(opcode, nlc, nli, nld, nlcprm, wcs, nldprm, world, pixel, contrl,
contxt, ierr)
const int *opcode, *nlc, *nli, *nld;
const char *nlcprm;
int *wcs;
double *nldprm;
double *world;
double *pixel;
int *contrl;
double contxt[20];
int *ierr;
{
int i, outside, stat;
double dp, imgcrd[9], lat, lng, ph, phi, sdummy, th, theta;
static double wrld[9];
struct wcsprm *wcsp;
struct celprm *wcscel;
*ierr = 0;
wcsp = (struct wcsprm *)wcs;
wcscel = &(wcsp->cel);
if (*opcode == 2) {
/* Compute pixel coordinates from world coordinates. */
if (wcsp->lng < 0) {
/* Simple linear coordinates. */
if (wcss2p(wcsp, 1, 0, world, &phi, &theta, imgcrd, pixel, &stat)) {
*ierr = 1;
}
return;
}
wrld[wcsp->lng] = world[0];
if (world[1] > 90.0) {
wrld[wcsp->lat] = 90.0;
outside = -2;
} else if (world[1] < -90.0) {
wrld[wcsp->lat] = -90.0;
outside = -2;
} else {
wrld[wcsp->lat] = world[1];
outside = 0;
}
if (*contrl == 0) {
if (wcss2p(wcsp, 1, 0, wrld, &phi, &theta, imgcrd, pixel, &stat)) {
/* Translate status return values. */
*ierr = stat ? 2 : 1;
return;
}
if (fabs(phi-contxt[2]) > 180.0) {
/* Hit a discontinuity at phi = +/- 180. */
contxt[4] = pixel[0];
contxt[5] = pixel[1];
if (contxt[2] > phi) {
ph = 179.9999;
dp = (phi - contxt[2]) + 360.0;
} else {
ph = -179.9999;
dp = (phi - contxt[2]) - 360.0;
}
/* First approximation for theta. */
if (dp == 0.0) {
th = contxt[3];
} else {
th = contxt[3] + (ph-contxt[2])*(theta-contxt[3])/dp;
}
/* Iterate once to refine the value of theta. */
sphx2s(wcscel->euler, 1, 1, 1, 1, &ph, &th, &lng, &lat);
if (wrld[wcsp->lng] == contxt[0]) {
/* We are following a meridian of longitude. */
lng = wrld[wcsp->lng];
} else {
/* We are following a parallel of latitude. */
lat = wrld[wcsp->lat];
}
sphs2x(wcscel->euler, 1, 1, 1, 1, &lng, &lat, &sdummy, &th);
contxt[0] = wrld[wcsp->lng];
contxt[1] = wrld[wcsp->lat];
contxt[2] = phi;
contxt[3] = theta;
/* Pixel coordinates crossing into the discontinuity. */
sphx2s(wcscel->euler, 1, 1, 1, 1, &ph, &th, wrld+wcsp->lng,
wrld+wcsp->lat);
if (wcss2p(wcsp, 1, 0, wrld, &phi, &theta, imgcrd, pixel,
&stat)) {
/* Translate status return values. */
*ierr = stat ? 2 : 1;
return;
}
/* Pixel coordinates crossing out of the discontinuity. */
ph *= -1.0;
sphx2s(wcscel->euler, 1, 1, 1, 1, &ph, &th, wrld+wcsp->lng,
wrld+wcsp->lat);
if (wcss2p(wcsp, 1, 0, wrld, &phi, &theta, imgcrd, contxt+6,
&stat)) {
/* Translate status return values. */
*ierr = stat ? 2 : 1;
return;
}
*contrl = 1;
} else {
/* Normal mode, no discontinuity. */
contxt[0] = wrld[wcsp->lng];
contxt[1] = wrld[wcsp->lat];
contxt[2] = phi;
contxt[3] = theta;
}
} else {
if (*contrl == 1) {
/* Move to the other side of the discontinuity. */
pixel[0] = contxt[6];
pixel[1] = contxt[7];
*contrl = 2;
} else {
/* Complete the traversal. */
pixel[0] = contxt[4];
pixel[1] = contxt[5];
*contrl = 0;
}
}
*ierr = outside;
} else if (*opcode == 1) {
/* Compute pixel coordinates from world coordinates. */
if (wcsp->lng < 0) {
/* Simple linear coordinates. */
if (wcss2p(wcsp, 1, 0, world, &phi, &theta, imgcrd, pixel, &stat)) {
*ierr = 1;
}
return;
}
wrld[wcsp->lng] = world[0];
if (world[1] > 90.0) {
wrld[wcsp->lat] = 90.0;
outside = -2;
} else if (world[1] < -90.0) {
wrld[wcsp->lat] = -90.0;
outside = -2;
} else {
wrld[wcsp->lat] = world[1];
outside = 0;
}
if (wcss2p(wcsp, 1, 0, wrld, &phi, &theta, imgcrd, pixel, &stat)) {
/* Translate status return values. */
*ierr = stat ? 2 : 1;
return;
}
contxt[0] = wrld[wcsp->lng];
contxt[1] = wrld[wcsp->lat];
contxt[2] = phi;
contxt[3] = theta;
*ierr = outside;
} else if (*opcode == 0) {
/* Initialize. */
if (*nli < WCSLEN) {
*ierr = 1;
return;
}
if ((*ierr = wcsset(wcsp))) {
*ierr = *ierr <= 2 ? 1 : 2;
}
for (i = 2; i < 9; i++) {
wrld[i] = 0.0;
}
*contrl = 0;
} else if (*opcode == -1) {
/* Compute world coordinates from pixel coordinates. */
if (wcsp2s(wcsp, 1, 0, pixel, imgcrd, &phi, &theta, wrld, &stat)) {
/* Translate status return values. */
*ierr = stat ? 3 : 1;
return;
}
if (wcsp->lng < 0) {
/* Simple linear coordinates. */
world[0] = wrld[0];
world[1] = wrld[1];
} else {
world[0] = wrld[wcsp->lng];
world[1] = wrld[wcsp->lat];
if (phi < -180.0 || phi > 180.0) {
/* Pixel is outside the principle range of native longitude. */
*ierr = 3;
return;
}
}
} else {
*ierr = 1;
}
return;
}