FACT++  1.0
palUnpcd.c
Go to the documentation of this file.
1 /*
2 *+
3 * Name:
4 * palUnpcd
5 
6 * Purpose:
7 * Remove pincushion/barrel distortion
8 
9 * Language:
10 * Starlink ANSI C
11 
12 * Type of Module:
13 * Library routine
14 
15 * Invocation:
16 * palUnpcd( double disco, double * x, double * y );
17 
18 * Arguments:
19 * disco = double (Given)
20 * Pincushion/barrel distortion coefficient.
21 * x = double * (Given & Returned)
22 * On input the distorted X coordinate, on output
23 * the tangent-plane X coordinate.
24 * y = double * (Given & Returned)
25 * On input the distorted Y coordinate, on output
26 * the tangent-plane Y coordinate.
27 
28 * Description:
29 * Remove pincushion/barrel distortion from a distorted [x,y] to give
30 * tangent-plane [x,y].
31 
32 * Authors:
33 * PTW: Pat Wallace (RAL)
34 * TIMJ: Tim Jenness
35 * {enter_new_authors_here}
36 
37 * Notes:
38 * - The distortion is of the form RP = R*(1+C*R^2), where R is
39 * the radial distance from the tangent point, C is the DISCO
40 * argument, and RP is the radial distance in the presence of
41 * the distortion.
42 *
43 * - For pincushion distortion, C is +ve; for barrel distortion,
44 * C is -ve.
45 *
46 * - For X,Y in "radians" - units of one projection radius,
47 * which in the case of a photograph is the focal length of
48 * the camera - the following DISCO values apply:
49 *
50 * Geometry DISCO
51 *
52 * astrograph 0.0
53 * Schmidt -0.3333
54 * AAT PF doublet +147.069
55 * AAT PF triplet +178.585
56 * AAT f/8 +21.20
57 * JKT f/8 +13.32
58 *
59 * - The present routine is a rigorous inverse of the companion
60 * routine palPcd. The expression for RP in Note 1 is rewritten
61 * in the form x^3+a*x+b=0 and solved by standard techniques.
62 *
63 * - Cases where the cubic has multiple real roots can sometimes
64 * occur, corresponding to extreme instances of barrel distortion
65 * where up to three different undistorted [X,Y]s all produce the
66 * same distorted [X,Y]. However, only one solution is returned,
67 * the one that produces the smallest change in [X,Y].
68 
69 * See Also:
70 * palPcd
71 
72 * History:
73 * 2000-09-03 (PTW):
74 * SLALIB implementation.
75 * 2015-01-01 (TIMJ):
76 * Initial version
77 * {enter_further_changes_here}
78 
79 * Copyright:
80 * Copyright (C) 2000 Rutherford Appleton Laboratory.
81 * Copyright (C) 2015 Tim Jenness
82 * All Rights Reserved.
83 
84 * Licence:
85 * This program is free software; you can redistribute it and/or
86 * modify it under the terms of the GNU General Public License as
87 * published by the Free Software Foundation; either version 3 of
88 * the License, or (at your option) any later version.
89 *
90 * This program is distributed in the hope that it will be
91 * useful, but WITHOUT ANY WARRANTY; without even the implied
92 * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
93 * PURPOSE. See the GNU General Public License for more details.
94 *
95 * You should have received a copy of the GNU General Public License
96 * along with this program. If not, see <http://www.gnu.org/licenses/>.
97 
98 * Bugs:
99 * {note_any_bugs_here}
100 *-
101 */
102 
103 #if HAVE_CONFIG_H
104 #include <config.h>
105 #endif
106 
107 #include <math.h>
108 
109 #include "pal.h"
110 #include "palmac.h"
111 
112 /* copysign is C99 */
113 #if HAVE_COPYSIGN
114 # define COPYSIGN copysign
115 #else
116 # define COPYSIGN(a,b) DSIGN(a,b)
117 #endif
118 
119 void palUnpcd( double disco, double * x, double *y ) {
120 
121  const double THIRD = 1.0/3.0;
122 
123  double rp,q,r,d,w,s,t,f,c,t3,f1,f2,f3,w1,w2,w3;
124  double c2;
125 
126  /* Distance of the point from the origin. */
127  rp = sqrt( (*x)*(*x)+(*y)*(*y));
128 
129  /* If zero, or if no distortion, no action is necessary. */
130  if (rp != 0.0 && disco != 0.0) {
131 
132  /* Begin algebraic solution. */
133  q = 1.0/(3.0*disco);
134  r = rp/(2.0*disco);
135  w = q*q*q+r*r;
136 
137  /* Continue if one real root, or three of which only one is positive. */
138  if (w > 0.0) {
139 
140  d = sqrt(w);
141  w = r+d;
142  s = COPYSIGN(pow(fabs(w),THIRD),w);
143  w = r-d;
144  t = COPYSIGN(pow(fabs(w),THIRD),w);
145  f = s+t;
146 
147  } else {
148  /* Three different real roots: use geometrical method instead. */
149  w = 2.0/sqrt(-3.0*disco);
150  c = 4.0*rp/(disco*w*w*w);
151  c2 = c*c;
152  s = sqrt(1.0-DMIN(c2,1.0));
153  t3 = atan2(s,c);
154 
155  /* The three solutions. */
156  f1 = w*cos((PAL__D2PI-t3)/3.0);
157  f2 = w*cos((t3)/3.0);
158  f3 = w*cos((PAL__D2PI+t3)/3.0);
159 
160  /* Pick the one that moves [X,Y] least. */
161  w1 = fabs(f1-rp);
162  w2 = fabs(f2-rp);
163  w3 = fabs(f3-rp);
164  if (w1 < w2) {
165  f = ( w1 < w3 ? f1 : f3 );
166  } else {
167  f = ( w2 < w3 ? f2 : f3 );
168  }
169  }
170 
171  /* Remove the distortion. */
172  f = f/rp;
173  *x *= f;
174  *y *= f;
175  }
176 }
void palUnpcd(double disco, double *x, double *y)
Definition: palUnpcd.c:119
#define DMIN(A, B)
Definition: palmac.h:129
double w
Definition: palObs.c:168
#define COPYSIGN(a, b)
Definition: palUnpcd.c:116
TT t
Definition: test_client.c:26
static const double PAL__D2PI
Definition: palmac.h:66