USGS

Isis 3.0 Object Programmers' Reference

Home

Chip.cpp
Go to the documentation of this file.
1 
24 #include <algorithm>
25 #include <cmath>
26 #include <string>
27 #include <vector>
28 #include "Camera.h"
29 #include "Chip.h"
30 #include "Cube.h"
31 #include "IException.h"
32 #include "Interpolator.h"
33 #include "LineManager.h"
34 #include "PolygonTools.h"
35 #include "Portal.h"
36 #include "Projection.h"
37 #include "TProjection.h"
38 #include "Statistics.h"
39 #include "geos/geom/Point.h"
40 #include "tnt/tnt_array2d_utils.h"
41 
42 using namespace std;
43 namespace Isis {
44 
48  Chip::Chip() {
49  Init(3, 3);
50  }
51 
57  Chip::Chip(const Chip &other) {
58  p_chipSamples = other.p_chipSamples;
59  p_chipLines = other.p_chipLines;
60  p_buf = other.p_buf;
61  p_tackSample = other.p_tackSample;
62  p_tackLine = other.p_tackLine;
63 
64  p_cubeTackSample = other.p_cubeTackSample;
65  p_cubeTackLine = other.p_cubeTackLine;
66 
67  p_validMinimum = other.p_validMinimum;
68  p_validMaximum = other.p_validMaximum;
69 
70  p_chipSample = other.p_chipSample;
71  p_chipLine = other.p_chipLine;
72  p_cubeSample = other.p_cubeSample;
73  p_cubeLine = other.p_cubeLine;
74 
75  if (other.p_clipPolygon) {
76  p_clipPolygon = PolygonTools::MakeMultiPolygon(
77  other.p_clipPolygon->clone());
78  }
79  else {
80  p_clipPolygon = NULL;
81  }
82 
83  p_affine = other.p_affine;
84  p_readInterpolator = other.p_readInterpolator;
85  p_filename = other.p_filename;
86  }
87 
94  Chip::Chip(const int samples, const int lines) {
95  Init(samples, lines);
96  }
97 
98 
100  Chip::~Chip() {
101  if(p_clipPolygon != NULL) delete p_clipPolygon;
102  }
103 
104 
112  void Chip::SetAllValues(const double &d) {
113  for(unsigned int i = 0 ; i < p_buf.size() ; i++) {
114  fill(p_buf[i].begin(), p_buf[i].end(), d);
115  }
116  }
117 
127  void Chip::Init(const int samples, const int lines) {
128  SetReadInterpolator(Interpolator::CubicConvolutionType);
129  SetSize(samples, lines);
130  SetValidRange();
131  p_clipPolygon = NULL;
132  }
133 
134 
145  void Chip::SetSize(const int samples, const int lines) {
146  if(samples <= 0.0 || lines <= 0.0) {
147  string msg = "Unable to set chip size to [" + IString(samples);
148  msg += ", " + IString(lines) + "]. Samples and lines must be greater than zero.";
149  throw IException(IException::User, msg, _FILEINFO_);
150  }
151  p_chipSamples = samples;
152  p_chipLines = lines;
153  p_buf.clear();
154  p_buf.resize(lines);
155  for(int i = 0; i < lines; i++) {
156  p_buf[i].resize(samples);
157  }
158  p_affine.Identity();
159  p_tackSample = ((samples - 1) / 2) + 1;
160  p_tackLine = ((lines - 1) / 2) + 1;
161  }
162 
170  bool Chip::IsInsideChip(double sample, double line) {
171  double minSamp = p_cubeTackSample - ((p_chipSamples - 1) / 2);
172  double maxSamp = p_cubeTackSample + ((p_chipSamples - 1) / 2);
173 
174  double minLine = p_cubeTackLine - ((p_chipLines - 1) / 2);
175  double maxLine = p_cubeTackLine + ((p_chipLines - 1) / 2);
176 
177  if(sample < minSamp || sample > maxSamp) return false;
178  if(line < minLine || line > maxLine) return false;
179  return true;
180  }
181 
182 
190  void Chip::TackCube(const double cubeSample, const double cubeLine) {
191  p_cubeTackSample = cubeSample;
192  p_cubeTackLine = cubeLine;
193  p_affine.Identity();
194  p_affine.Translate(p_cubeTackSample, p_cubeTackLine);
195  }
196 
197 
213  void Chip::Load(Cube &cube, const double rotation, const double scale,
214  const int band) {
215  // Initialize our affine transform
216  p_affine.Identity();
217 
218  // We want an affine which translates from chip to cube. Note
219  // that we want to give adjusted chip coordinates such that
220  // (0,0) is at the chip tack point and maps to the cube tack point.
221  p_affine.Scale(scale);
222  p_affine.Rotate(rotation);
223  p_affine.Translate(p_cubeTackSample, p_cubeTackLine);
224 
225  // Now go read the data from the cube into the chip
226  Read(cube, band);
227 
228  // Store off the cube address in case someone wants to match
229  // this chip
230  p_filename = cube.fileName();
231  }
232 
258  void Chip::Load(Cube &cube, const Affine &affine, const bool &keepPoly,
259  const int band) {
260 
261  // Set the tackpoint center to the cube location
262  SetTransform(affine);
263  SetChipPosition(TackSample(), TackLine());
264 
265  // Remove the clipping polygon if requested
266  if(!keepPoly) {
267  delete p_clipPolygon;
268  p_clipPolygon = 0;
269  }
270 
271  // Now go read the data from the cube into the chip
272  Read(cube, band);
273 
274  // Store off the cube address in case someone wants to match
275  // this chip
276  p_filename = cube.fileName();
277  }
278 
279 
320  void Chip::Load(Cube &cube, Chip &match, Cube &matchChipCube, const double scale, const int band) {
321  // See if the match cube has a camera or projection
322  Camera *matchCam = NULL;
323  TProjection *matchProj = NULL;
324  try {
325  matchCam = matchChipCube.camera();
326  }
327  catch(IException &error1) {
328  try {
329  matchProj = (TProjection *) matchChipCube.projection();
330  }
331  catch(IException &error2) {
332  QString msg = "Can not geom chip. ";
333  msg += "Match chip cube [" + matchChipCube.fileName();
334  msg += "] is not a camera or map projection";
335 
336  IException fullError(IException::User, msg, _FILEINFO_);
337  fullError.append(error1);
338  fullError.append(error2);
339 
340  throw fullError;
341  }
342  }
343 
344  // See if the cube we are loading has a camera/projection
345  Camera *cam = NULL;
346  Projection *proj = NULL;
347  try {
348  cam = cube.camera();
349  }
350  catch(IException &error1) {
351  try {
352  proj = cube.projection();
353  }
354  catch(IException &error2) {
355  QString msg = "Can not geom chip. ";
356  msg += "Chip cube [" + cube.fileName();
357  msg += "] is not a camera or map projection";
358 
359  IException fullError(IException::User, msg, _FILEINFO_);
360  fullError.append(error1);
361  fullError.append(error2);
362 
363  throw fullError;
364  }
365  }
366 
367  // Ok we can attempt to create an affine transformation that
368  // maps our chip to the match chip. We will need a set of at
369  // least 3 control points so we can fit the affine transform.
370  // We will try to find 4 points, one from each corner of the chip
371  vector<double> x(4), y(4);
372  vector<double> xp(4), yp(4);
373 
374  // Choose these control points by beginning at each corner and moving
375  // inward in the chip until an acceptable point is found
376  // i = 0, start at upper left corner (1, 1)
377  // i = 1, start at lower left corner (1, Lines()-1)
378  // i = 2, start at upper right corner (Samples()-1, 1)
379  // i = 3, start at lower right corner (Samples()-1, Lines()-1)
380  for(int i = 0; i < (int) xp.size(); i++) {
381  // define initial values for starting/ending sample/line for each index
382  int startSamp = 1;
383  int startLine = 1;
384  int endSamp = Samples() - 1;
385  int endLine = Lines() - 1;
386 
387  bool pointfound = false;
388  while(!pointfound) {
389  // start and end may cross (see MovePoints())
390  // if we move outside chip, break out of loop
391  if(startSamp < 1 || startSamp > Samples() - 1 ||
392  endSamp < 1 || endSamp > Samples() - 1 ||
393  startLine < 1 || startLine > Lines() - 1 ||
394  endLine < 1 || endLine > Lines() - 1) {
395  // unable to find acceptable control point from this corner
396  // erase point and go to the next corner
397  x.erase(x.begin() + i);
398  y.erase(y.begin() + i);
399  xp.erase(xp.begin() + i);
400  yp.erase(yp.begin() + i);
401  i--;
402  break;
403  }
404  int chipSamp, chipLine;
405  if(i < 2) {
406  chipSamp = startSamp;
407  }
408  else {
409  chipSamp = endSamp;
410  }
411  if(i % 2 == 0) {
412  chipLine = startLine;
413  }
414  else {
415  chipLine = endLine;
416  }
417  // Determine the offset from the tack point in our chip
418  // to one of the four corners
419  int sampOffset = chipSamp - TackSample();
420  int lineOffset = chipLine - TackLine();
421 
422  // Use this offset to compute a chip position in the match
423  // 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  p_affine.Solve(&x[0], &y[0], &xp[0], &yp[0], (int)x.size());
527 
528  // TLS 8/3/06 Apply scale
529  p_affine.Scale(scale);
530 
531  // Finally we need to make the affine map the tack point
532  // to the requested cube sample/line
533  p_affine.Compute(0.0, 0.0);
534  double cubeSampleOffset = p_cubeTackSample - p_affine.xp();
535  double cubeLineOffset = p_cubeTackLine - p_affine.yp();
536  p_affine.Translate(cubeSampleOffset, cubeLineOffset);
537 
538  // Now go read the data from the cube into the chip
539  Read(cube, band);
540 
541  // Store off the cube address in case someone wants to match
542  // this chip
543  p_filename = cube.fileName();
544  }
545 
546 
572  bool Chip::PointsColinear(const double x0, const double y0, const double x1, const double y1,
573  const double x2, const double y2, const double tol) {
574  // check angles at each point of the triangle composed of the 3 points
575  // if any angle is near 0 or 180 degrees, then the points are almost colinear
576 
577  // we have the following property:
578  // sin(theta) = |v x w|/(|v|*|w|) where
579  // v=(vx,vy) and w=(wx,wy) are the vectors that define the angle theta
580  // |v| is the magnitude (norm) of the vector. In 2D, this is |v| = sqrt(vx^2 + vy^2)
581  // v x w is the cross product of the vectors. In 2D, this is v x w = vx*wy-vy*wx
582  // See equations (5) and (6) at http://mathworld.wolfram.com/CrossProduct.html
583 
584 
585  // first find the vectors that define the angles at each point
586  // For example, if we shift the point P0 to the origin,
587  // the vectors defining the angle at P0
588  // are v01 = (x1-x0, y1-y0) and v02 = (x2-x0, y2-y0)
589  // Note: v10 = -v01 and |v x w| = |w x v|
590  // so we only need 3 vectors and the order we use these doesn't matter
591  vector<double> v01, v12, v20;
592  //
593  v01.push_back(x1 - x0);
594  v01.push_back(y1 - y0);
595  v12.push_back(x2 - x1);
596  v12.push_back(y2 - y1);
597  v20.push_back(x0 - x2);
598  v20.push_back(y0 - y2);
599 
600  // sin(angle at P0) = |v01 x v02|/(|v01|*|v02|) = |v01x*v02y-v01y*v02x|/(sqrt(v01x^2+v01y^2)*sqrt(v01x^2+v02y^2))
601  double sinP0 = fabs(v01[0] * v20[1] - v01[1] * v20[0]) / sqrt((pow(v01[0], 2) + pow(v01[1], 2)) * (pow(v12[0], 2) + pow(v12[1], 2)));
602  // sin(angle at P1)
603  double sinP1 = fabs(v12[0] * v20[1] - v12[1] * v20[0]) / sqrt((pow(v12[0], 2) + pow(v12[1], 2)) * (pow(v20[0], 2) + pow(v20[1], 2)));
604  // sin(angle at P2)
605  double sinP2 = fabs(v20[0] * v01[1] - v20[1] * v01[0]) / sqrt((pow(v20[0], 2) + pow(v20[1], 2)) * (pow(v01[0], 2) + pow(v01[1], 2)));
606 
607  // We will seek angles with sine near 0 (thus a multiple of 180 degrees or pi radians)
608  // we will use a tolerance of tol degrees (tol*pi/180 radians)
609  // compare the smallest sine value to the sine of tol,
610  // if it is less, then the angle is less than tol degrees or
611  // greater than 180-tol degrees, so points are almost colinear
612  double minSinValue = min(sinP0, min(sinP1, sinP2));
613  if(minSinValue < sin(tol * PI / 180)) {
614  return true;
615  }
616  else {
617  return false;
618  }
619  }
620 
621 
644  vector<int> Chip::MovePoints(const int startSamp, const int startLine, const int endSamp, const int endLine) {
645  vector<int> newlocations(4);
646  int sinc = (endSamp - startSamp) / 4;
647  // Ensures that the inc can cause start and end to cross
648  if(sinc < 1) {
649  sinc = 1;
650  }
651  int linc = (endLine - startLine) / 3;
652  // Ensures that the inc can cause start and end to cross
653  if(linc < 1) {
654  linc = 1;
655  }
656  newlocations[0] = startSamp + sinc;
657  newlocations[1] = startLine + linc;
658  newlocations[2] = endSamp - sinc;
659  newlocations[3] = endLine - linc;
660  return newlocations;
661  }
662 
672  void Chip::SetChipPosition(const double sample, const double line) {
673  p_chipSample = sample;
674  p_chipLine = line;
675  p_affine.Compute(sample - TackSample(), line - TackLine());
676  p_cubeSample = p_affine.xp();
677  p_cubeLine = p_affine.yp();
678  }
679 
680 
691  void Chip::SetCubePosition(const double sample, const double line) {
692  p_cubeSample = sample;
693  p_cubeLine = line;
694  p_affine.ComputeInverse(sample, line);
695  p_chipSample = p_affine.x() + TackSample();
696  p_chipLine = p_affine.y() + TackLine();
697  }
698 
699 
712  void Chip::SetValidRange(const double minimum, const double maximum) {
713  if(minimum >= maximum) {
714  string msg = "Unable to set valid chip range to [" + IString(minimum);
715  msg += ", " + IString(maximum) + "]. First parameter must be smaller than the second.";
716  throw IException(IException::Programmer, msg, _FILEINFO_);
717  }
718 
719  p_validMinimum = minimum;
720  p_validMaximum = maximum;
721  }
722 
723 
732  /* bool Chip::IsValid(int sample, int line) {
733  double value = (*this)(sample,line);
734  if (value < p_validMinimum) return false;
735  if (value > p_validMaximum) return false;
736  return true;
737  }*/
738 
739 
750  bool Chip::IsValid(double percentage) {
751  int validCount = 0;
752  for(int samp = 1; samp <= Samples(); samp++) {
753  for(int line = 1; line <= Lines(); line++) {
754  if(IsValid(samp, line)) validCount++;
755  }
756  }
757  double validPercentage = 100.0 * (double) validCount /
758  (double)(Samples() * Lines());
759  if(validPercentage < percentage) return false;
760  return true;
761  }
762 
763 
779  Chip Chip::Extract(int samples, int lines, int samp, int line) {
780  if(samples > Samples() || lines > Lines()) {
781  string msg = "Cannot extract sub-chip of size [" + IString(samples);
782  msg += ", " + IString(lines) + "] from chip of size [" + IString(Samples());
783  msg += ", " + IString(Lines()) + "]";
784  throw IException(IException::Programmer, msg, _FILEINFO_);
785  }
786 
787  Chip chipped(samples, lines);
788  for(int oline = 1; oline <= lines; oline++) {
789  for(int osamp = 1; osamp <= samples; osamp++) {
790  int thisSamp = samp + (osamp - chipped.TackSample());
791  int thisLine = line + (oline - chipped.TackLine());
792  if((thisSamp < 1) || (thisLine < 1) ||
793  (thisSamp > Samples()) || thisLine > Lines()) {
794  chipped.SetValue(osamp, oline, Isis::Null);
795  }
796  else {
797  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
798  }
799  }
800  }
801 
802  chipped.p_affine = p_affine;
803  chipped.p_validMinimum = p_validMinimum;
804  chipped.p_validMaximum = p_validMaximum;
805  chipped.p_tackSample = chipped.TackSample() + TackSample() - samp;
806  chipped.p_tackLine = chipped.TackLine() + TackLine() - line;
807 
808  return chipped;
809  }
810 
822  void Chip::Extract(int samp, int line, Chip &chipped) {
823  int samples = chipped.Samples();
824  int lines = chipped.Lines();
825  //chipped.Init(samples, lines);
826  chipped.p_tackSample = ((samples - 1) / 2) + 1;
827  chipped.p_tackLine = ((lines - 1) / 2) + 1;
828 
829  for(int oline = 1; oline <= lines; oline++) {
830  for(int osamp = 1; osamp <= samples; osamp++) {
831  int thisSamp = samp + (osamp - chipped.TackSample());
832  int thisLine = line + (oline - chipped.TackLine());
833  if((thisSamp < 1) || (thisLine < 1) ||
834  (thisSamp > Samples()) || thisLine > Lines()) {
835  chipped.SetValue(osamp, oline, Isis::Null);
836  }
837  else {
838  chipped.SetValue(osamp, oline, GetValue(thisSamp, thisLine));
839  }
840  }
841  }
842 
843  chipped.p_affine = p_affine;
844  chipped.p_validMinimum = p_validMinimum;
845  chipped.p_validMaximum = p_validMaximum;
846  chipped.p_tackSample = chipped.TackSample() + TackSample() - samp;
847  chipped.p_tackLine = chipped.TackLine() + TackLine() - line;
848 
849  return;
850  }
851 
852 
898  void Chip::Extract(Chip &chipped, Affine &affine) {
899  // Create an interpolator and portal for interpolation
900  Interpolator interp(Interpolator::BiLinearType);
901  Portal port(interp.Samples(), interp.Lines(), Isis::Double,
902  interp.HotSample(), interp.HotLine());
903 
904  int samples = chipped.Samples();
905  int lines = chipped.Lines();
906 
907  for(int oline = 1; oline <= lines; oline++) {
908  int relativeLine = oline - chipped.TackLine();
909  for(int osamp = 1; osamp <= samples; osamp++) {
910  int relativeSamp = osamp - chipped.TackSample();
911  affine.Compute(relativeSamp, relativeLine);
912  double xp = affine.xp() + TackSample();
913  double yp = affine.yp() + TackLine();
914  port.SetPosition(xp, yp, 1);
915  for(int i = 0 ; i < port.size() ; i++) {
916  int csamp = port.Sample(i);
917  int cline = port.Line(i);
918  if((csamp < 1) || (cline < 1) ||
919  (csamp > Samples()) || cline > Lines()) {
920  port[i] = Isis::Null;
921  }
922  else {
923  port[i] = GetValue(csamp, cline);
924  }
925  }
926  chipped.SetValue(osamp, oline, interp.Interpolate(xp, yp, port.DoubleBuffer()));
927  }
928  }
929 
930  chipped.p_validMinimum = p_validMinimum;
931  chipped.p_validMaximum = p_validMaximum;
932  chipped.p_filename = p_filename;
933 
934  // Make necessary adjustments to remaining chip elements. Note that this
935  // matrix multiply acheives a completed transform of two Affine matrices.
936  // No translations are required - only update tack points.
937  chipped.p_affine = Affine(TNT::matmult(affine.Forward(), p_affine.Forward()));
938 
939  affine.Compute(0.0, 0.0);
940  chipped.p_cubeTackSample = p_cubeTackSample + affine.xp();
941  chipped.p_cubeTackLine = p_cubeTackLine + affine.yp();
942 
943  chipped.p_chipSample = chipped.TackSample();
944  chipped.p_chipLine = chipped.TackLine();
945  chipped.p_cubeSample = chipped.p_cubeTackSample;
946  chipped.p_cubeLine = chipped.p_cubeTackLine;
947 
948  return;
949  }
950 
951 
959  Isis::Statistics *Chip::Statistics() {
960  Isis::Statistics *stats = new Isis::Statistics();
961 
962  stats->SetValidRange(p_validMinimum, p_validMaximum);
963 
964  for(int i = 0; i < p_chipSamples; i++) {
965  stats->AddData(&p_buf[i][0], p_chipLines);
966  }
967 
968  return stats;
969  }
970 
971 
993  void Chip::Read(Cube &cube, const int band) {
994  // Create an interpolator and portal for geoming
995  Interpolator interp(p_readInterpolator);
996  Portal port(interp.Samples(), interp.Lines(), cube.pixelType(),
997  interp.HotSample(), interp.HotLine());
998  // Loop through the pixels in the chip and geom them
999  for(int line = 1; line <= Lines(); line++) {
1000  for(int samp = 1; samp <= Samples(); samp++) {
1001  SetChipPosition((double)samp, (double)line);
1002  if((CubeSample() < 0.5) || (CubeLine() < 0.5) ||
1003  (CubeSample() > cube.sampleCount() + 0.5) ||
1004  (CubeLine() > cube.lineCount() + 0.5)) {
1005  p_buf[line-1][samp-1] = Isis::NULL8;
1006  }
1007  else if(p_clipPolygon == NULL) {
1008  port.SetPosition(CubeSample(), CubeLine(), band);
1009  cube.read(port);
1010  p_buf[line-1][samp-1] =
1011  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
1012  }
1013  else {
1014  geos::geom::Point *pnt = globalFactory.createPoint(
1015  geos::geom::Coordinate(CubeSample(), CubeLine()));
1016  if(pnt->within(p_clipPolygon)) {
1017  port.SetPosition(CubeSample(), CubeLine(), band);
1018  cube.read(port);
1019  p_buf[line-1][samp-1] =
1020  interp.Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
1021  }
1022  else {
1023  p_buf[line-1][samp-1] = Isis::NULL8;
1024  }
1025  delete pnt;
1026  }
1027  }
1028  }
1029  }
1030 
1031 
1037  void Chip::Write(const QString &filename) {
1038  Cube c;
1039  c.setDimensions(Samples(), Lines(), 1);
1040  c.create(filename);
1041  LineManager line(c);
1042  for(int i = 1; i <= Lines(); i++) {
1043  line.SetLine(i);
1044  for(int j = 1; j <= Samples(); j++) {
1045  line[j-1] = GetValue(j, i);
1046  }
1047  c.write(line);
1048  }
1049  c.close();
1050  }
1051 
1052 
1061  void Chip::SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon) {
1062  if(p_clipPolygon != NULL) delete p_clipPolygon;
1063  p_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1064  }
1065 
1071  Chip &Chip::operator=(const Chip &other) {
1072  p_chipSamples = other.p_chipSamples;
1073  p_chipLines = other.p_chipLines;
1074  p_buf = other.p_buf;
1075  p_tackSample = other.p_tackSample;
1076  p_tackLine = other.p_tackLine;
1077 
1078  p_cubeTackSample = other.p_cubeTackSample;
1079  p_cubeTackLine = other.p_cubeTackLine;
1080 
1081  p_validMinimum = other.p_validMinimum;
1082  p_validMaximum = other.p_validMaximum;
1083 
1084  p_chipSample = other.p_chipSample;
1085  p_chipLine = other.p_chipLine;
1086  p_cubeSample = other.p_cubeSample;
1087  p_cubeLine = other.p_cubeLine;
1088 
1089  // Free allocated memory.
1090  if (p_clipPolygon) {
1091  delete p_clipPolygon;
1092  p_clipPolygon = NULL;
1093  }
1094 
1095  if (other.p_clipPolygon) {
1096  p_clipPolygon = PolygonTools::MakeMultiPolygon(
1097  other.p_clipPolygon->clone());
1098  }
1099 
1100  p_affine = other.p_affine;
1101  p_readInterpolator = other.p_readInterpolator;
1102  p_filename = other.p_filename;
1103 
1104  return *this;
1105  }
1106 } // end namespace isis
1107