|
Isis 3.0 Developer's Reference (API) |
Home |
00001 #ifndef GruenTypes_h 00002 #define GruenTypes_h 00003 00026 #include <cmath> 00027 #include <iostream> 00028 #include <sstream> 00029 #include <iomanip> 00030 00031 #include <tnt/tnt_array1d.h> 00032 #include <tnt/tnt_array2d.h> 00033 #include <tnt/tnt_array2d_utils.h> 00034 00035 #include "Affine.h" 00036 #include "Chip.h" 00037 #include "Constants.h" 00038 #include "IException.h" 00039 #include "PvlKeyword.h" 00040 #include "SpecialPixel.h" 00041 00042 00043 namespace Isis { 00044 00045 typedef Affine::AMatrix GMatrix; 00046 typedef TNT::Array1D<double> GVector; 00047 00048 // Constraints 00049 enum { NCONSTR = 8 }; 00050 00069 class Coordinate { 00070 public: 00071 Coordinate() : m_y(Null), m_x(Null) { } 00072 Coordinate(double y, double x) : m_y(y), m_x(x) { } 00073 Coordinate(const Chip &chip) : m_y(chip.CubeLine()), 00074 m_x(chip.CubeSample()){ } 00075 ~Coordinate() { } 00076 00078 void setLatLon(const double &latitude, const double &longitude) { 00079 m_y = latitude; 00080 m_x = longitude; 00081 return; 00082 } 00083 00085 void setLineSamp(const double &line, const double &sample) { 00086 m_y = line; 00087 m_x = sample; 00088 return; 00089 } 00090 00092 Coordinate &operator+=(const Coordinate &other) { 00093 if ( isValid() && other.isValid()) { 00094 m_y += other.m_y; 00095 m_x += other.m_x; 00096 } 00097 else { 00098 m_y = m_x = Null; 00099 } 00100 return (*this); 00101 } 00102 00104 Coordinate &operator-=(const Coordinate &other) { 00105 if ( isValid() && other.isValid() ) { 00106 m_y -= other.m_y; 00107 m_x -= other.m_x; 00108 } 00109 else { 00110 m_y = m_x = Null; 00111 } 00112 return (*this); 00113 } 00114 00116 double getDistance(const Coordinate &pntA = Coordinate(0.0, 0.0)) const { 00117 double yd = pntA.m_y - m_y; 00118 double xd = pntA.m_x - m_x; 00119 return (std::sqrt((xd * xd) + (yd * yd))); 00120 } 00121 00123 inline bool isValid() const { 00124 return ( !(IsSpecial(m_x) || IsSpecial(m_y))); 00125 } 00126 00127 inline double getLatitude() const { return (m_y); } 00128 inline double getLongitude() const { return (m_x); } 00129 inline double getLine() const { return (m_y); } 00130 inline double getSample() const { return (m_x); } 00131 00132 double m_y; // Overloaded as Latitude or line 00133 double m_x; // Overloaded as Longitude or sample 00134 }; 00135 00136 00146 inline Coordinate operator+(const Coordinate &A, const Coordinate &B) { 00147 if ( A.isValid() && B.isValid() ) { 00148 return (Coordinate(A.m_y+B.m_y, A.m_x+B.m_x)); 00149 } 00150 else { 00151 return (Coordinate()); 00152 } 00153 } 00154 00164 inline Coordinate operator-(const Coordinate &A, const Coordinate &B) { 00165 if ( A.isValid() && B.isValid() ) { 00166 return (Coordinate(A.m_y-B.m_y, A.m_x-B.m_x)); 00167 } 00168 else { 00169 return (Coordinate()); 00170 } 00171 } 00172 00187 class PointPair { 00188 public: 00189 PointPair() : m_left(), m_right() { } 00190 PointPair(const double &line, const double &sample) : m_left(line, sample), 00191 m_right() { } 00192 PointPair(const Coordinate &left, 00193 const Coordinate &right = Coordinate()) : m_left(left), 00194 m_right(right) { } 00195 00197 inline bool isValid() const { 00198 return (m_left.isValid() && m_right.isValid()); 00199 } 00200 inline const Coordinate &getLeft() const { return (m_left); } 00201 inline const Coordinate &getRight() const { return (m_right); } 00202 00203 inline double getLine() const { return (getLeftLine()); } 00204 inline double getSample() const { return (getLeftSample()); } 00205 inline double getLeftLine() const { return (m_left.getLine()); } 00206 inline double getLeftSample() const { return (m_left.getSample()); } 00207 inline double getRightLine() const { return (m_right.getLine()); } 00208 inline double getRightSample() const { return (m_right.getSample()); } 00209 00210 Coordinate m_left; // Left image line/sample 00211 Coordinate m_right; // Right image line/sample 00212 }; 00213 00214 00222 class Radiometric { 00223 public: 00224 Radiometric() : m_shift(0.0), m_gain(0.0) { } 00225 Radiometric(const double &shift, const double &gain) : 00226 m_shift(shift), m_gain(gain) { } 00227 00228 inline double Shift() const { return (m_shift); } 00229 inline double Gain() const { return (m_gain); } 00230 00231 00233 Radiometric &operator+=(const Radiometric &B) { 00234 m_shift += B.m_shift; 00235 m_gain += B.m_gain; 00236 return (*this); 00237 } 00238 00239 double m_shift; // Radiometric shift 00240 double m_gain; // Radiometric gain 00241 }; 00242 00244 inline Radiometric operator+(const Radiometric &A, const Radiometric &B) { 00245 return (Radiometric(A.m_shift+B.m_shift, A.m_gain+B.m_gain)); 00246 } 00247 00248 00258 class AffineRadio { 00259 public: 00260 AffineRadio() : m_affine(Affine::getIdentity()), m_radio() {} 00261 AffineRadio(const GMatrix &A) : m_affine(A), m_radio() { } 00262 AffineRadio(const GMatrix &M, const double &shift, 00263 const double &gain) : m_affine(M), m_radio(shift, gain) { } 00264 AffineRadio(const GVector &alpha) : m_affine(), m_radio() { 00265 clone(alpha); // Clone from an alpha matrix 00266 } 00267 AffineRadio(const Radiometric &radio) : m_affine(Affine::getIdentity()), 00268 m_radio(radio) { } 00269 ~AffineRadio() { } 00270 00272 AffineRadio &operator+=(const AffineRadio &other) { 00273 m_affine = m_affine + (other.m_affine - Affine::getIdentity()); 00274 m_radio += other.m_radio; 00275 return (*this); 00276 } 00277 00279 void Translate(const Coordinate &offset) { 00280 GMatrix trans = Affine::getIdentity(); 00281 trans[0][2] = offset.getSample(); 00282 trans[1][2] = offset.getLine(); 00283 m_affine = TNT::matmult(trans, m_affine); 00284 return; 00285 } 00286 00288 Coordinate getPoint(const Coordinate &location) const { 00289 double x = m_affine[0][0] * location.getSample() + 00290 m_affine[0][1] * location.getLine() + m_affine[0][2]; 00291 double y = m_affine[1][0] * location.getSample() + 00292 m_affine[1][1] * location.getLine() + m_affine[1][2]; 00293 return (Coordinate(y, x)); 00294 } 00295 00296 GMatrix m_affine; // Affine transform 00297 Radiometric m_radio; // Radiometric gain and shift 00298 00299 private: 00301 void clone(const GVector &alpha) { 00302 if ( alpha.dim1() != 8 ) { 00303 QString mess = "Alpha array for AffineRadio must have 8 elements " 00304 " but has " + toString(alpha.dim1()); 00305 throw IException(IException::Programmer, mess, _FILEINFO_); 00306 } 00307 m_affine = Affine::getIdentity(); 00308 m_affine[0][0] += alpha[1]; 00309 m_affine[0][1] += alpha[2]; 00310 m_affine[0][2] += alpha[0]; 00311 00312 m_affine[1][0] += alpha[4]; 00313 m_affine[1][1] += alpha[5]; 00314 m_affine[1][2] += alpha[3]; 00315 00316 m_radio.m_shift = alpha[6]; 00317 m_radio.m_gain = alpha[7]; 00318 } 00319 }; 00320 00321 00335 struct AffineTolerance { 00336 public: 00337 AffineTolerance() : m_transTol(0.1), m_scaleTol(0.5), m_shearTol(0.5) { } 00338 AffineTolerance(const double &transTol, const double &scaleTol, 00339 const double &shearTol) : m_transTol(transTol), 00340 m_scaleTol(scaleTol), 00341 m_shearTol(shearTol) { } 00342 ~AffineTolerance() { } 00343 00344 double m_transTol; // Affine translation tolerance 00345 double m_scaleTol; // Affine scale tolerance 00346 double m_shearTol; // Affine shear tolerance 00347 }; 00348 00349 00364 class Threshold { 00365 public: 00366 Threshold() : m_thresh(6, 0.0) { } 00367 Threshold(const Chip &chip, const AffineTolerance &tolerance) : m_thresh(6) { 00368 m_thresh[0] = tolerance.m_scaleTol / (((double)(chip.Samples() - 1)) / 2.0); 00369 m_thresh[1] = tolerance.m_shearTol / (((double)(chip.Lines() - 1)) / 2.0); 00370 m_thresh[2] = tolerance.m_transTol; 00371 00372 m_thresh[3] = tolerance.m_shearTol / (((double)(chip.Samples() - 1)) / 2.0); 00373 m_thresh[4] = tolerance.m_scaleTol / (((double)(chip.Lines() - 1)) / 2.0); 00374 m_thresh[5] = tolerance.m_transTol; 00375 } 00376 ~Threshold() { } 00377 00379 bool hasConverged(const AffineRadio &affine) const { 00380 GMatrix Malpha = affine.m_affine - Affine::getIdentity(); 00381 const double *alpha = Malpha[0]; 00382 for ( int i = 0 ; i < m_thresh.dim1() ; i++ ) { 00383 if ( std::fabs(alpha[i]) >= m_thresh[i] ) return (false); 00384 } 00385 return (true); // If all values are below threshold 00386 } 00387 00388 GVector m_thresh; 00389 }; 00390 00391 00399 struct Analysis { 00400 Analysis() : m_npts(0), m_variance(0.0), m_sevals(), 00401 m_kmat(), m_status(-1) { 00402 for ( int i = 0 ; i < 2 ; i++ ) { 00403 m_sevals[i] = 999.0; 00404 m_kmat[i] = 999.0; 00405 } 00406 } 00407 ~Analysis() { } 00408 00409 inline bool isValid() const { return (m_status == 0); } 00410 00412 inline double getEigen() const { 00413 double eigen = std::sqrt(m_sevals[0] * m_sevals[0] + 00414 m_sevals[1] * m_sevals[1]); 00415 return (eigen); 00416 } 00417 00419 inline void setZeroState() { 00420 for ( int i = 0 ; i < 2 ; i++ ) { 00421 m_sevals[i] = 0.0; 00422 m_kmat[i] = 0.0; 00423 } 00424 m_status = 0; 00425 return; 00426 } 00427 00428 BigInt m_npts; 00429 double m_variance; 00430 double m_sevals[2]; // 2 sorted eigenvalues 00431 double m_kmat[2]; // Sample/Line uncertainty 00432 int m_status; // Status 00433 }; 00434 00435 00449 class MatchPoint { 00450 public: 00451 MatchPoint() : m_point(), m_affine(), m_analysis(), m_status(-1) { } 00452 MatchPoint(const AffineRadio &radio) : m_point(), m_affine(radio), 00453 m_analysis(), m_status(-1) { } 00454 MatchPoint(const PointPair &point) : m_point(point), m_affine(), 00455 m_analysis(), m_status(-1) { } 00456 ~MatchPoint() { } 00457 00458 inline int getStatus() const { return (m_status); } 00459 const MatchPoint &setStatus(int status) { 00460 m_status = status; 00461 return (*this); 00462 } 00463 00464 inline bool isValid() const { return (m_status == 0); } 00465 inline double getEigen() const { return (m_analysis.getEigen()); } 00466 00468 Coordinate getAffinePoint(const Coordinate &coord = Coordinate(0.0, 0.0)) 00469 const { 00470 return (m_affine.getPoint(coord)); 00471 } 00472 00473 PointPair m_point; // Pattern (left) and search (right) points 00474 AffineRadio m_affine; // Resulting Affine transform 00475 Analysis m_analysis; // Error analysis of registration 00476 int m_nIters; // Number of iterations required to match 00477 int m_status; // Status - good is 0 00478 }; 00479 00480 } // namespace Isis 00481 #endif