Isis 3 Programmer Reference
Chip.cpp
1 
6 /* SPDX-License-Identifier: CC0-1.0 */
7 
8 #include "Chip.h"
9 #include "Camera.h"
10 #include "Cube.h"
11 #include "IException.h"
12 #include "Interpolator.h"
13 #include "IString.h"
14 #include "LineManager.h"
15 #include "PolygonTools.h"
16 #include "Portal.h"
17 #include "Projection.h"
18 #include "Statistics.h"
19 #include "TProjection.h"
20 
21 #include <algorithm>
22 #include <cmath>
23 #include <string>
24 #include <vector>
25 
26 #include <geos/geom/Point.h>
27 #include <tnt/tnt_array2d_utils.h>
28 
29 using namespace std;
30 namespace Isis {
31 
35  Chip::Chip() {
36  Init(3, 3);
37  }
38 
44  Chip::Chip(const Chip &other) {
45  m_chipSamples = other.m_chipSamples;
46  m_chipLines = other.m_chipLines;
47  m_buf = other.m_buf;
48  m_tackSample = other.m_tackSample;
49  m_tackLine = other.m_tackLine;
50 
51  m_cubeTackSample = other.m_cubeTackSample;
52  m_cubeTackLine = other.m_cubeTackLine;
53 
54  m_validMinimum = other.m_validMinimum;
55  m_validMaximum = other.m_validMaximum;
56 
57  m_chipSample = other.m_chipSample;
58  m_chipLine = other.m_chipLine;
59  m_cubeSample = other.m_cubeSample;
60  m_cubeLine = other.m_cubeLine;
61 
62  if (other.m_clipPolygon) {
63  m_clipPolygon = PolygonTools::MakeMultiPolygon(
64  other.m_clipPolygon->clone());
65  }
66  else {
67  m_clipPolygon = NULL;
68  }
69 
70  m_affine = other.m_affine;
71  m_readInterpolator = other.m_readInterpolator;
72  m_filename = other.m_filename;
73  }
74 
75 
82  Chip::Chip(const int samples, const int lines) {
83  Init(samples, lines);
84  }
85 
86 
88  Chip::~Chip() {
89  if (m_clipPolygon != NULL) delete m_clipPolygon;
90  }
91 
92 
100  void Chip::SetAllValues(const double &d) {
101  for (unsigned int i = 0; i < m_buf.size(); i++) {
102  fill(m_buf[i].begin(), m_buf[i].end(), d);
103  }
104  }
105 
106 
116  void Chip::Init(const int samples, const int lines) {
117  SetReadInterpolator(Interpolator::CubicConvolutionType);
118  SetSize(samples, lines);
119  SetValidRange();
120  m_clipPolygon = NULL;
121  }
122 
123 
134  void Chip::SetSize(const int samples, const int lines) {
135  if ( samples <= 0.0 || lines <= 0.0 ) {
136  QString msg;
137  msg += "Unable to set chip size to [";
138  msg += toString(samples) + ", ";
139  msg += toString(lines) + "]. Samples and lines must be greater than zero.";
140  throw IException(IException::User, msg, _FILEINFO_);
141  }
142  m_chipSamples = samples;
143  m_chipLines = lines;
144  m_buf.clear();
145  m_buf.resize(lines);
146  for (int i = 0; i < lines; i++) {
147  m_buf[i].resize(samples);
148  }
149  m_affine.Identity();
150  m_tackSample = ((samples - 1) / 2) + 1;
151  m_tackLine = ((lines - 1) / 2) + 1;
152  }
153 
154 
162  bool Chip::IsInsideChip(double sample, double line) {
163  double minSamp = m_cubeTackSample - ((m_chipSamples - 1) / 2);
164  double maxSamp = m_cubeTackSample + ((m_chipSamples - 1) / 2);
165 
166  double minLine = m_cubeTackLine - ((m_chipLines - 1) / 2);
167  double maxLine = m_cubeTackLine + ((m_chipLines - 1) / 2);
168 
169  if ( sample < minSamp || sample > maxSamp ) return false;
170  if ( line < minLine || line > maxLine ) return false;
171  return true;
172  }
173 
174 
182  void Chip::TackCube(const double cubeSample, const double cubeLine) {
183  m_cubeTackSample = cubeSample;
184  m_cubeTackLine = cubeLine;
185  m_affine.Identity();
186  m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
187  }
188 
189 
203  void Chip::Load(Cube &cube, const double rotation, const double scale, const int band) {
204  // Initialize our affine transform
205  m_affine.Identity();
206 
207  // We want an affine which translates from chip to cube. Note that we want to give adjusted
208  // chip coordinates such that (0,0) is at the chip tack point and maps to the cube tack point.
209  m_affine.Scale(scale);
210  m_affine.Rotate(rotation);
211  m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
212 
213  // Now go read the data from the cube into the chip
214  Read(cube, band);
215 
216  // Store off the cube address in case someone wants to match this chip
217  m_filename = cube.fileName();
218  }
219 
220 
244  void Chip::Load(Cube &cube, const Affine &affine, const bool &keepPoly, const int band) {
245 
246  // Set the tackpoint center to the cube location
247  SetTransform(affine);
248  SetChipPosition(TackSample(), TackLine());
249 
250  // Remove the clipping polygon if requested
251  if (!keepPoly) {
252  delete m_clipPolygon;
253  m_clipPolygon = 0;
254  }
255 
256  // Now go read the data from the cube into the chip
257  Read(cube, band);
258 
259  // Store off the cube address in case someone wants to match this chip
260  m_filename = cube.fileName();
261  }
262 
263 
300  void Chip::Load(Cube &cube, Chip &match, Cube &matchChipCube, const double scale, const int band)
301  {
302  // See if the match cube has a camera or projection
303  Camera *matchCam = NULL;
304  TProjection *matchProj = NULL;
305  try {
306  matchCam = matchChipCube.camera();
307  }
308  catch (IException &error1) {
309  try {
310  matchProj = (TProjection *) matchChipCube.projection();
311  }
312  catch (IException &error2) {
313  QString msg = "Can not geom chip. ";
314  msg += "Match chip cube [" + matchChipCube.fileName();
315  msg += "] is not a camera or map projection";
316 
317  IException fullError(IException::User, msg, _FILEINFO_);
318  fullError.append(error1);
319  fullError.append(error2);
320 
321  throw fullError;
322  }
323  }
324 
325  // See if the cube we are loading has a camera/projection
326  Camera *cam = NULL;
327  Projection *proj = NULL;
328  try {
329  cam = cube.camera();
330  }
331  catch (IException &error1) {
332  try {
333  proj = cube.projection();
334  }
335  catch (IException &error2) {
336  QString msg = "Can not geom chip. ";
337  msg += "Chip cube [" + cube.fileName();
338  msg += "] is not a camera or map projection";
339 
340  IException fullError(IException::User, msg, _FILEINFO_);
341  fullError.append(error1);
342  fullError.append(error2);
343 
344  throw fullError;
345  }
346  }
347 
348  // Ok we can attempt to create an affine transformation that maps our chip to the match chip.
349  // We will need a set of at least 3 control points so we can fit the affine transform.
350  // We will try to find 4 points, one from each corner of the chip.
351  vector<double> x(4), y(4);
352  vector<double> xp(4), yp(4);
353 
354  // Choose these control points by beginning at each corner and moving inward in the chip
355  // until an acceptable point is found
356  // i = 0, start at upper left corner (1, 1)
357  // i = 1, start at lower left corner (1, Lines()-1)
358  // i = 2, start at upper right corner (Samples()-1, 1)
359  // i = 3, start at lower right corner (Samples()-1, Lines()-1)
360  for (int i = 0; i < (int) xp.size(); i++) {
361  // define initial values for starting/ending sample/line for each index
362  int startSamp = 1;
363  int startLine = 1;
364  int endSamp = Samples() - 1;
365  int endLine = Lines() - 1;
366 
367  bool pointfound = false;
368  while (!pointfound) {
369  // start and end may cross (see MovePoints())
370  // if we move outside chip, break out of loop
371  if (startSamp < 1 || startSamp > Samples() - 1 ||
372  endSamp < 1 || endSamp > Samples() - 1 ||
373  startLine < 1 || startLine > Lines() - 1 ||
374  endLine < 1 || endLine > Lines() - 1) {
375  // unable to find acceptable control point from this corner
376  // erase point and go to the next corner
377  x.erase(x.begin() + i);
378  y.erase(y.begin() + i);
379  xp.erase(xp.begin() + i);
380  yp.erase(yp.begin() + i);
381  i--;
382  break;
383  }
384  int chipSamp, chipLine;
385  if (i < 2) {
386  chipSamp = startSamp;
387  }
388  else {
389  chipSamp = endSamp;
390  }
391  if (i % 2 == 0) {
392  chipLine = startLine;
393  }
394  else {
395  chipLine = endLine;
396  }
397  // Determine the offset from the tack point in our chip to one of the four corners.
398  int sampOffset = chipSamp - TackSample();
399  int lineOffset = chipLine - TackLine();
400 
401  // Use this offset to compute a chip position in the match chip.
402  double matchChipSamp = match.TackSample() + sampOffset;
403  double matchChipLine = match.TackLine() + lineOffset;
404 
405  // Now get the lat/lon at that chip position.
406  match.SetChipPosition(matchChipSamp, matchChipLine);
407  double lat, lon;
408  if (matchCam != NULL) {
409  matchCam->SetImage(match.CubeSample(), match.CubeLine());
410  if (!matchCam->HasSurfaceIntersection() ) {
411  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
412  startSamp = newlocation[0];
413  startLine = newlocation[1];
414  endSamp = newlocation[2];
415  endLine = newlocation[3];
416  continue;
417  }
418  lat = matchCam->UniversalLatitude();
419  lon = matchCam->UniversalLongitude();
420  }
421  else {
422  matchProj->SetWorld(match.CubeSample(), match.CubeLine() );
423  if (!matchProj->IsGood() ) {
424  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
425  startSamp = newlocation[0];
426  startLine = newlocation[1];
427  endSamp = newlocation[2];
428  endLine = newlocation[3];
429  continue;
430  }
431  lat = matchProj->UniversalLatitude();
432  lon = matchProj->UniversalLongitude();
433  }
434 
435  // Now use that lat/lon to find a line/sample in our chip
436  double line, samp;
437  if (cam != NULL) {
438  cam->SetUniversalGround(lat, lon);
439  if (!cam->HasSurfaceIntersection() ) {
440  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
441  startSamp = newlocation[0];
442  startLine = newlocation[1];
443  endSamp = newlocation[2];
444  endLine = newlocation[3];
445  continue;
446  }
447  samp = cam->Sample(); // getting negative sample?!?!?!
448  line = cam->Line();
449  }
450  else {
451  proj->SetUniversalGround(lat, lon);
452  if (!proj->IsGood()) {
453  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
454  startSamp = newlocation[0];
455  startLine = newlocation[1];
456  endSamp = newlocation[2];
457  endLine = newlocation[3];
458  continue;
459  }
460  samp = proj->WorldX();
461  line = proj->WorldY();
462  }
463 
464  // if (line < 1 || line > cube.lineCount()) continue;
465  // if (samp < 1 || samp > cube.sampleCount()) continue;
466 
467  // Ok save this control point
468  pointfound = true;
469  x[i] = sampOffset;
470  y[i] = lineOffset;
471  xp[i] = samp;
472  yp[i] = line;
473 
474  // If we get 3 points on the same line, affine transform will fail.
475  // Choose a one degree default tolerance for linearity check method.
476  double tol = 1.0;
477  // If we have already removed a point, use a stricter tolerance of 2 degrees.
478  if (xp.size() == 3) {
479  tol = 2.0;
480  }
481  if (i > 1) {
482  if ( PointsColinear(xp[0], yp[0], xp[1], yp[1], xp[i], yp[i], tol) ) {
483  // try to find a point further along that is not colinear
484  pointfound = false;
485  vector<int> newlocation = MovePoints(startSamp, startLine, endSamp, endLine);
486  startSamp = newlocation[0];
487  startLine = newlocation[1];
488  endSamp = newlocation[2];
489  endLine = newlocation[3];
490  continue;
491  }
492  }
493  }
494  }
495 
496  if (xp.size() < 3) {
497  QString msg = "Cannot find enough points to perform Affine transformation. ";
498  msg += "Unable to load chip from [" + cube.fileName();
499  msg += "] to match chip from [" + matchChipCube.fileName() + "].";
500  throw IException(IException::User, msg, _FILEINFO_);
501  }
502 
503  // Now take our control points and create the affine map
504  m_affine.Solve(&x[0], &y[0], &xp[0], &yp[0], (int)x.size());
505 
506  // TLS 8/3/06 Apply scale
507  m_affine.Scale(scale);
508 
509  // Finally we need to make the affine map the tack point to the requested cube sample/line
510  m_affine.Compute(0.0, 0.0);
511  double cubeSampleOffset = m_cubeTackSample - m_affine.xp();
512  double cubeLineOffset = m_cubeTackLine - m_affine.yp();
513  m_affine.Translate(cubeSampleOffset, cubeLineOffset);
514 
515  // Now go read the data from the cube into the chip
516  Read(cube, band);
517 
518  // Store off the cube address in case someone wants to match
519  // this chip
520  m_filename = cube.fileName();
521  }
522 
523 
546  bool Chip::PointsColinear(const double x0, const double y0, const double x1, const double y1,
547  const double x2, const double y2, const double tol) {
548  // check angles at each point of the triangle composed of the 3 points
549  // if any angle is near 0 or 180 degrees, then the points are almost colinear
550 
551  // we have the following property:
552  // sin(theta) = |v x w|/(|v|*|w|) where
553  // v=(vx,vy) and w=(wx,wy) are the vectors that define the angle theta
554  // |v| is the magnitude (norm) of the vector. In 2D, this is |v| = sqrt(vx^2 + vy^2)
555  // v x w is the cross product of the vectors. In 2D, this is v x w = vx*wy-vy*wx
556  // See equations (5) and (6) at http://mathworld.wolfram.com/CrossProduct.html
557 
558 
559  // first find the vectors that define the angles at each point
560  // For example, if we shift the point P0 to the origin,
561  // the vectors defining the angle at P0
562  // are v01 = (x1-x0, y1-y0) and v02 = (x2-x0, y2-y0)
563  // Note: v10 = -v01 and |v x w| = |w x v|
564  // so we only need 3 vectors and the order we use these doesn't matter
565  vector<double> v01, v12, v20;
566  v01.push_back(x1 - x0);
567  v01.push_back(y1 - y0);
568  v12.push_back(x2 - x1);
569  v12.push_back(y2 - y1);
570  v20.push_back(x0 - x2);
571  v20.push_back(y0 - y2);
572 
573  // sin(angle at P0) = |v01 x v02|/(|v01|*|v02|) =
574  // |v01x*v02y-v01y*v02x|/(sqrt(v01x^2+v01y^2)*sqrt(v01x^2+v02y^2))
575  double sinP0 = fabs(v01[0] * v20[1] - v01[1] * v20[0]) /
576  sqrt((pow(v01[0], 2) + pow(v01[1], 2)) * (pow(v12[0], 2) + pow(v12[1], 2)));
577  // sin(angle at P1)
578  double sinP1 = fabs(v12[0] * v20[1] - v12[1] * v20[0]) /
579  sqrt((pow(v12[0], 2) + pow(v12[1], 2)) * (pow(v20[0], 2) + pow(v20[1], 2)));
580  // sin(angle at P2)
581  double sinP2 = fabs(v20[0] * v01[1] - v20[1] * v01[0]) /
582  sqrt((pow(v20[0], 2) + pow(v20[1], 2)) * (pow(v01[0], 2) + pow(v01[1], 2)));
583 
584  // We will seek angles with sine near 0 (thus a multiple of 180 degrees or pi radians)
585  // We will use a tolerance of tol degrees (tol*pi/180 radians)
586  // Compare the smallest sine value to the sine of tol,
587  // if it is less, then the angle is less than tol degrees or
588  // greater than 180-tol degrees, so points are almost colinear
589  double minSinValue = min(sinP0, min(sinP1, sinP2));
590  if ( minSinValue < sin(tol * PI / 180) ) {
591  return true;
592  }
593  else {
594  return false;
595  }
596  }
597 
598 
615  vector<int> Chip::MovePoints(const int startSamp, const int startLine,
616  const int endSamp, const int endLine) {
617  vector<int> newlocations(4);
618  int sinc = (endSamp - startSamp) / 4;
619  // Ensures that the inc can cause start and end to cross
620  if (sinc < 1) {
621  sinc = 1;
622  }
623  int linc = (endLine - startLine) / 3;
624  // Ensures that the inc can cause start and end to cross
625  if (linc < 1) {
626  linc = 1;
627  }
628  newlocations[0] = startSamp + sinc;
629  newlocations[1] = startLine + linc;
630  newlocations[2] = endSamp - sinc;
631  newlocations[3] = endLine - linc;
632  return newlocations;
633  }
634 
643  void Chip::SetChipPosition(const double sample, const double line) {
644  m_chipSample = sample;
645  m_chipLine = line;
646  m_affine.Compute(sample - TackSample(), line - TackLine());
647  m_cubeSample = m_affine.xp();
648  m_cubeLine = m_affine.yp();
649  }
650 
651 
660  void Chip::SetCubePosition(const double sample, const double line) {
661  m_cubeSample = sample;
662  m_cubeLine = line;
663  m_affine.ComputeInverse(sample, line);
664  m_chipSample = m_affine.x() + TackSample();
665  m_chipLine = m_affine.y() + TackLine();
666  }
667 
668 
681  void Chip::SetValidRange(const double minimum, const double maximum) {
682  if (minimum >= maximum) {
683  QString msg = "Unable to set valid chip range to [" + toString(minimum);
684  msg += ", " + toString(maximum) + "]. First parameter must be smaller than the second.";
685  throw IException(IException::Programmer, msg, _FILEINFO_);
686  }
687 
688  m_validMinimum = minimum;
689  m_validMaximum = maximum;
690  }
691 
692 
701  bool Chip::IsValid(double percentage) {
702  int validCount = 0;
703  for (int samp = 1; samp <= Samples(); samp++) {
704  for (int line = 1; line <= Lines(); line++) {
705  if (IsValid(samp, line)) validCount++;
706  }
707  }
708  double validPercentage = 100.0 * (double) validCount /
709  (double)(Samples() * Lines());
710  if (validPercentage < percentage) return false;
711  return true;
712  }
713 
714 
727  Chip Chip::Extract(int samples, int lines, int samp, int line) {
728  if ( samples > Samples() || lines > Lines() ) {
729  QString msg = "Cannot extract sub-chip of size [" + toString(samples);
730  msg += ", " + toString(lines) + "] from chip of size [" + toString(Samples());
731  msg += ", " + toString(Lines()) + "]";
732  throw IException(IException::Programmer, msg, _FILEINFO_);
733  }
734 
735  Chip chipped(samples, lines);
736  for (int oline = 1; oline <= lines; oline++) {
737  for (int osamp = 1; osamp <= samples; osamp++) {
738  int thisSamp = samp + (osamp - chipped.TackSample());
739  int thisLine = line + (oline - chipped.TackLine());
740  if ((thisSamp < 1) ||
741  (thisLine < 1) ||
742  (thisSamp > Samples()) ||
743  (thisLine > Lines()) ) {
744  chipped.SetValue(osamp, oline, Isis::Null);
745  }
746  else {
747  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
748  }
749  }
750  }
751 
752  chipped.m_affine = m_affine;
753  chipped.m_validMinimum = m_validMinimum;
754  chipped.m_validMaximum = m_validMaximum;
755  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
756  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
757 
758  return chipped;
759  }
760 
772  void Chip::Extract(int samp, int line, Chip &chipped) {
773  int samples = chipped.Samples();
774  int lines = chipped.Lines();
775  //chipped.Init(samples, lines);
776  chipped.m_tackSample = ((samples - 1) / 2) + 1;
777  chipped.m_tackLine = ((lines - 1) / 2) + 1;
778 
779  for (int oline = 1; oline <= lines; oline++) {
780  for (int osamp = 1; osamp <= samples; osamp++) {
781  int thisSamp = samp + (osamp - chipped.TackSample());
782  int thisLine = line + (oline - chipped.TackLine());
783  if ((thisSamp < 1) ||
784  (thisLine < 1) ||
785  (thisSamp > Samples()) ||
786  (thisLine > Lines()) ) {
787  chipped.SetValue(osamp, oline, Isis::Null);
788  }
789  else {
790  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
791  }
792  }
793  }
794 
795  chipped.m_affine = m_affine;
796  chipped.m_validMinimum = m_validMinimum;
797  chipped.m_validMaximum = m_validMaximum;
798  chipped.m_tackSample = chipped.TackSample() + TackSample() - samp;
799  chipped.m_tackLine = chipped.TackLine() + TackLine() - line;
800 
801  return;
802  }
803 
804 
846  void Chip::Extract(Chip &chipped, Affine &affine) {
847  // Create an interpolator and portal for interpolation
848  Interpolator interp(Interpolator::BiLinearType);
849  Portal port(interp.Samples(), interp.Lines(), Isis::Double,
850  interp.HotSample(), interp.HotLine());
851 
852  int samples = chipped.Samples();
853  int lines = chipped.Lines();
854 
855  for (int oline = 1; oline <= lines; oline++) {
856  int relativeLine = oline - chipped.TackLine();
857  for (int osamp = 1; osamp <= samples; osamp++) {
858  int relativeSamp = osamp - chipped.TackSample();
859  affine.Compute(relativeSamp, relativeLine);
860  double xp = affine.xp() + TackSample();
861  double yp = affine.yp() + TackLine();
862  port.SetPosition(xp, yp, 1);
863  for (int i = 0; i < port.size(); i++) {
864  int csamp = port.Sample(i);
865  int cline = port.Line(i);
866  if ((csamp < 1) ||
867  (cline < 1) ||
868  (csamp > Samples()) ||
869  (cline > Lines()) ) {
870  port[i] = Isis::Null;
871  }
872  else {
873  port[i] = GetValue(csamp, cline);
874  }
875  }
876  chipped.SetValue(osamp, oline, interp.Interpolate(xp, yp, port.DoubleBuffer()));
877  }
878  }
879 
880  chipped.m_validMinimum = m_validMinimum;
881  chipped.m_validMaximum = m_validMaximum;
882  chipped.m_filename = m_filename;
883 
884  // Make necessary adjustments to remaining chip elements. Note that this matrix multiply
885  // acheives a completed transform of two Affine matrices.
886  // No translations are required - only update tack points.
887  chipped.m_affine = Affine(TNT::matmult(affine.Forward(), m_affine.Forward()));
888 
889  affine.Compute(0.0, 0.0);
890  chipped.m_cubeTackSample = m_cubeTackSample + affine.xp();
891  chipped.m_cubeTackLine = m_cubeTackLine + affine.yp();
892 
893  chipped.m_chipSample = chipped.TackSample();
894  chipped.m_chipLine = chipped.TackLine();
895  chipped.m_cubeSample = chipped.m_cubeTackSample;
896  chipped.m_cubeLine = chipped.m_cubeTackLine;
897 
898  return;
899  }
900 
901 
909  Isis::Statistics *Chip::Statistics() {
910  Isis::Statistics *stats = new Isis::Statistics();
911 
912  stats->SetValidRange(m_validMinimum, m_validMaximum);
913 
914  for (int i = 0; i < m_chipSamples; i++) {
915  stats->AddData(&m_buf[i][0], m_chipLines);
916  }
917 
918  return stats;
919  }
920 
921 
939  void Chip::Read(Cube &cube, const int band) {
940  // Create an interpolator and portal for geoming
941  Interpolator interp(m_readInterpolator);
942  Portal port(interp.Samples(), interp.Lines(), cube.pixelType(),
943  interp.HotSample(), interp.HotLine());
944  // Loop through the pixels in the chip and geom them
945  for (int line = 1; line <= Lines(); line++) {
946  for (int samp = 1; samp <= Samples(); samp++) {
947  SetChipPosition((double)samp, (double)line);
948  if ((CubeSample() < 0.5) ||
949  (CubeLine() < 0.5) ||
950  (CubeSample() > cube.sampleCount() + 0.5) ||
951  (CubeLine() > cube.lineCount() + 0.5)) {
952 
953  m_buf[line-1][samp-1] = Isis::NULL8;
954  }
955  else if (m_clipPolygon == NULL) {
956  port.SetPosition(CubeSample(), CubeLine(), band);
957  cube.read(port);
958  m_buf[line-1][samp-1] =
959  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
960  }
961  else {
962  geos::geom::Point *pnt = globalFactory->createPoint(
963  geos::geom::Coordinate(CubeSample(), CubeLine()));
964  if (pnt->within(m_clipPolygon)) {
965  port.SetPosition(CubeSample(), CubeLine(), band);
966  cube.read(port);
967  m_buf[line-1][samp-1] =
968  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
969  }
970  else {
971  m_buf[line-1][samp-1] = Isis::NULL8;
972  }
973  delete pnt;
974  }
975  }
976  }
977  }
978 
979 
985  void Chip::Write(const QString &filename) {
986  Cube c;
987  c.setDimensions(Samples(), Lines(), 1);
988  c.create(filename);
989  LineManager line(c);
990  for (int i = 1; i <= Lines(); i++) {
991  line.SetLine(i);
992  for (int j = 1; j <= Samples(); j++) {
993  line[j-1] = GetValue(j, i);
994  }
995  c.write(line);
996  }
997  c.close();
998  }
999 
1000 
1008  void Chip::SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon) {
1009  if (m_clipPolygon != NULL) delete m_clipPolygon;
1010  m_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1011  }
1012 
1013 
1021  Chip &Chip::operator=(const Chip &other) {
1022  m_chipSamples = other.m_chipSamples;
1023  m_chipLines = other.m_chipLines;
1024  m_buf = other.m_buf;
1025  m_tackSample = other.m_tackSample;
1026  m_tackLine = other.m_tackLine;
1027 
1028  m_cubeTackSample = other.m_cubeTackSample;
1029  m_cubeTackLine = other.m_cubeTackLine;
1030 
1031  m_validMinimum = other.m_validMinimum;
1032  m_validMaximum = other.m_validMaximum;
1033 
1034  m_chipSample = other.m_chipSample;
1035  m_chipLine = other.m_chipLine;
1036  m_cubeSample = other.m_cubeSample;
1037  m_cubeLine = other.m_cubeLine;
1038 
1039  // Free allocated memory.
1040  if (m_clipPolygon) {
1041  delete m_clipPolygon;
1042  m_clipPolygon = NULL;
1043  }
1044 
1045  if (other.m_clipPolygon) {
1046  m_clipPolygon = PolygonTools::MakeMultiPolygon(
1047  other.m_clipPolygon->clone());
1048  }
1049 
1050  m_affine = other.m_affine;
1051  m_readInterpolator = other.m_readInterpolator;
1052  m_filename = other.m_filename;
1053 
1054  return *this;
1055  }
1056 } // end namespace isis
Isis::Affine::Compute
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
Definition: Affine.cpp:191
Isis::Statistics
This class is used to accumulate statistics on double arrays.
Definition: Statistics.h:94
Isis::Cube::fileName
virtual QString fileName() const
Returns the opened cube's filename.
Definition: Cube.cpp:1563
Isis::Statistics::AddData
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
Definition: Statistics.cpp:141
Isis::LineManager
Buffer manager, for moving through a cube in lines.
Definition: LineManager.h:39
Isis::Chip::m_tackSample
int m_tackSample
Middle sample of the chip.
Definition: Chip.h:349
Isis::PI
const double PI
The mathematical constant PI.
Definition: Constants.h:40
Isis::Portal
Buffer for containing a two dimensional section of an image.
Definition: Portal.h:36
Isis::TProjection::UniversalLatitude
virtual double UniversalLatitude()
This returns a universal latitude (planetocentric).
Definition: TProjection.cpp:908
Isis::Sensor::HasSurfaceIntersection
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
Definition: Sensor.cpp:186
Isis::Camera::SetImage
virtual 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:154
Isis::Cube::read
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:807
Isis::Camera::Sample
virtual double Sample() const
Returns the current sample number.
Definition: Camera.cpp:2690
Isis::Buffer::DoubleBuffer
double * DoubleBuffer() const
Returns the value of the shape buffer.
Definition: Buffer.h:138
Isis::Cube::close
void close(bool remove=false)
Closes the cube and updates the labels.
Definition: Cube.cpp:260
Isis::Interpolator::Lines
int Lines()
Returns the number of lines needed by the interpolator.
Definition: Interpolator.cpp:236
Isis::Projection::SetUniversalGround
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:417
Isis::Chip::CubeSample
double CubeSample() const
Definition: Chip.h:203
Isis::Camera
Definition: Camera.h:236
Isis::Chip::m_validMaximum
double m_validMaximum
valid maximum chip pixel value
Definition: Chip.h:356
Isis::Chip::SetValue
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Definition: Chip.h:126
Isis::toString
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition: IString.cpp:211
Isis::Interpolator::HotSample
double HotSample()
Returns the sample coordinate of the center pixel in the buffer for the interpolator.
Definition: Interpolator.cpp:265
Isis::Chip::m_clipPolygon
geos::geom::MultiPolygon * m_clipPolygon
clipping polygon set by SetClipPolygon
Definition: Chip.h:363
Isis::IException::append
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
Definition: IException.cpp:409
Isis::Chip::m_chipLine
double m_chipLine
chip line set by SetChip/CubePosition
Definition: Chip.h:359
Isis::Chip::TackSample
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
Definition: Chip.h:176
Isis::Chip::CubeLine
double CubeLine() const
Definition: Chip.h:210
Isis::Chip::Lines
int Lines() const
Definition: Chip.h:106
Isis::Projection::WorldY
virtual double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:544
Isis::Projection::IsGood
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:374
Isis::Chip::m_readInterpolator
Interpolator::interpType m_readInterpolator
Interpolator type set by.
Definition: Chip.h:369
Isis::Sensor::UniversalLongitude
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Definition: Sensor.cpp:233
Isis::Cube::lineCount
int lineCount() const
Definition: Cube.cpp:1734
Isis::Chip::TackLine
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.
Definition: Chip.h:187
Isis::Affine::Forward
AMatrix Forward() const
Returns the forward Affine matrix.
Definition: Affine.h:127
Isis::Chip::m_cubeTackSample
double m_cubeTackSample
cube sample at the chip tack
Definition: Chip.h:352
Isis::Cube::setDimensions
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Definition: Cube.cpp:1217
Isis::Cube::create
void create(const QString &cfile)
This method will create an isis cube for writing.
Definition: Cube.cpp:414
Isis::Chip::m_validMinimum
double m_validMinimum
valid minimum chip pixel value
Definition: Chip.h:355
Isis::TProjection
Base class for Map TProjections.
Definition: TProjection.h:166
Isis::Chip::m_chipLines
int m_chipLines
Number of lines in the chip.
Definition: Chip.h:347
Isis::Chip::m_cubeTackLine
double m_cubeTackLine
cube line at the chip tack
Definition: Chip.h:353
Isis::Camera::SetUniversalGround
virtual bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
Definition: Camera.cpp:380
Isis::Cube::sampleCount
int sampleCount() const
Definition: Cube.cpp:1807
Isis::Projection::WorldX
virtual double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround,...
Definition: Projection.cpp:524
Isis::Cube
IO Handler for Isis Cubes.
Definition: Cube.h:167
Isis::Interpolator
Pixel interpolator.
Definition: Interpolator.h:34
Isis::IException
Isis exception class.
Definition: IException.h:91
Isis::Projection::SetWorld
virtual bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
Definition: Projection.cpp:497
Isis::Null
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:95
Isis::Cube::camera
Camera * camera()
Return a camera associated with the cube.
Definition: Cube.cpp:1451
Isis::Chip::m_tackLine
int m_tackLine
Middle line of the chip.
Definition: Chip.h:350
Isis::LineManager::SetLine
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:44
std
Namespace for the standard library.
Isis::Cube::pixelType
PixelType pixelType() const
Definition: Cube.cpp:1758
Isis::Interpolator::Interpolate
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.
Definition: Interpolator.cpp:56
Isis::Affine::xp
double xp() const
Returns the computed x'.
Definition: Affine.h:86
Isis::Cube::write
void write(Blob &blob, bool overwrite=true)
This method will write a blob of data (e.g.
Definition: Cube.cpp:971
Isis::TProjection::UniversalLongitude
virtual double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
Definition: TProjection.cpp:922
Isis::Chip::m_chipSample
double m_chipSample
chip sample set by SetChip/CubePosition
Definition: Chip.h:358
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::Affine
Affine basis function.
Definition: Affine.h:65
Isis::Chip::m_chipSamples
int m_chipSamples
Number of samples in the chip.
Definition: Chip.h:346
Isis::Buffer::size
int size() const
Returns the total number of pixels in the shape buffer.
Definition: Buffer.h:97
Isis::Chip::m_cubeSample
double m_cubeSample
cube sample set by SetCubePosition
Definition: Chip.h:360
Isis::Interpolator::Samples
int Samples()
Returns the number of samples needed by the interpolator.
Definition: Interpolator.cpp:208
Isis::Affine::yp
double yp() const
Returns the computed y'.
Definition: Affine.h:95
Isis::Camera::Line
virtual double Line() const
Returns the current line number.
Definition: Camera.cpp:2710
Isis::Chip::SetChipPosition
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
Definition: Chip.cpp:643
Isis::Chip::m_buf
std::vector< std::vector< double > > m_buf
Chip buffer.
Definition: Chip.h:348
Isis::Buffer::Sample
int Sample(const int index=0) const
Returns the sample position associated with a shape buffer index.
Definition: Buffer.cpp:127
Isis::Projection
Base class for Map Projections.
Definition: Projection.h:155
Isis::Interpolator::HotLine
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
Definition: Interpolator.cpp:297
Isis::Chip::m_filename
QString m_filename
FileName of loaded cube.
Definition: Chip.h:373
Isis::Portal::SetPosition
void SetPosition(const double sample, const double line, const int band)
Sets the line and sample position of the buffer.
Definition: Portal.h:93
Isis::Cube::projection
Projection * projection()
Definition: Cube.cpp:1794
Isis::Buffer::Line
int Line(const int index=0) const
Returns the line position associated with a shape buffer index.
Definition: Buffer.cpp:145
Isis::Chip::m_affine
Affine m_affine
Transform set by SetTransform.
Definition: Chip.h:366
Isis::Chip::m_cubeLine
double m_cubeLine
cube line set by SetCubePosition
Definition: Chip.h:361
Isis
This is free and unencumbered software released into the public domain.
Definition: Apollo.h:16
Isis::Sensor::UniversalLatitude
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Definition: Sensor.cpp:210