USGS

Isis 3.0 Developer's Reference (API)

Home

GruenTypes.h

Go to the documentation of this file.
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