Isis 3.0 Programmer Reference
Back | Home
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(int sample, int line) {
724  double value = (*this)(sample,line);
725  if (value < m_validMinimum) return false;
726  if (value > m_validMaximum) return false;
727  return true;
728  }*/
729 
730 
739  bool Chip::IsValid(double percentage) {
740  int validCount = 0;
741  for (int samp = 1; samp <= Samples(); samp++) {
742  for (int line = 1; line <= Lines(); line++) {
743  if (IsValid(samp, line)) validCount++;
744  }
745  }
746  double validPercentage = 100.0 * (double) validCount /
747  (double)(Samples() * Lines());
748  if (validPercentage < percentage) return false;
749  return true;
750  }
751 
752 
765  Chip Chip::Extract(int samples, int lines, int samp, int line) {
766  if ( samples > Samples() || lines > Lines() ) {
767  QString msg = "Cannot extract sub-chip of size [" + toString(samples);
768  msg += ", " + toString(lines) + "] from chip of size [" + toString(Samples());
769  msg += ", " + toString(Lines()) + "]";
770  throw IException(IException::Programmer, msg, _FILEINFO_);
771  }
772 
773  Chip chipped(samples, lines);
774  for (int oline = 1; oline <= lines; oline++) {
775  for (int osamp = 1; osamp <= samples; osamp++) {
776  int thisSamp = samp + (osamp - chipped.TackSample());
777  int thisLine = line + (oline - chipped.TackLine());
778  if ((thisSamp < 1) ||
779  (thisLine < 1) ||
780  (thisSamp > Samples()) ||
781  (thisLine > Lines()) ) {
782  chipped.SetValue(osamp, oline, Isis::Null);
783  }
784  else {
785  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
786  }
787  }
788  }
789 
790  chipped.m_affine = m_affine;
791  chipped.m_validMinimum = m_validMinimum;
792  chipped.m_validMaximum = m_validMaximum;
793  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
794  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
795 
796  return chipped;
797  }
798 
810  void Chip::Extract(int samp, int line, Chip &chipped) {
811  int samples = chipped.Samples();
812  int lines = chipped.Lines();
813  //chipped.Init(samples, lines);
814  chipped.m_tackSample = ((samples - 1) / 2) + 1;
815  chipped.m_tackLine = ((lines - 1) / 2) + 1;
816 
817  for (int oline = 1; oline <= lines; oline++) {
818  for (int osamp = 1; osamp <= samples; osamp++) {
819  int thisSamp = samp + (osamp - chipped.TackSample());
820  int thisLine = line + (oline - chipped.TackLine());
821  if ((thisSamp < 1) ||
822  (thisLine < 1) ||
823  (thisSamp > Samples()) ||
824  (thisLine > Lines()) ) {
825  chipped.SetValue(osamp, oline, Isis::Null);
826  }
827  else {
828  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
829  }
830  }
831  }
832 
833  chipped.m_affine = m_affine;
834  chipped.m_validMinimum = m_validMinimum;
835  chipped.m_validMaximum = m_validMaximum;
836  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
837  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
838 
839  return;
840  }
841 
842 
884  void Chip::Extract(Chip &chipped, Affine &affine) {
885  // Create an interpolator and portal for interpolation
886  Interpolator interp(Interpolator::BiLinearType);
887  Portal port(interp.Samples(), interp.Lines(), Isis::Double,
888  interp.HotSample(), interp.HotLine());
889 
890  int samples = chipped.Samples();
891  int lines = chipped.Lines();
892 
893  for (int oline = 1; oline <= lines; oline++) {
894  int relativeLine = oline - chipped.TackLine();
895  for (int osamp = 1; osamp <= samples; osamp++) {
896  int relativeSamp = osamp - chipped.TackSample();
897  affine.Compute(relativeSamp, relativeLine);
898  double xp = affine.xp() + TackSample();
899  double yp = affine.yp() + TackLine();
900  port.SetPosition(xp, yp, 1);
901  for (int i = 0; i < port.size(); i++) {
902  int csamp = port.Sample(i);
903  int cline = port.Line(i);
904  if ((csamp < 1) ||
905  (cline < 1) ||
906  (csamp > Samples()) ||
907  (cline > Lines()) ) {
908  port[i] = Isis::Null;
909  }
910  else {
911  port[i] = GetValue(csamp, cline);
912  }
913  }
914  chipped.SetValue(osamp, oline, interp.Interpolate(xp, yp, port.DoubleBuffer()));
915  }
916  }
917 
918  chipped.m_validMinimum = m_validMinimum;
919  chipped.m_validMaximum = m_validMaximum;
920  chipped.m_filename = m_filename;
921 
922  // Make necessary adjustments to remaining chip elements. Note that this matrix multiply
923  // acheives a completed transform of two Affine matrices.
924  // No translations are required - only update tack points.
925  chipped.m_affine = Affine(TNT::matmult(affine.Forward(), m_affine.Forward()));
926 
927  affine.Compute(0.0, 0.0);
928  chipped.m_cubeTackSample = m_cubeTackSample + affine.xp();
929  chipped.m_cubeTackLine = m_cubeTackLine + affine.yp();
930 
931  chipped.m_chipSample = chipped.TackSample();
932  chipped.m_chipLine = chipped.TackLine();
933  chipped.m_cubeSample = chipped.m_cubeTackSample;
934  chipped.m_cubeLine = chipped.m_cubeTackLine;
935 
936  return;
937  }
938 
939 
947  Isis::Statistics *Chip::Statistics() {
948  Isis::Statistics *stats = new Isis::Statistics();
949 
950  stats->SetValidRange(m_validMinimum, m_validMaximum);
951 
952  for (int i = 0; i < m_chipSamples; i++) {
953  stats->AddData(&m_buf[i][0], m_chipLines);
954  }
955 
956  return stats;
957  }
958 
959 
977  void Chip::Read(Cube &cube, const int band) {
978  // Create an interpolator and portal for geoming
979  Interpolator interp(m_readInterpolator);
980  Portal port(interp.Samples(), interp.Lines(), cube.pixelType(),
981  interp.HotSample(), interp.HotLine());
982  // Loop through the pixels in the chip and geom them
983  for (int line = 1; line <= Lines(); line++) {
984  for (int samp = 1; samp <= Samples(); samp++) {
985  SetChipPosition((double)samp, (double)line);
986  if ((CubeSample() < 0.5) ||
987  (CubeLine() < 0.5) ||
988  (CubeSample() > cube.sampleCount() + 0.5) ||
989  (CubeLine() > cube.lineCount() + 0.5)) {
990 
991  m_buf[line-1][samp-1] = Isis::NULL8;
992  }
993  else if (m_clipPolygon == NULL) {
994  port.SetPosition(CubeSample(), CubeLine(), band);
995  cube.read(port);
996  m_buf[line-1][samp-1] =
997  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
998  }
999  else {
1000  geos::geom::Point *pnt = globalFactory.createPoint(
1001  geos::geom::Coordinate(CubeSample(), CubeLine()));
1002  if (pnt->within(m_clipPolygon)) {
1003  port.SetPosition(CubeSample(), CubeLine(), band);
1004  cube.read(port);
1005  m_buf[line-1][samp-1] =
1006  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
1007  }
1008  else {
1009  m_buf[line-1][samp-1] = Isis::NULL8;
1010  }
1011  delete pnt;
1012  }
1013  }
1014  }
1015  }
1016 
1017 
1023  void Chip::Write(const QString &filename) {
1024  Cube c;
1025  c.setDimensions(Samples(), Lines(), 1);
1026  c.create(filename);
1027  LineManager line(c);
1028  for (int i = 1; i <= Lines(); i++) {
1029  line.SetLine(i);
1030  for (int j = 1; j <= Samples(); j++) {
1031  line[j-1] = GetValue(j, i);
1032  }
1033  c.write(line);
1034  }
1035  c.close();
1036  }
1037 
1038 
1046  void Chip::SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon) {
1047  if (m_clipPolygon != NULL) delete m_clipPolygon;
1048  m_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1049  }
1050 
1051 
1057  Chip &Chip::operator=(const Chip &other) {
1058  m_chipSamples = other.m_chipSamples;
1059  m_chipLines = other.m_chipLines;
1060  m_buf = other.m_buf;
1061  m_tackSample = other.m_tackSample;
1062  m_tackLine = other.m_tackLine;
1063 
1064  m_cubeTackSample = other.m_cubeTackSample;
1065  m_cubeTackLine = other.m_cubeTackLine;
1066 
1067  m_validMinimum = other.m_validMinimum;
1068  m_validMaximum = other.m_validMaximum;
1069 
1070  m_chipSample = other.m_chipSample;
1071  m_chipLine = other.m_chipLine;
1072  m_cubeSample = other.m_cubeSample;
1073  m_cubeLine = other.m_cubeLine;
1074 
1075  // Free allocated memory.
1076  if (m_clipPolygon) {
1077  delete m_clipPolygon;
1078  m_clipPolygon = NULL;
1079  }
1080 
1081  if (other.m_clipPolygon) {
1082  m_clipPolygon = PolygonTools::MakeMultiPolygon(
1083  other.m_clipPolygon->clone());
1084  }
1085 
1086  m_affine = other.m_affine;
1087  m_readInterpolator = other.m_readInterpolator;
1088  m_filename = other.m_filename;
1089 
1090  return *this;
1091  }
1092 } // 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
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:510
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:109
double m_validMaximum
valid maximum chip pixel value
Definition: Chip.h:351
PixelType pixelType() const
Definition: Cube.cpp:1355
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.
double m_cubeLine
cube line set by SetCubePosition
Definition: Chip.h:356
Camera * camera()
Return a camera associated with the cube.
Definition: Cube.cpp:1118
A small chip of data used for pattern matching.
Definition: Chip.h:101
Buffer for containing a two dimensional section of an image.
Definition: Portal.h:52
Base class for Map TProjections.
Definition: TProjection.h:178
double m_cubeSample
cube sample set by SetCubePosition
Definition: Chip.h:355
Interpolator::interpType m_readInterpolator
Interpolator type set by.
Definition: Chip.h:364
const double PI(3.14159265358979323846)
The mathematical constant PI.
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
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:225
int m_tackSample
Middle sample of the chip.
Definition: Chip.h:344
double m_chipSample
chip sample set by SetChip/CubePosition
Definition: Chip.h:353
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:226
Projection * projection()
Definition: Cube.cpp:1391
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:686
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Definition: Cube.cpp:894
Buffer manager, for moving through a cube in lines.
Definition: LineManager.h:55
int Samples() const
Return the number of samples in the chip.
Definition: Chip.h:114
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:392
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:248
double m_cubeTackLine
cube line at the chip tack
Definition: Chip.h:348
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:166
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:109
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
Base class for Map Projections.
Definition: Projection.h:169
int sampleCount() const
Definition: Cube.cpp:1404
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
Definition: Affine.cpp:204
Affine basis function.
Definition: Affine.h:79
double m_validMinimum
valid minimum chip pixel value
Definition: Chip.h:350
int Samples()
Returns the number of samples needed by the interpolator.
AMatrix Forward() const
Returns the forward Affine matrix.
Definition: Affine.h:120
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
double Sample()
Returns the current sample number.
Definition: Camera.cpp:2752
double m_cubeTackSample
cube sample at the chip tack
Definition: Chip.h:347
void close(bool remove=false)
Closes the cube and updates the labels.
Definition: Cube.cpp:175
int m_chipLines
Number of lines in the chip.
Definition: Chip.h:342
int TackSample() const
Return the fixed tack sample of the chip.
Definition: Chip.h:187
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition: Sensor.cpp:201
double CubeLine() const
Returns cube line after invoking SetChipPosition.
Definition: Chip.h:217
double UniversalLatitude()
This returns a universal latitude (planetocentric).
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 m_filename
FileName of loaded cube.
Definition: Chip.h:368
double yp() const
Returns the computed y&#39;.
Definition: Affine.h:101
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:483
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Definition: Chip.h:141
Affine m_affine
Transform set by SetTransform.
Definition: Chip.h:361
int m_tackLine
Middle line of the chip.
Definition: Chip.h:345
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:358
int Lines() const
Return the number of lines in the chip.
Definition: Chip.h:121
double Line()
Returns the current line number.
Definition: Camera.cpp:2772
void write(Blob &blob)
This method will write a blob of data (e.g.
Definition: Cube.cpp:725
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:99
int m_chipSamples
Number of samples in the chip.
Definition: Chip.h:341
std::vector< std::vector< double > > m_buf
Chip buffer.
Definition: Chip.h:343
double xp() const
Returns the computed x&#39;.
Definition: Affine.h:96
QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1160
double CubeSample() const
Returns cube sample after invoking SetChipPosition.
Definition: Chip.h:212
int TackLine() const
Return the fixed tack line of the chip.
Definition: Chip.h:198
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:158
int lineCount() const
Definition: Cube.cpp:1331
void create(const QString &cfile)
This method will create an isis cube for writing.
Definition: Cube.cpp:321
double m_chipLine
chip line set by SetChip/CubePosition
Definition: Chip.h:354
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
Definition: Projection.cpp:530
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:15:50