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
29using namespace std;
30namespace Isis {
31
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) {
64 other.m_clipPolygon->clone().release());
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
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);
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 }
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;
187 }
188
189
203 void Chip::Load(Cube &cube, const double rotation, const double scale, const int band) {
204 // Initialize our affine transform
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);
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);
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());
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);
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
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
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 std::unique_ptr<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 pnt.reset();
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;
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) {
1047 other.m_clipPolygon->clone().release());
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
Affine basis function.
Definition Affine.h:65
AMatrix Forward() const
Returns the forward Affine matrix.
Definition Affine.h:127
void ComputeInverse(double xp, double yp)
Compute (x,y) given (xp,yp).
Definition Affine.cpp:205
double xp() const
Returns the computed x'.
Definition Affine.h:86
double y() const
Returns the computed y.
Definition Affine.h:115
void Translate(double tx, double ty)
Apply a translation to the current affine transform.
Definition Affine.cpp:134
double yp() const
Returns the computed y'.
Definition Affine.h:95
void Scale(double scaleFactor)
Apply a scale to the current affine transform.
Definition Affine.cpp:174
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
Definition Affine.cpp:191
void Identity()
Set the forward and inverse affine transform to the identity.
Definition Affine.cpp:73
void Solve(const double x[], const double y[], const double xp[], const double yp[], int n)
Given a set of coordinate pairs (n >= 3), compute the affine transform that best fits the points.
Definition Affine.cpp:92
void Rotate(double rot)
Apply a translation to the current affine transform.
Definition Affine.cpp:151
double x() const
Returns the computed x.
Definition Affine.h:106
A small chip of data used for pattern matching.
Definition Chip.h:86
double CubeLine() const
Definition Chip.h:210
Affine m_affine
Transform set by SetTransform.
Definition Chip.h:366
void SetReadInterpolator(const Interpolator::interpType type)
Sets Interpolator Type for loading a chip.
Definition Chip.h:323
double m_cubeTackSample
cube sample at the chip tack
Definition Chip.h:352
void SetSize(const int samples, const int lines)
Change the size of the Chip.
Definition Chip.cpp:134
void Write(const QString &filename)
Writes the contents of the Chip to a cube.
Definition Chip.cpp:985
double GetValue(int sample, int line)
Loads a Chip with a value.
Definition Chip.h:145
Interpolator::interpType m_readInterpolator
Interpolator type set by.
Definition Chip.h:369
void SetTransform(const Affine &affine, const bool &keepPoly=true)
Sets the internal Affine transform to new translation.
Definition Chip.h:290
int Samples() const
Definition Chip.h:99
double m_cubeSample
cube sample set by SetCubePosition
Definition Chip.h:360
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Set the valid range of data in the chip.
Definition Chip.cpp:681
bool PointsColinear(double x0, double y0, double x1, double y1, double x2, double y2, double tol)
This method is called by Load() to determine whether the given 3 points are nearly colinear.
Definition Chip.cpp:546
double m_cubeLine
cube line set by SetCubePosition
Definition Chip.h:361
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
Definition Chip.h:176
std::vector< std::vector< double > > m_buf
Chip buffer.
Definition Chip.h:348
bool IsInsideChip(double sample, double line)
Definition Chip.cpp:162
int Lines() const
Definition Chip.h:106
void SetAllValues(const double &d)
Single value assignment operator.
Definition Chip.cpp:100
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
Definition Chip.cpp:643
double m_chipLine
chip line set by SetChip/CubePosition
Definition Chip.h:359
double m_validMinimum
valid minimum chip pixel value
Definition Chip.h:355
int m_tackSample
Middle sample of the chip.
Definition Chip.h:349
Isis::Statistics * Statistics()
Returns a statistics object of the current data in the chip.
Definition Chip.cpp:909
void SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon)
Sets the clipping polygon for this chip.
Definition Chip.cpp:1008
std::vector< int > MovePoints(int startSamp, int startLine, int endSamp, int endLine)
This method is called by Load() to move a control point across the chip.
Definition Chip.cpp:615
void Read(Cube &cube, const int band)
This method reads data from a cube and puts it into the chip.
Definition Chip.cpp:939
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
Definition Chip.cpp:182
double CubeSample() const
Definition Chip.h:203
bool IsValid(int sample, int line)
Definition Chip.h:240
int m_tackLine
Middle line of the chip.
Definition Chip.h:350
virtual ~Chip()
Destroys the Chip object.
Definition Chip.cpp:88
Chip Extract(int samples, int lines, int samp, int line)
Extract a sub-chip from a chip.
Definition Chip.cpp:727
int m_chipLines
Number of lines in the chip.
Definition Chip.h:347
geos::geom::MultiPolygon * m_clipPolygon
clipping polygon set by SetClipPolygon
Definition Chip.h:363
void Load(Cube &cube, const double rotation=0.0, const double scale=1.0, const int band=1)
Load cube data into the Chip.
Definition Chip.cpp:203
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.
Definition Chip.h:187
Chip & operator=(const Chip &other)
Copy assignment operator.
Definition Chip.cpp:1021
Chip()
Constructs a Chip.
Definition Chip.cpp:35
void SetCubePosition(const double sample, const double line)
Compute the position of the chip given a cube coordinate.
Definition Chip.cpp:660
void Init(const int samples, const int lines)
Common initialization used by constructors.
Definition Chip.cpp:116
double m_cubeTackLine
cube line at the chip tack
Definition Chip.h:353
double m_chipSample
chip sample set by SetChip/CubePosition
Definition Chip.h:358
QString m_filename
FileName of loaded cube.
Definition Chip.h:373
int m_chipSamples
Number of samples in the chip.
Definition Chip.h:346
double m_validMaximum
valid maximum chip pixel value
Definition Chip.h:356
IO Handler for Isis Cubes.
Definition Cube.h:168
int lineCount() const
Definition Cube.cpp:1740
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Definition Cube.cpp:1223
Camera * camera()
Return a camera associated with the cube.
Definition Cube.cpp:1457
int sampleCount() const
Definition Cube.cpp:1813
PixelType pixelType() const
Definition Cube.cpp:1764
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:813
virtual QString fileName() const
Returns the opened cube's filename.
Definition Cube.cpp:1569
Projection * projection()
Definition Cube.cpp:1800
Isis exception class.
Definition IException.h:91
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
Pixel interpolator.
Buffer manager, for moving through a cube in lines.
Definition LineManager.h:39
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...
static geos::geom::MultiPolygon * CopyMultiPolygon(const geos::geom::MultiPolygon *mpolygon)
This static method will create a deep copy of a geos::geom::MultiPolygon.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
Buffer for containing a two dimensional section of an image.
Definition Portal.h:36
Base class for Map Projections.
Definition Projection.h:155
This class is used to accumulate statistics on double arrays.
Definition Statistics.h:94
Base class for Map TProjections.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Definition IString.cpp:211
const double Null
Value for an Isis Null pixel.
const double PI
The mathematical constant PI.
Definition Constants.h:40
Namespace for the standard library.