source: branches/FACT++_lidctrl_usb/pal/palUnpcd.c@ 18716

Last change on this file since 18716 was 18347, checked in by tbretz, 9 years ago
File size: 4.7 KB
Line 
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
119void 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}
Note: See TracBrowser for help on using the repository browser.