Isis 3 Programmer Reference
Chip.cpp
Go to the documentation of this file.
1 
24 #include "Chip.h"
25 
26 
27 
28 
29 #include "Camera.h"
30 #include "Cube.h"
31 #include "IException.h"
32 #include "Interpolator.h"
33 #include "IString.h"
34 #include "LineManager.h"
35 #include "PolygonTools.h"
36 #include "Portal.h"
37 #include "Projection.h"
38 #include "Statistics.h"
39 #include "TProjection.h"
40 
41 #include <algorithm>
42 #include <cmath>
43 #include <string>
44 #include <vector>
45 
46 #include <geos/geom/Point.h>
47 #include <tnt/tnt_array2d_utils.h>
48 
49 
50 
51 using namespace std;
52 namespace Isis {
53 
57  Chip::Chip() {
58  Init(3, 3);
59  }
60 
66  Chip::Chip(const Chip &other) {
67  m_chipSamples = other.m_chipSamples;
68  m_chipLines = other.m_chipLines;
69  m_buf = other.m_buf;
70  m_tackSample = other.m_tackSample;
71  m_tackLine = other.m_tackLine;
72 
73  m_cubeTackSample = other.m_cubeTackSample;
74  m_cubeTackLine = other.m_cubeTackLine;
75 
76  m_validMinimum = other.m_validMinimum;
77  m_validMaximum = other.m_validMaximum;
78 
79  m_chipSample = other.m_chipSample;
80  m_chipLine = other.m_chipLine;
81  m_cubeSample = other.m_cubeSample;
82  m_cubeLine = other.m_cubeLine;
83 
84  if (other.m_clipPolygon) {
85  m_clipPolygon = PolygonTools::MakeMultiPolygon(
86  other.m_clipPolygon->clone());
87  }
88  else {
89  m_clipPolygon = NULL;
90  }
91 
92  m_affine = other.m_affine;
93  m_readInterpolator = other.m_readInterpolator;
94  m_filename = other.m_filename;
95  }
96 
97 
104  Chip::Chip(const int samples, const int lines) {
105  Init(samples, lines);
106  }
107 
108 
110  Chip::~Chip() {
111  if (m_clipPolygon != NULL) delete m_clipPolygon;
112  }
113 
114 
122  void Chip::SetAllValues(const double &d) {
123  for (unsigned int i = 0; i < m_buf.size(); i++) {
124  fill(m_buf[i].begin(), m_buf[i].end(), d);
125  }
126  }
127 
128 
138  void Chip::Init(const int samples, const int lines) {
139  SetReadInterpolator(Interpolator::CubicConvolutionType);
140  SetSize(samples, lines);
141  SetValidRange();
142  m_clipPolygon = NULL;
143  }
144 
145 
156  void Chip::SetSize(const int samples, const int lines) {
157  if ( samples <= 0.0 || lines <= 0.0 ) {
158  QString msg;
159  msg += "Unable to set chip size to [";
160  msg += toString(samples) + ", ";
161  msg += toString(lines) + "]. Samples and lines must be greater than zero.";
162  throw IException(IException::User, msg, _FILEINFO_);
163  }
164  m_chipSamples = samples;
165  m_chipLines = lines;
166  m_buf.clear();
167  m_buf.resize(lines);
168  for (int i = 0; i < lines; i++) {
169  m_buf[i].resize(samples);
170  }
171  m_affine.Identity();
172  m_tackSample = ((samples - 1) / 2) + 1;
173  m_tackLine = ((lines - 1) / 2) + 1;
174  }
175 
176 
184  bool Chip::IsInsideChip(double sample, double line) {
185  double minSamp = m_cubeTackSample - ((m_chipSamples - 1) / 2);
186  double maxSamp = m_cubeTackSample + ((m_chipSamples - 1) / 2);
187 
188  double minLine = m_cubeTackLine - ((m_chipLines - 1) / 2);
189  double maxLine = m_cubeTackLine + ((m_chipLines - 1) / 2);
190 
191  if ( sample < minSamp || sample > maxSamp ) return false;
192  if ( line < minLine || line > maxLine ) return false;
193  return true;
194  }
195 
196 
204  void Chip::TackCube(const double cubeSample, const double cubeLine) {
205  m_cubeTackSample = cubeSample;
206  m_cubeTackLine = cubeLine;
207  m_affine.Identity();
208  m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
209  }
210 
211 
225  void Chip::Load(Cube &cube, const double rotation, const double scale, const int band) {
226  // Initialize our affine transform
227  m_affine.Identity();
228 
229  // We want an affine which translates from chip to cube. Note that we want to give adjusted
230  // chip coordinates such that (0,0) is at the chip tack point and maps to the cube tack point.
231  m_affine.Scale(scale);
232  m_affine.Rotate(rotation);
233  m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
234 
235  // Now go read the data from the cube into the chip
236  Read(cube, band);
237 
238  // Store off the cube address in case someone wants to match this chip
239  m_filename = cube.fileName();
240  }
241 
242 
266  void Chip::Load(Cube &cube, const Affine &affine, const bool &keepPoly, const int band) {
267 
268  // Set the tackpoint center to the cube location
269  SetTransform(affine);
270  SetChipPosition(TackSample(), TackLine());
271 
272  // Remove the clipping polygon if requested
273  if (!keepPoly) {
274  delete m_clipPolygon;
275  m_clipPolygon = 0;
276  }
277 
278  // Now go read the data from the cube into the chip
279  Read(cube, band);
280 
281  // Store off the cube address in case someone wants to match this chip
282  m_filename = cube.fileName();
283  }
284 
285 
322  void Chip::Load(Cube &cube, Chip &match, Cube &matchChipCube, const double scale, const int band)
323  {
324  // See if the match cube has a camera or projection
325  Camera *matchCam = NULL;
326  TProjection *matchProj = NULL;
327  try {
328  matchCam = matchChipCube.camera();
329  }
330  catch (IException &error1) {
331  try {
332  matchProj = (TProjection *) matchChipCube.projection();
333  }
334  catch (IException &error2) {
335  QString msg = "Can not geom chip. ";
336  msg += "Match chip cube [" + matchChipCube.fileName();
337  msg += "] is not a camera or map projection";
338 
339  IException fullError(IException::User, msg, _FILEINFO_);
340  fullError.append(error1);
341  fullError.append(error2);
342 
343  throw fullError;
344  }
345  }
346 
347  // See if the cube we are loading has a camera/projection
348  Camera *cam = NULL;
349  Projection *proj = NULL;
350  try {
351  cam = cube.camera();
352  }
353  catch (IException &error1) {
354  try {
355  proj = cube.projection();
356  }
357  catch (IException &error2) {
358  QString msg = "Can not geom chip. ";
359  msg += "Chip cube [" + cube.fileName();
360  msg += "] is not a camera or map projection";
361 
362  IException fullError(IException::User, msg, _FILEINFO_);
363  fullError.append(error1);
364  fullError.append(error2);
365 
366  throw fullError;
367  }
368  }
369 
370  // Ok we can attempt to create an affine transformation that maps our chip to the match chip.
371  // We will need a set of at least 3 control points so we can fit the affine transform.
372  // We will try to find 4 points, one from each corner of the chip.
373  vector<double> x(4), y(4);
374  vector<double> xp(4), yp(4);
375 
376  // Choose these control points by beginning at each corner and moving inward in the chip
377  // until an acceptable point is found
378  // i = 0, start at upper left corner (1, 1)
379  // i = 1, start at lower left corner (1, Lines()-1)
380  // i = 2, start at upper right corner (Samples()-1, 1)
381  // i = 3, start at lower right corner (Samples()-1, Lines()-1)
382  for (int i = 0; i < (int) xp.size(); i++) {
383  // define initial values for starting/ending sample/line for each index
384  int startSamp = 1;
385  int startLine = 1;
386  int endSamp = Samples() - 1;
387  int endLine = Lines() - 1;
388 
389  bool pointfound = false;
390  while (!pointfound) {
391  // start and end may cross (see MovePoints())
392  // if we move outside chip, break out of loop
393  if (startSamp < 1 || startSamp > Samples() - 1 ||
394  endSamp < 1 || endSamp > Samples() - 1 ||
395  startLine < 1 || startLine > Lines() - 1 ||
396  endLine < 1 || endLine > Lines() - 1) {
397  // unable to find acceptable control point from this corner
398  // erase point and go to the next corner
399  x.erase(x.begin() + i);
400  y.erase(y.begin() + i);
401  xp.erase(xp.begin() + i);
402  yp.erase(yp.begin() + i);
403  i--;
404  break;
405  }
406  int chipSamp, chipLine;
407  if (i < 2) {
408  chipSamp = startSamp;
409  }
410  else {
411  chipSamp = endSamp;
412  }
413  if (i % 2 == 0) {
414  chipLine = startLine;
415  }
416  else {
417  chipLine = endLine;
418  }
419  // Determine the offset from the tack point in our chip to one of the four corners.
420  int sampOffset = chipSamp - TackSample();
421  int lineOffset = chipLine - TackLine();
422 
423  // Use this offset to compute a chip position in the match chip.
424  double matchChipSamp = match.TackSample() + sampOffset;
425  double matchChipLine = match.TackLine() + lineOffset;
426 
427  // Now get the lat/lon at that chip position.
428  match.SetChipPosition(matchChipSamp, matchChipLine);
429  double lat, lon;
430  if (matchCam != NULL) {
431  matchCam->SetImage(match.CubeSample(), match.CubeLine());
432  if (!matchCam->HasSurfaceIntersection() ) {
433  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
434  startSamp = newlocation[0];
435  startLine = newlocation[1];
436  endSamp = newlocation[2];
437  endLine = newlocation[3];
438  continue;
439  }
440  lat = matchCam->UniversalLatitude();
441  lon = matchCam->UniversalLongitude();
442  }
443  else {
444  matchProj->SetWorld(match.CubeSample(), match.CubeLine() );
445  if (!matchProj->IsGood() ) {
446  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
447  startSamp = newlocation[0];
448  startLine = newlocation[1];
449  endSamp = newlocation[2];
450  endLine = newlocation[3];
451  continue;
452  }
453  lat = matchProj->UniversalLatitude();
454  lon = matchProj->UniversalLongitude();
455  }
456 
457  // Now use that lat/lon to find a line/sample in our chip
458  double line, samp;
459  if (cam != NULL) {
460  cam->SetUniversalGround(lat, lon);
461  if (!cam->HasSurfaceIntersection() ) {
462  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
463  startSamp = newlocation[0];
464  startLine = newlocation[1];
465  endSamp = newlocation[2];
466  endLine = newlocation[3];
467  continue;
468  }
469  samp = cam->Sample(); // getting negative sample?!?!?!
470  line = cam->Line();
471  }
472  else {
473  proj->SetUniversalGround(lat, lon);
474  if (!proj->IsGood()) {
475  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
476  startSamp = newlocation[0];
477  startLine = newlocation[1];
478  endSamp = newlocation[2];
479  endLine = newlocation[3];
480  continue;
481  }
482  samp = proj->WorldX();
483  line = proj->WorldY();
484  }
485 
486  // if (line < 1 || line > cube.lineCount()) continue;
487  // if (samp < 1 || samp > cube.sampleCount()) continue;
488 
489  // Ok save this control point
490  pointfound = true;
491  x[i] = sampOffset;
492  y[i] = lineOffset;
493  xp[i] = samp;
494  yp[i] = line;
495 
496  // If we get 3 points on the same line, affine transform will fail.
497  // Choose a one degree default tolerance for linearity check method.
498  double tol = 1.0;
499  // If we have already removed a point, use a stricter tolerance of 2 degrees.
500  if (xp.size() == 3) {
501  tol = 2.0;
502  }
503  if (i > 1) {
504  if ( PointsColinear(xp[0], yp[0], xp[1], yp[1], xp[i], yp[i], tol) ) {
505  // try to find a point further along that is not colinear
506  pointfound = false;
507  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
508  startSamp = newlocation[0];
509  startLine = newlocation[1];
510  endSamp = newlocation[2];
511  endLine = newlocation[3];
512  continue;
513  }
514  }
515  }
516  }
517 
518  if (xp.size() < 3) {
519  QString msg = "Cannot find enough points to perform Affine transformation. ";
520  msg += "Unable to load chip from [" + cube.fileName();
521  msg += "] to match chip from [" + matchChipCube.fileName() + "].";
522  throw IException(IException::User, msg, _FILEINFO_);
523  }
524 
525  // Now take our control points and create the affine map
526  m_affine.Solve(&x[0], &y[0], &xp[0], &yp[0], (int)x.size());
527 
528  // TLS 8/3/06 Apply scale
529  m_affine.Scale(scale);
530 
531  // Finally we need to make the affine map the tack point to the requested cube sample/line
532  m_affine.Compute(0.0, 0.0);
533  double cubeSampleOffset = m_cubeTackSample - m_affine.xp();
534  double cubeLineOffset = m_cubeTackLine - m_affine.yp();
535  m_affine.Translate(cubeSampleOffset, cubeLineOffset);
536 
537  // Now go read the data from the cube into the chip
538  Read(cube, band);
539 
540  // Store off the cube address in case someone wants to match
541  // this chip
542  m_filename = cube.fileName();
543  }
544 
545 
568  bool Chip::PointsColinear(const double x0, const double y0, const double x1, const double y1,
569  const double x2, const double y2, const double tol) {
570  // check angles at each point of the triangle composed of the 3 points
571  // if any angle is near 0 or 180 degrees, then the points are almost colinear
572 
573  // we have the following property:
574  // sin(theta) = |v x w|/(|v|*|w|) where
575  // v=(vx,vy) and w=(wx,wy) are the vectors that define the angle theta
576  // |v| is the magnitude (norm) of the vector. In 2D, this is |v| = sqrt(vx^2 + vy^2)
577  // v x w is the cross product of the vectors. In 2D, this is v x w = vx*wy-vy*wx
578  // See equations (5) and (6) at http://mathworld.wolfram.com/CrossProduct.html
579 
580 
581  // first find the vectors that define the angles at each point
582  // For example, if we shift the point P0 to the origin,
583  // the vectors defining the angle at P0
584  // are v01 = (x1-x0, y1-y0) and v02 = (x2-x0, y2-y0)
585  // Note: v10 = -v01 and |v x w| = |w x v|
586  // so we only need 3 vectors and the order we use these doesn't matter
587  vector<double> v01, v12, v20;
588  v01.push_back(x1 - x0);
589  v01.push_back(y1 - y0);
590  v12.push_back(x2 - x1);
591  v12.push_back(y2 - y1);
592  v20.push_back(x0 - x2);
593  v20.push_back(y0 - y2);
594 
595  // sin(angle at P0) = |v01 x v02|/(|v01|*|v02|) =
596  // |v01x*v02y-v01y*v02x|/(sqrt(v01x^2+v01y^2)*sqrt(v01x^2+v02y^2))
597  double sinP0 = fabs(v01[0] * v20[1] - v01[1] * v20[0]) /
598  sqrt((pow(v01[0], 2) + pow(v01[1], 2)) * (pow(v12[0], 2) + pow(v12[1], 2)));
599  // sin(angle at P1)
600  double sinP1 = fabs(v12[0] * v20[1] - v12[1] * v20[0]) /
601  sqrt((pow(v12[0], 2) + pow(v12[1], 2)) * (pow(v20[0], 2) + pow(v20[1], 2)));
602  // sin(angle at P2)
603  double sinP2 = fabs(v20[0] * v01[1] - v20[1] * v01[0]) /
604  sqrt((pow(v20[0], 2) + pow(v20[1], 2)) * (pow(v01[0], 2) + pow(v01[1], 2)));
605 
606  // We will seek angles with sine near 0 (thus a multiple of 180 degrees or pi radians)
607  // We will use a tolerance of tol degrees (tol*pi/180 radians)
608  // Compare the smallest sine value to the sine of tol,
609  // if it is less, then the angle is less than tol degrees or
610  // greater than 180-tol degrees, so points are almost colinear
611  double minSinValue = min(sinP0, min(sinP1, sinP2));
612  if ( minSinValue < sin(tol * PI / 180) ) {
613  return true;
614  }
615  else {
616  return false;
617  }
618  }
619 
620 
637  vector<int> Chip::MovePoints(const int startSamp, const int startLine,
638  const int endSamp, const int endLine) {
639  vector<int> newlocations(4);
640  int sinc = (endSamp - startSamp) / 4;
641  // Ensures that the inc can cause start and end to cross
642  if (sinc < 1) {
643  sinc = 1;
644  }
645  int linc = (endLine - startLine) / 3;
646  // Ensures that the inc can cause start and end to cross
647  if (linc < 1) {
648  linc = 1;
649  }
650  newlocations[0] = startSamp + sinc;
651  newlocations[1] = startLine + linc;
652  newlocations[2] = endSamp - sinc;
653  newlocations[3] = endLine - linc;
654  return newlocations;
655  }
656 
665  void Chip::SetChipPosition(const double sample, const double line) {
666  m_chipSample = sample;
667  m_chipLine = line;
668  m_affine.Compute(sample - TackSample(), line - TackLine());
669  m_cubeSample = m_affine.xp();
670  m_cubeLine = m_affine.yp();
671  }
672 
673 
682  void Chip::SetCubePosition(const double sample, const double line) {
683  m_cubeSample = sample;
684  m_cubeLine = line;
685  m_affine.ComputeInverse(sample, line);
686  m_chipSample = m_affine.x() + TackSample();
687  m_chipLine = m_affine.y() + TackLine();
688  }
689 
690 
703  void Chip::SetValidRange(const double minimum, const double maximum) {
704  if (minimum >= maximum) {
705  QString msg = "Unable to set valid chip range to [" + toString(minimum);
706  msg += ", " + toString(maximum) + "]. First parameter must be smaller than the second.";
707  throw IException(IException::Programmer, msg, _FILEINFO_);
708  }
709 
710  m_validMinimum = minimum;
711  m_validMaximum = maximum;
712  }
713 
714 
723  bool Chip::IsValid(double percentage) {
724  int validCount = 0;
725  for (int samp = 1; samp <= Samples(); samp++) {
726  for (int line = 1; line <= Lines(); line++) {
727  if (IsValid(samp, line)) validCount++;
728  }
729  }
730  double validPercentage = 100.0 * (double) validCount /
731  (double)(Samples() * Lines());
732  if (validPercentage < percentage) return false;
733  return true;
734  }
735 
736 
749  Chip Chip::Extract(int samples, int lines, int samp, int line) {
750  if ( samples > Samples() || lines > Lines() ) {
751  QString msg = "Cannot extract sub-chip of size [" + toString(samples);
752  msg += ", " + toString(lines) + "] from chip of size [" + toString(Samples());
753  msg += ", " + toString(Lines()) + "]";
754  throw IException(IException::Programmer, msg, _FILEINFO_);
755  }
756 
757  Chip chipped(samples, lines);
758  for (int oline = 1; oline <= lines; oline++) {
759  for (int osamp = 1; osamp <= samples; osamp++) {
760  int thisSamp = samp + (osamp - chipped.TackSample());
761  int thisLine = line + (oline - chipped.TackLine());
762  if ((thisSamp < 1) ||
763  (thisLine < 1) ||
764  (thisSamp > Samples()) ||
765  (thisLine > Lines()) ) {
766  chipped.SetValue(osamp, oline, Isis::Null);
767  }
768  else {
769  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
770  }
771  }
772  }
773 
774  chipped.m_affine = m_affine;
775  chipped.m_validMinimum = m_validMinimum;
776  chipped.m_validMaximum = m_validMaximum;
777  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
778  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
779 
780  return chipped;
781  }
782 
794  void Chip::Extract(int samp, int line, Chip &chipped) {
795  int samples = chipped.Samples();
796  int lines = chipped.Lines();
797  //chipped.Init(samples, lines);
798  chipped.m_tackSample = ((samples - 1) / 2) + 1;
799  chipped.m_tackLine = ((lines - 1) / 2) + 1;
800 
801  for (int oline = 1; oline <= lines; oline++) {
802  for (int osamp = 1; osamp <= samples; osamp++) {
803  int thisSamp = samp + (osamp - chipped.TackSample());
804  int thisLine = line + (oline - chipped.TackLine());
805  if ((thisSamp < 1) ||
806  (thisLine < 1) ||
807  (thisSamp > Samples()) ||
808  (thisLine > Lines()) ) {
809  chipped.SetValue(osamp, oline, Isis::Null);
810  }
811  else {
812  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
813  }
814  }
815  }
816 
817  chipped.m_affine = m_affine;
818  chipped.m_validMinimum = m_validMinimum;
819  chipped.m_validMaximum = m_validMaximum;
820  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
821  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
822 
823  return;
824  }
825 
826 
868  void Chip::Extract(Chip &chipped, Affine &affine) {
869  // Create an interpolator and portal for interpolation
870  Interpolator interp(Interpolator::BiLinearType);
871  Portal port(interp.Samples(), interp.Lines(), Isis::Double,
872  interp.HotSample(), interp.HotLine());
873 
874  int samples = chipped.Samples();
875  int lines = chipped.Lines();
876 
877  for (int oline = 1; oline <= lines; oline++) {
878  int relativeLine = oline - chipped.TackLine();
879  for (int osamp = 1; osamp <= samples; osamp++) {
880  int relativeSamp = osamp - chipped.TackSample();
881  affine.Compute(relativeSamp, relativeLine);
882  double xp = affine.xp() + TackSample();
883  double yp = affine.yp() + TackLine();
884  port.SetPosition(xp, yp, 1);
885  for (int i = 0; i < port.size(); i++) {
886  int csamp = port.Sample(i);
887  int cline = port.Line(i);
888  if ((csamp < 1) ||
889  (cline < 1) ||
890  (csamp > Samples()) ||
891  (cline > Lines()) ) {
892  port[i] = Isis::Null;
893  }
894  else {
895  port[i] = GetValue(csamp, cline);
896  }
897  }
898  chipped.SetValue(osamp, oline, interp.Interpolate(xp, yp, port.DoubleBuffer()));
899  }
900  }
901 
902  chipped.m_validMinimum = m_validMinimum;
903  chipped.m_validMaximum = m_validMaximum;
904  chipped.m_filename = m_filename;
905 
906  // Make necessary adjustments to remaining chip elements. Note that this matrix multiply
907  // acheives a completed transform of two Affine matrices.
908  // No translations are required - only update tack points.
909  chipped.m_affine = Affine(TNT::matmult(affine.Forward(), m_affine.Forward()));
910 
911  affine.Compute(0.0, 0.0);
912  chipped.m_cubeTackSample = m_cubeTackSample + affine.xp();
913  chipped.m_cubeTackLine = m_cubeTackLine + affine.yp();
914 
915  chipped.m_chipSample = chipped.TackSample();
916  chipped.m_chipLine = chipped.TackLine();
917  chipped.m_cubeSample = chipped.m_cubeTackSample;
918  chipped.m_cubeLine = chipped.m_cubeTackLine;
919 
920  return;
921  }
922 
923 
931  Isis::Statistics *Chip::Statistics() {
932  Isis::Statistics *stats = new Isis::Statistics();
933 
934  stats->SetValidRange(m_validMinimum, m_validMaximum);
935 
936  for (int i = 0; i < m_chipSamples; i++) {
937  stats->AddData(&m_buf[i][0], m_chipLines);
938  }
939 
940  return stats;
941  }
942 
943 
961  void Chip::Read(Cube &cube, const int band) {
962  // Create an interpolator and portal for geoming
963  Interpolator interp(m_readInterpolator);
964  Portal port(interp.Samples(), interp.Lines(), cube.pixelType(),
965  interp.HotSample(), interp.HotLine());
966  // Loop through the pixels in the chip and geom them
967  for (int line = 1; line <= Lines(); line++) {
968  for (int samp = 1; samp <= Samples(); samp++) {
969  SetChipPosition((double)samp, (double)line);
970  if ((CubeSample() < 0.5) ||
971  (CubeLine() < 0.5) ||
972  (CubeSample() > cube.sampleCount() + 0.5) ||
973  (CubeLine() > cube.lineCount() + 0.5)) {
974 
975  m_buf[line-1][samp-1] = Isis::NULL8;
976  }
977  else if (m_clipPolygon == NULL) {
978  port.SetPosition(CubeSample(), CubeLine(), band);
979  cube.read(port);
980  m_buf[line-1][samp-1] =
981  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
982  }
983  else {
984  geos::geom::Point *pnt = globalFactory.createPoint(
985  geos::geom::Coordinate(CubeSample(), CubeLine()));
986  if (pnt->within(m_clipPolygon)) {
987  port.SetPosition(CubeSample(), CubeLine(), band);
988  cube.read(port);
989  m_buf[line-1][samp-1] =
990  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
991  }
992  else {
993  m_buf[line-1][samp-1] = Isis::NULL8;
994  }
995  delete pnt;
996  }
997  }
998  }
999  }
1000 
1001 
1007  void Chip::Write(const QString &filename) {
1008  Cube c;
1009  c.setDimensions(Samples(), Lines(), 1);
1010  c.create(filename);
1011  LineManager line(c);
1012  for (int i = 1; i <= Lines(); i++) {
1013  line.SetLine(i);
1014  for (int j = 1; j <= Samples(); j++) {
1015  line[j-1] = GetValue(j, i);
1016  }
1017  c.write(line);
1018  }
1019  c.close();
1020  }
1021 
1022 
1030  void Chip::SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon) {
1031  if (m_clipPolygon != NULL) delete m_clipPolygon;
1032  m_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1033  }
1034 
1035 
1043  Chip &Chip::operator=(const Chip &other) {
1044  m_chipSamples = other.m_chipSamples;
1045  m_chipLines = other.m_chipLines;
1046  m_buf = other.m_buf;
1047  m_tackSample = other.m_tackSample;
1048  m_tackLine = other.m_tackLine;
1049 
1050  m_cubeTackSample = other.m_cubeTackSample;
1051  m_cubeTackLine = other.m_cubeTackLine;
1052 
1053  m_validMinimum = other.m_validMinimum;
1054  m_validMaximum = other.m_validMaximum;
1055 
1056  m_chipSample = other.m_chipSample;
1057  m_chipLine = other.m_chipLine;
1058  m_cubeSample = other.m_cubeSample;
1059  m_cubeLine = other.m_cubeLine;
1060 
1061  // Free allocated memory.
1062  if (m_clipPolygon) {
1063  delete m_clipPolygon;
1064  m_clipPolygon = NULL;
1065  }
1066 
1067  if (other.m_clipPolygon) {
1068  m_clipPolygon = PolygonTools::MakeMultiPolygon(
1069  other.m_clipPolygon->clone());
1070  }
1071 
1072  m_affine = other.m_affine;
1073  m_readInterpolator = other.m_readInterpolator;
1074  m_filename = other.m_filename;
1075 
1076  return *this;
1077  }
1078 } // end namespace isis
bool SetLine(const int line, const int band=1)
Positions the buffer at the requested line and returns a status indicator if the set was succesful or...
Definition: LineManager.cpp:60
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
Definition: Chip.cpp:665
double HotSample()
Returns the sample coordinate of the center pixel in the buffer for the interpolator.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
double m_validMaximum
valid maximum chip pixel value
Definition: Chip.h:372
double Interpolate(const double isamp, const double iline, const double buf[])
Performs an interpolation on the data according to the parameters set in the constructor.
const double PI
The mathematical constant PI.
Definition: Constants.h:56
double m_cubeLine
cube line set by SetCubePosition
Definition: Chip.h:377
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
Camera * camera()
Return a camera associated with the cube.
Definition: Cube.cpp:1166
A small chip of data used for pattern matching.
Definition: Chip.h:102
Buffer for containing a two dimensional section of an image.
Definition: Portal.h:52
Base class for Map TProjections.
Definition: TProjection.h:182
int sampleCount() const
Definition: Cube.cpp:1452
double m_cubeSample
cube sample set by SetCubePosition
Definition: Chip.h:376
Interpolator::interpType m_readInterpolator
Interpolator type set by.
Definition: Chip.h:385
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception&#39;s causational exc...
Definition: IException.cpp:425
int m_tackSample
Middle sample of the chip.
Definition: Chip.h:365
Namespace for the standard library.
double m_chipSample
chip sample set by SetChip/CubePosition
Definition: Chip.h:374
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround, or SetWorld was with successful or not.
Definition: Projection.cpp:389
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
Projection * projection()
Definition: Cube.cpp:1439
double yp() const
Returns the computed y&#39;.
Definition: Affine.h:110
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Definition: Cube.cpp:932
Buffer manager, for moving through a cube in lines.
Definition: LineManager.h:55
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:396
double m_cubeTackLine
cube line at the chip tack
Definition: Chip.h:369
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:539
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
Definition: Camera.cpp:170
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:107
double xp() const
Returns the computed x&#39;.
Definition: Affine.h:101
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
Base class for Map Projections.
Definition: Projection.h:171
int Lines() const
Definition: Chip.h:122
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
Definition: Affine.cpp:205
Affine basis function.
Definition: Affine.h:80
double m_validMinimum
valid minimum chip pixel value
Definition: Chip.h:371
int Samples()
Returns the number of samples needed by the interpolator.
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
double CubeLine() const
Definition: Chip.h:226
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2702
double m_cubeTackSample
cube sample at the chip tack
Definition: Chip.h:368
double CubeSample() const
Definition: Chip.h:219
void close(bool remove=false)
Closes the cube and updates the labels.
Definition: Cube.cpp:177
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
int m_chipLines
Number of lines in the chip.
Definition: Chip.h:363
int TackSample() const
This method returns a chip&#39;s fixed tack sample; the middle of the chip.
Definition: Chip.h:192
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
PixelType pixelType() const
Definition: Cube.cpp:1403
double UniversalLatitude()
This returns a universal latitude (planetocentric).
QString m_filename
FileName of loaded cube.
Definition: Chip.h:389
AMatrix Forward() const
Returns the forward Affine matrix.
Definition: Affine.h:142
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:512
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Definition: Chip.h:142
Affine m_affine
Transform set by SetTransform.
Definition: Chip.h:382
int m_tackLine
Middle line of the chip.
Definition: Chip.h:366
int Lines()
Returns the number of lines needed by the interpolator.
Pixel interpolator.
Definition: Interpolator.h:51
geos::geom::MultiPolygon * m_clipPolygon
clipping polygon set by SetClipPolygon
Definition: Chip.h:379
int Samples() const
Definition: Chip.h:115
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
double Line()
Returns the current line number.
Definition: Camera.cpp:2722
int lineCount() const
Definition: Cube.cpp:1379
void write(Blob &blob)
This method will write a blob of data (e.g.
Definition: Cube.cpp:763
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
Definition: Projection.cpp:432
Isis exception class.
Definition: IException.h:107
int m_chipSamples
Number of samples in the chip.
Definition: Chip.h:362
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
std::vector< std::vector< double > > m_buf
Chip buffer.
Definition: Chip.h:364
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:154
void create(const QString &cfile)
This method will create an isis cube for writing.
Definition: Cube.cpp:331
double m_chipLine
chip line set by SetChip/CubePosition
Definition: Chip.h:375
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:559
int TackLine() const
This method returns a chip&#39;s fixed tack line; the middle of the chip.
Definition: Chip.h:203
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition: Sensor.cpp:201
IO Handler for Isis Cubes.
Definition: Cube.h:170