/*
*+
* Name:
* palUnpcd
* Purpose:
* Remove pincushion/barrel distortion
* Language:
* Starlink ANSI C
* Type of Module:
* Library routine
* Invocation:
* palUnpcd( double disco, double * x, double * y );
* Arguments:
* disco = double (Given)
* Pincushion/barrel distortion coefficient.
* x = double * (Given & Returned)
* On input the distorted X coordinate, on output
* the tangent-plane X coordinate.
* y = double * (Given & Returned)
* On input the distorted Y coordinate, on output
* the tangent-plane Y coordinate.
* Description:
* Remove pincushion/barrel distortion from a distorted [x,y] to give
* tangent-plane [x,y].
* Authors:
* PTW: Pat Wallace (RAL)
* TIMJ: Tim Jenness
* {enter_new_authors_here}
* Notes:
* - The distortion is of the form RP = R*(1+C*R^2), where R is
* the radial distance from the tangent point, C is the DISCO
* argument, and RP is the radial distance in the presence of
* the distortion.
*
* - For pincushion distortion, C is +ve; for barrel distortion,
* C is -ve.
*
* - For X,Y in "radians" - units of one projection radius,
* which in the case of a photograph is the focal length of
* the camera - the following DISCO values apply:
*
* Geometry DISCO
*
* astrograph 0.0
* Schmidt -0.3333
* AAT PF doublet +147.069
* AAT PF triplet +178.585
* AAT f/8 +21.20
* JKT f/8 +13.32
*
* - The present routine is a rigorous inverse of the companion
* routine palPcd. The expression for RP in Note 1 is rewritten
* in the form x^3+a*x+b=0 and solved by standard techniques.
*
* - Cases where the cubic has multiple real roots can sometimes
* occur, corresponding to extreme instances of barrel distortion
* where up to three different undistorted [X,Y]s all produce the
* same distorted [X,Y]. However, only one solution is returned,
* the one that produces the smallest change in [X,Y].
* See Also:
* palPcd
* History:
* 2000-09-03 (PTW):
* SLALIB implementation.
* 2015-01-01 (TIMJ):
* Initial version
* {enter_further_changes_here}
* Copyright:
* Copyright (C) 2000 Rutherford Appleton Laboratory.
* Copyright (C) 2015 Tim Jenness
* All Rights Reserved.
* Licence:
* 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 3 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, see .
* Bugs:
* {note_any_bugs_here}
*-
*/
#if HAVE_CONFIG_H
#include
#endif
#include
#include "pal.h"
#include "palmac.h"
/* copysign is C99 */
#if HAVE_COPYSIGN
# define COPYSIGN copysign
#else
# define COPYSIGN(a,b) DSIGN(a,b)
#endif
void palUnpcd( double disco, double * x, double *y ) {
const double THIRD = 1.0/3.0;
double rp,q,r,d,w,s,t,f,c,t3,f1,f2,f3,w1,w2,w3;
double c2;
/* Distance of the point from the origin. */
rp = sqrt( (*x)*(*x)+(*y)*(*y));
/* If zero, or if no distortion, no action is necessary. */
if (rp != 0.0 && disco != 0.0) {
/* Begin algebraic solution. */
q = 1.0/(3.0*disco);
r = rp/(2.0*disco);
w = q*q*q+r*r;
/* Continue if one real root, or three of which only one is positive. */
if (w > 0.0) {
d = sqrt(w);
w = r+d;
s = COPYSIGN(pow(fabs(w),THIRD),w);
w = r-d;
t = COPYSIGN(pow(fabs(w),THIRD),w);
f = s+t;
} else {
/* Three different real roots: use geometrical method instead. */
w = 2.0/sqrt(-3.0*disco);
c = 4.0*rp/(disco*w*w*w);
c2 = c*c;
s = sqrt(1.0-DMIN(c2,1.0));
t3 = atan2(s,c);
/* The three solutions. */
f1 = w*cos((PAL__D2PI-t3)/3.0);
f2 = w*cos((t3)/3.0);
f3 = w*cos((PAL__D2PI+t3)/3.0);
/* Pick the one that moves [X,Y] least. */
w1 = fabs(f1-rp);
w2 = fabs(f2-rp);
w3 = fabs(f3-rp);
if (w1 < w2) {
f = ( w1 < w3 ? f1 : f3 );
} else {
f = ( w2 < w3 ? f2 : f3 );
}
}
/* Remove the distortion. */
f = f/rp;
*x *= f;
*y *= f;
}
}