1 //*******************************************************************
2 // Copyright (C) 2000 ImageLinks Inc.
3 //
4 // License: LGPL
5 //
6 // See LICENSE.txt file in the top level directory for more details.
7 //
8 // Author: Garrett Potts
9 //
10 //*************************************************************************
11 // $Id: ossim2dTo2dTransform.cpp 15766 2009-10-20 12:37:09Z gpotts $
12
13 #include <cstdlib>
14 #include <sstream>
15 #include <ossim/base/ossim2dTo2dTransform.h>
16
17
18 RTTI_DEF1(ossim2dTo2dTransform, "ossim2dTo2dTransform", ossimObject);
19
20 #include <ossim/base/ossimKeywordNames.h>
21 #include <ossim/base/ossimKeywordlist.h>
22 #include <ossim/base/ossimNotifyContext.h>
23
24 // ### CREATE_COPY ###
25 // Implementation of static factory method createCopy() requires includes here of ALL 2D-to-2D
26 // transform types that need a deep copy capability:
27 #include <ossim/base/ossimAffineTransform.h>
28 #include <ossim/projection/ossimImageViewAffineTransform.h>
29 #include <ossim/projection/ossimImageViewProjectionTransform.h>
30 #include <ossim/projection/ossimMeanRadialLensDistortion.h>
31 #include <ossim/base/ossimQuadTreeWarp.h>
32 #include <ossim/projection/ossimRadialDecentLensDistortion.h>
33
34 //***
35 // Define Trace flags for use within this file:
36 //***
37 #include <ossim/base/ossimTrace.h>
38 static ossimTrace traceExec ("ossim2dTo2dTransform:exec");
39 static ossimTrace traceDebug ("ossim2dTo2dTransform:debug");
40
41 static const double DEFAULT_THRESHOLD = 1000.0*DBL_EPSILON;
42 static const int DEFAULT_MAX_ITERATIONS = 10;
43
44 //*****************************************************************************
45 // CONSTRUCTOR:
46 //*****************************************************************************
ossim2dTo2dTransform()47 ossim2dTo2dTransform::ossim2dTo2dTransform()
48 :
49 theConvergenceThreshold (DEFAULT_THRESHOLD),
50 theMaxIterations (DEFAULT_MAX_ITERATIONS),
51 theDxDy(1.0, 1.0)
52 {
53 }
54
55 //*****************************************************************************
56 // METHOD:
57 //*****************************************************************************
inverse(const ossimDpt & input,ossimDpt & output) const58 void ossim2dTo2dTransform::inverse(const ossimDpt& input,
59 ossimDpt& output) const
60 {
61 static const char MODULE[] = "ossim2dTo2dTransform::inverse";
62 if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", entering...\n";
63
64 //***
65 // Begin with guess. Forward transform is defined as trasforming left to
66 // right. We are therefore solving for left:
67 //***
68 ossimDpt left = getOrigin();
69 ossimDpt left_dx;
70 ossimDpt left_dy;
71 ossimDpt right;
72 ossimDpt right_dx;
73 ossimDpt right_dy;
74 ossimDpt dr_dx;
75 ossimDpt dr_dy;
76 ossimDpt r_diff;
77 ossimDpt l_diff;
78 double inverse_norm;
79 int iters=0;
80 //***
81 // Begin iterations:
82 //***
83 do
84 {
85 //***
86 // establish perturbed image points about the guessed point:
87 //***
88 left_dx.x = left.x + theDxDy.x;
89 left_dx.y = left.y;
90 left_dy.x = left.x;
91 left_dy.y = left.y + theDxDy.y;
92
93 //***
94 // Compute numerical partials at current guessed point:
95 //***
96 forward(left, right);
97 forward(left_dx, right_dx);
98 forward(left_dy, right_dy);
99
100 dr_dx.x = (right_dx.x - right.x)/theDxDy.x; //e
101 dr_dx.y = (right_dx.y - right.y)/theDxDy.y; //g
102 dr_dy.x = (right_dy.x - right.x)/theDxDy.x; //f
103 dr_dy.y = (right_dy.y - right.y)/theDxDy.y; //h
104
105 //***
106 // Test for convergence:
107 //***
108 r_diff = input - right;
109
110 //***
111 // Compute linearized estimate of image point given gp delta:
112 //***
113 inverse_norm = dr_dy.x*dr_dx.y - dr_dx.x*dr_dy.y; // fg-eh
114
115 if (inverse_norm != 0)
116 {
117 l_diff.x = (-dr_dy.y*r_diff.x + dr_dy.x*r_diff.y)/inverse_norm;
118 l_diff.y = ( dr_dx.y*r_diff.x - dr_dx.x*r_diff.y)/inverse_norm;
119
120 left += l_diff;
121 }
122 else
123 {
124 l_diff.x = 0;
125 l_diff.y = 0;
126 }
127
128 iters++;
129
130 } while (((fabs(l_diff.x) > theConvergenceThreshold) ||
131 (fabs(l_diff.y) > theConvergenceThreshold)) &&
132 (iters < theMaxIterations));
133
134 //***
135 // Note that this error mesage appears only if max count was reached while
136 // iterating. A linear (no iteration) solution would finish with iters =
137 // MAX_NUM_ITERATIONS + 1:
138 //***
139 if (iters == theMaxIterations)
140 {
141 ossimNotify(ossimNotifyLevel_WARN) << "WARNING: " << MODULE << ", exceeded max number of iterations computing inverse "
142 << "transform for point: " << input << "\n";
143 }
144
145 output = left;
146 if (traceExec()) ossimNotify(ossimNotifyLevel_DEBUG) << "DEBUG: " << MODULE << ", returning...\n";
147 return;
148
149 }
150
151 //*****************************************************************************
152 // METHOD:
153 //*****************************************************************************
saveState(ossimKeywordlist & kwl,const char * prefix) const154 bool ossim2dTo2dTransform::saveState(ossimKeywordlist& kwl,
155 const char* prefix) const
156 {
157 kwl.add(prefix,
158 ossimKeywordNames::CONVERGENCE_THRESHOLD_KW,
159 theConvergenceThreshold,
160 true);
161 kwl.add(prefix,
162 ossimKeywordNames::MAX_ITERATIONS_KW,
163 theMaxIterations,
164 true);
165 kwl.add(prefix,
166 "dxdy",
167 ossimString::toString(theDxDy.x) + " " +
168 ossimString::toString(theDxDy.y),
169 true);
170
171 return ossimObject::saveState(kwl, prefix);
172 }
173
174 //*****************************************************************************
175 // METHOD:
176 //*****************************************************************************
loadState(const ossimKeywordlist & kwl,const char * prefix)177 bool ossim2dTo2dTransform::loadState(const ossimKeywordlist& kwl,
178 const char* prefix)
179 {
180 bool result = true;
181
182 const char* buf;
183
184 buf= kwl.find(prefix, ossimKeywordNames::CONVERGENCE_THRESHOLD_KW);
185
186 if (buf)
187 {
188 theConvergenceThreshold = atof(buf);
189 }
190 else
191 {
192 theConvergenceThreshold = .00000000000002;
193 }
194
195 buf= kwl.find(prefix, ossimKeywordNames::MAX_ITERATIONS_KW);
196 if(buf)
197 {
198 theMaxIterations = atoi(buf);
199 }
200 else
201 {
202 theMaxIterations = 10;
203 }
204 const char* dxdy = kwl.find(prefix, "dxdy");
205 if(dxdy)
206 {
207 ossimString tempString(dxdy);
208 std::vector<ossimString> splitArray;
209 tempString = tempString.trim();
210 tempString.split(splitArray, " ");
211 if(splitArray.size()==2)
212 {
213 theDxDy.x = splitArray[0].toDouble();
214 theDxDy.y = splitArray[1].toDouble();
215 }
216 }
217 if(result)
218 {
219 ossimObject::loadState(kwl, prefix);
220 }
221
222 return result;
223 }
224
forward(ossimDpt & modify_this) const225 void ossim2dTo2dTransform::forward(ossimDpt& modify_this) const
226 {
227 ossimDpt output;
228 forward(modify_this, output);
229 modify_this = output;
230 }
231
inverse(ossimDpt & modify_this) const232 void ossim2dTo2dTransform::inverse(ossimDpt& modify_this) const
233 {
234 ossimDpt output;
235 inverse(modify_this, output);
236 modify_this = output;
237 }
238
getOrigin() const239 ossimDpt ossim2dTo2dTransform::getOrigin()const
240 {
241 return ossimDpt(0,0);
242 }
243
setConvergenceThreshold(const double & new_threshold)244 void ossim2dTo2dTransform::setConvergenceThreshold(const double& new_threshold)
245 {
246 theConvergenceThreshold = new_threshold;
247 }
248
setMaxIterations(int new_max_iters)249 void ossim2dTo2dTransform::setMaxIterations(int new_max_iters)
250 {
251 theMaxIterations = new_max_iters;
252 }
253
setDxDy(const ossimDpt & dxdy)254 void ossim2dTo2dTransform::setDxDy(const ossimDpt& dxdy)
255 {
256 theDxDy.x = dxdy.x;
257 theDxDy.y = dxdy.y;
258 }
259
operator =(const ossim2dTo2dTransform & rhs)260 const ossim2dTo2dTransform& ossim2dTo2dTransform::operator=(const ossim2dTo2dTransform& rhs )
261 {
262 if (this != &rhs)
263 {
264 ossimObject::operator = (rhs);
265
266 theConvergenceThreshold = rhs.theConvergenceThreshold;
267 theMaxIterations = rhs.theMaxIterations;
268 theDxDy = rhs.theDxDy;
269 }
270 return *this;
271 }
272
print(std::ostream & out) const273 std::ostream& ossim2dTo2dTransform::print(std::ostream& out) const
274 {
275 out << "convergenceThreshold: " << theConvergenceThreshold << "\n"
276 << "maxIterations: " << theMaxIterations << "\n"
277 << "dxdy: " << theDxDy << "\n";
278 return out;
279 }
280
281