Isis 3 Programmer Reference
GruenTypes.h
1 #ifndef GruenTypes_h
2 #define GruenTypes_h
3 
8 /* SPDX-License-Identifier: CC0-1.0 */
9 
10 #include <cmath>
11 #include <iostream>
12 #include <sstream>
13 #include <iomanip>
14 
15 #include <tnt/tnt_array1d.h>
16 #include <tnt/tnt_array2d.h>
17 #include <tnt/tnt_array2d_utils.h>
18 
19 #include "Affine.h"
20 #include "Chip.h"
21 #include "Constants.h"
22 #include "IException.h"
23 #include "PvlKeyword.h"
24 #include "SpecialPixel.h"
25 
26 
27 namespace Isis {
28 
29  typedef Affine::AMatrix GMatrix;
30  typedef TNT::Array1D<double> GVector;
31 
32  // Constraints
33  enum { NCONSTR = 8 };
34 
53  class Coordinate {
54  public:
55  Coordinate() : m_y(Null), m_x(Null) { }
56  Coordinate(double y, double x) : m_y(y), m_x(x) { }
57  Coordinate(const Chip &chip) : m_y(chip.CubeLine()),
58  m_x(chip.CubeSample()){ }
59  ~Coordinate() { }
60 
62  void setLatLon(const double &latitude, const double &longitude) {
63  m_y = latitude;
64  m_x = longitude;
65  return;
66  }
67 
69  void setLineSamp(const double &line, const double &sample) {
70  m_y = line;
71  m_x = sample;
72  return;
73  }
74 
76  Coordinate &operator+=(const Coordinate &other) {
77  if ( isValid() && other.isValid()) {
78  m_y += other.m_y;
79  m_x += other.m_x;
80  }
81  else {
82  m_y = m_x = Null;
83  }
84  return (*this);
85  }
86 
88  Coordinate &operator-=(const Coordinate &other) {
89  if ( isValid() && other.isValid() ) {
90  m_y -= other.m_y;
91  m_x -= other.m_x;
92  }
93  else {
94  m_y = m_x = Null;
95  }
96  return (*this);
97  }
98 
100  double getDistance(const Coordinate &pntA = Coordinate(0.0, 0.0)) const {
101  double yd = pntA.m_y - m_y;
102  double xd = pntA.m_x - m_x;
103  return (std::sqrt((xd * xd) + (yd * yd)));
104  }
105 
107  inline bool isValid() const {
108  return ( !(IsSpecial(m_x) || IsSpecial(m_y)));
109  }
110 
111  inline double getLatitude() const { return (m_y); }
112  inline double getLongitude() const { return (m_x); }
113  inline double getLine() const { return (m_y); }
114  inline double getSample() const { return (m_x); }
115 
116  double m_y; // Overloaded as Latitude or line
117  double m_x; // Overloaded as Longitude or sample
118  };
119 
120 
130  inline Coordinate operator+(const Coordinate &A, const Coordinate &B) {
131  if ( A.isValid() && B.isValid() ) {
132  return (Coordinate(A.m_y+B.m_y, A.m_x+B.m_x));
133  }
134  else {
135  return (Coordinate());
136  }
137  }
138 
148  inline Coordinate operator-(const Coordinate &A, const Coordinate &B) {
149  if ( A.isValid() && B.isValid() ) {
150  return (Coordinate(A.m_y-B.m_y, A.m_x-B.m_x));
151  }
152  else {
153  return (Coordinate());
154  }
155  }
156 
171  class PointPair {
172  public:
173  PointPair() : m_left(), m_right() { }
174  PointPair(const double &line, const double &sample) : m_left(line, sample),
175  m_right() { }
176  PointPair(const Coordinate &left,
177  const Coordinate &right = Coordinate()) : m_left(left),
178  m_right(right) { }
179 
181  inline bool isValid() const {
182  return (m_left.isValid() && m_right.isValid());
183  }
184  inline const Coordinate &getLeft() const { return (m_left); }
185  inline const Coordinate &getRight() const { return (m_right); }
186 
187  inline double getLine() const { return (getLeftLine()); }
188  inline double getSample() const { return (getLeftSample()); }
189  inline double getLeftLine() const { return (m_left.getLine()); }
190  inline double getLeftSample() const { return (m_left.getSample()); }
191  inline double getRightLine() const { return (m_right.getLine()); }
192  inline double getRightSample() const { return (m_right.getSample()); }
193 
194  Coordinate m_left; // Left image line/sample
195  Coordinate m_right; // Right image line/sample
196  };
197 
198 
206  class Radiometric {
207  public:
208  Radiometric() : m_shift(0.0), m_gain(0.0) { }
209  Radiometric(const double &shift, const double &gain) :
210  m_shift(shift), m_gain(gain) { }
211 
212  inline double Shift() const { return (m_shift); }
213  inline double Gain() const { return (m_gain); }
214 
215 
218  m_shift += B.m_shift;
219  m_gain += B.m_gain;
220  return (*this);
221  }
222 
223  double m_shift; // Radiometric shift
224  double m_gain; // Radiometric gain
225  };
226 
228  inline Radiometric operator+(const Radiometric &A, const Radiometric &B) {
229  return (Radiometric(A.m_shift+B.m_shift, A.m_gain+B.m_gain));
230  }
231 
232 
242  class AffineRadio {
243  public:
244  AffineRadio() : m_affine(Affine::getIdentity()), m_radio() {}
245  AffineRadio(const GMatrix &A) : m_affine(A), m_radio() { }
246  AffineRadio(const GMatrix &M, const double &shift,
247  const double &gain) : m_affine(M), m_radio(shift, gain) { }
248  AffineRadio(const GVector &alpha) : m_affine(), m_radio() {
249  clone(alpha); // Clone from an alpha matrix
250  }
251  AffineRadio(const Radiometric &radio) : m_affine(Affine::getIdentity()),
252  m_radio(radio) { }
253  ~AffineRadio() { }
254 
257  m_affine = m_affine + (other.m_affine - Affine::getIdentity());
258  m_radio += other.m_radio;
259  return (*this);
260  }
261 
263  void Translate(const Coordinate &offset) {
264  GMatrix trans = Affine::getIdentity();
265  trans[0][2] = offset.getSample();
266  trans[1][2] = offset.getLine();
267  m_affine = TNT::matmult(trans, m_affine);
268  return;
269  }
270 
272  Coordinate getPoint(const Coordinate &location) const {
273  double x = m_affine[0][0] * location.getSample() +
274  m_affine[0][1] * location.getLine() + m_affine[0][2];
275  double y = m_affine[1][0] * location.getSample() +
276  m_affine[1][1] * location.getLine() + m_affine[1][2];
277  return (Coordinate(y, x));
278  }
279 
280  GMatrix m_affine; // Affine transform
281  Radiometric m_radio; // Radiometric gain and shift
282 
283  private:
285  void clone(const GVector &alpha) {
286  if ( alpha.dim1() != 8 ) {
287  QString mess = "Alpha array for AffineRadio must have 8 elements "
288  " but has " + toString(alpha.dim1());
289  throw IException(IException::Programmer, mess, _FILEINFO_);
290  }
291  m_affine = Affine::getIdentity();
292  m_affine[0][0] += alpha[1];
293  m_affine[0][1] += alpha[2];
294  m_affine[0][2] += alpha[0];
295 
296  m_affine[1][0] += alpha[4];
297  m_affine[1][1] += alpha[5];
298  m_affine[1][2] += alpha[3];
299 
300  m_radio.m_shift = alpha[6];
301  m_radio.m_gain = alpha[7];
302  }
303  };
304 
305 
320  public:
321  AffineTolerance() : m_transTol(0.1), m_scaleTol(0.5), m_shearTol(0.5) { }
322  AffineTolerance(const double &transTol, const double &scaleTol,
323  const double &shearTol) : m_transTol(transTol),
324  m_scaleTol(scaleTol),
325  m_shearTol(shearTol) { }
326  ~AffineTolerance() { }
327 
328  double m_transTol; // Affine translation tolerance
329  double m_scaleTol; // Affine scale tolerance
330  double m_shearTol; // Affine shear tolerance
331  };
332 
333 
348  class Threshold {
349  public:
350  Threshold() : m_thresh(6, 0.0) { }
351  Threshold(const Chip &chip, const AffineTolerance &tolerance) : m_thresh(6) {
352  m_thresh[0] = tolerance.m_scaleTol / (((double)(chip.Samples() - 1)) / 2.0);
353  m_thresh[1] = tolerance.m_shearTol / (((double)(chip.Lines() - 1)) / 2.0);
354  m_thresh[2] = tolerance.m_transTol;
355 
356  m_thresh[3] = tolerance.m_shearTol / (((double)(chip.Samples() - 1)) / 2.0);
357  m_thresh[4] = tolerance.m_scaleTol / (((double)(chip.Lines() - 1)) / 2.0);
358  m_thresh[5] = tolerance.m_transTol;
359  }
360  ~Threshold() { }
361 
363  bool hasConverged(const AffineRadio &affine) const {
364  GMatrix Malpha = affine.m_affine - Affine::getIdentity();
365  const double *alpha = Malpha[0];
366  for ( int i = 0 ; i < m_thresh.dim1() ; i++ ) {
367  if ( std::fabs(alpha[i]) >= m_thresh[i] ) return (false);
368  }
369  return (true); // If all values are below threshold
370  }
371 
372  GVector m_thresh;
373  };
374 
375 
383  struct Analysis {
384  Analysis() : m_npts(0), m_variance(0.0), m_sevals(),
385  m_kmat(), m_status(-1) {
386  for ( int i = 0 ; i < 2 ; i++ ) {
387  m_sevals[i] = 999.0;
388  m_kmat[i] = 999.0;
389  }
390  }
391  ~Analysis() { }
392 
393  inline bool isValid() const { return (m_status == 0); }
394 
396  inline double getEigen() const {
397  double eigen = std::sqrt(m_sevals[0] * m_sevals[0] +
398  m_sevals[1] * m_sevals[1]);
399  return (eigen);
400  }
401 
403  inline void setZeroState() {
404  for ( int i = 0 ; i < 2 ; i++ ) {
405  m_sevals[i] = 0.0;
406  m_kmat[i] = 0.0;
407  }
408  m_status = 0;
409  return;
410  }
411 
412  BigInt m_npts;
413  double m_variance;
414  double m_sevals[2]; // 2 sorted eigenvalues
415  double m_kmat[2]; // Sample/Line uncertainty
416  int m_status; // Status
417  };
418 
419 
433  class MatchPoint {
434  public:
435  MatchPoint() : m_point(), m_affine(), m_analysis(), m_status(-1) { }
436  MatchPoint(const AffineRadio &radio) : m_point(), m_affine(radio),
437  m_analysis(), m_status(-1) { }
438  MatchPoint(const PointPair &point) : m_point(point), m_affine(),
439  m_analysis(), m_status(-1) { }
440  ~MatchPoint() { }
441 
442  inline int getStatus() const { return (m_status); }
443  const MatchPoint &setStatus(int status) {
444  m_status = status;
445  return (*this);
446  }
447 
448  inline bool isValid() const { return (m_status == 0); }
449  inline double getEigen() const { return (m_analysis.getEigen()); }
450 
452  Coordinate getAffinePoint(const Coordinate &coord = Coordinate(0.0, 0.0))
453  const {
454  return (m_affine.getPoint(coord));
455  }
456 
457  PointPair m_point; // Pattern (left) and search (right) points
458  AffineRadio m_affine; // Resulting Affine transform
459  Analysis m_analysis; // Error analysis of registration
460  int m_nIters; // Number of iterations required to match
461  int m_status; // Status - good is 0
462  };
463 
464 } // namespace Isis
465 #endif
Isis::Radiometric::operator+=
Radiometric & operator+=(const Radiometric &B)
Add radiometric parameters from another set of parameters.
Definition: GruenTypes.h:217
Isis::AffineRadio::getPoint
Coordinate getPoint(const Coordinate &location) const
Applies the affine transfrom to a point and returns result.
Definition: GruenTypes.h:272
Isis::Affine::AMatrix
TNT::Array2D< double > AMatrix
Affine Matrix.
Definition: Affine.h:67
Isis::Radiometric
Store for radiometric gain and shift parameters.
Definition: GruenTypes.h:206
Isis::PointPair::isValid
bool isValid() const
Left, right and geometry coordinates must all be good data.
Definition: GruenTypes.h:181
Isis::Coordinate::getDistance
double getDistance(const Coordinate &pntA=Coordinate(0.0, 0.0)) const
Computes the distance from this point and the point provided.
Definition: GruenTypes.h:100
Isis::Coordinate::setLatLon
void setLatLon(const double &latitude, const double &longitude)
Use Latitude/Longitude interface.
Definition: GruenTypes.h:62
Isis::AffineRadio
Container for affine and radiometric parameters.
Definition: GruenTypes.h:242
Isis::Chip::CubeSample
double CubeSample() const
Definition: Chip.h:203
Isis::Coordinate
Define a generic Y/X container.
Definition: GruenTypes.h:53
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::IsSpecial
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:197
Isis::Chip::CubeLine
double CubeLine() const
Definition: Chip.h:210
Isis::Chip::Lines
int Lines() const
Definition: Chip.h:106
Isis::Threshold
Compute/test the Affine convergence from given parameters/chip.
Definition: GruenTypes.h:348
Isis::Analysis
Error analysis of Gruen match point solution.
Definition: GruenTypes.h:383
Isis::AffineRadio::operator+=
AffineRadio & operator+=(const AffineRadio &other)
Define update procedure for accumulating Gruen iterations.
Definition: GruenTypes.h:256
Isis::PointPair
Define a point set of left, right and geometry at that location.
Definition: GruenTypes.h:171
Isis::BigInt
long long int BigInt
Big int.
Definition: Constants.h:49
Isis::Affine::getIdentity
static AMatrix getIdentity()
Return an Affine identity matrix.
Definition: Affine.cpp:61
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Coordinate::isValid
bool isValid() const
Check for goodness.
Definition: GruenTypes.h:107
Isis::MatchPoint
Structure containing comprehensive registration info/results.
Definition: GruenTypes.h:433
Isis::Null
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:95
Isis::Analysis::getEigen
double getEigen() const
Returns the square of the of sum of the squares of eigenvalues.
Definition: GruenTypes.h:396
Isis::IException::Programmer
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:146
Isis::Coordinate::operator+=
Coordinate & operator+=(const Coordinate &other)
Add a point to this point.
Definition: GruenTypes.h:76
Isis::AffineRadio::clone
void clone(const GVector &alpha)
Generate a matrix from the Gruen alpha vector.
Definition: GruenTypes.h:285
Isis::MatchPoint::getAffinePoint
Coordinate getAffinePoint(const Coordinate &coord=Coordinate(0.0, 0.0)) const
Return registration offset of a given chip coordinate from center
Definition: GruenTypes.h:452
Isis::operator-
Coordinate operator-(const Coordinate &A, const Coordinate &B)
Subtraction operator for Coordinate.
Definition: GruenTypes.h:148
Isis::AffineTolerance
Container for Affine limits parameters.
Definition: GruenTypes.h:319
Isis::Chip
A small chip of data used for pattern matching.
Definition: Chip.h:86
Isis::Chip::Samples
int Samples() const
Definition: Chip.h:99
Isis::Analysis::setZeroState
void setZeroState()
Resets eigenvalues to 0.
Definition: GruenTypes.h:403
Isis::AffineRadio::Translate
void Translate(const Coordinate &offset)
Apply a translation to the given offset.
Definition: GruenTypes.h:263
Isis::Coordinate::operator-=
Coordinate & operator-=(const Coordinate &other)
Subtract a point from this point.
Definition: GruenTypes.h:88
Isis::Coordinate::setLineSamp
void setLineSamp(const double &line, const double &sample)
Use the Line/Sample interface.
Definition: GruenTypes.h:69
Isis::Threshold::hasConverged
bool hasConverged(const AffineRadio &affine) const
Determines convergence from an affine/radiometric fit.
Definition: GruenTypes.h:363
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::operator+
Coordinate operator+(const Coordinate &A, const Coordinate &B)
Summation operator for Coordinate.
Definition: GruenTypes.h:130