39 #include "geos/geom/Point.h"
40 #include "tnt/tnt_array2d_utils.h"
57 Chip::Chip(
const Chip &other) {
76 p_clipPolygon = PolygonTools::MakeMultiPolygon(
94 Chip::Chip(
const int samples,
const int lines) {
101 if(p_clipPolygon != NULL)
delete p_clipPolygon;
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);
127 void Chip::Init(
const int samples,
const int lines) {
128 SetReadInterpolator(Interpolator::CubicConvolutionType);
129 SetSize(samples, lines);
131 p_clipPolygon = NULL;
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.";
151 p_chipSamples = samples;
155 for(
int i = 0; i < lines; i++) {
156 p_buf[i].resize(samples);
159 p_tackSample = ((samples - 1) / 2) + 1;
160 p_tackLine = ((lines - 1) / 2) + 1;
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);
174 double minLine = p_cubeTackLine - ((p_chipLines - 1) / 2);
175 double maxLine = p_cubeTackLine + ((p_chipLines - 1) / 2);
177 if(sample < minSamp || sample > maxSamp)
return false;
178 if(line < minLine || line > maxLine)
return false;
190 void Chip::TackCube(
const double cubeSample,
const double cubeLine) {
191 p_cubeTackSample = cubeSample;
192 p_cubeTackLine = cubeLine;
194 p_affine.Translate(p_cubeTackSample, p_cubeTackLine);
213 void Chip::Load(
Cube &cube,
const double rotation,
const double scale,
221 p_affine.Scale(scale);
222 p_affine.Rotate(rotation);
223 p_affine.Translate(p_cubeTackSample, p_cubeTackLine);
258 void Chip::Load(
Cube &cube,
const Affine &affine,
const bool &keepPoly,
262 SetTransform(affine);
263 SetChipPosition(TackSample(), TackLine());
267 delete p_clipPolygon;
320 void Chip::Load(
Cube &cube,
Chip &match,
Cube &matchChipCube,
const double scale,
const int band) {
325 matchCam = matchChipCube.
camera();
332 QString msg =
"Can not geom chip. ";
333 msg +=
"Match chip cube [" + matchChipCube.
fileName();
334 msg +=
"] is not a camera or map projection";
355 QString msg =
"Can not geom chip. ";
356 msg +=
"Chip cube [" + cube.
fileName();
357 msg +=
"] is not a camera or map projection";
371 vector<double> x(4), y(4);
372 vector<double> xp(4), yp(4);
380 for(
int i = 0; i < (int) xp.size(); i++) {
384 int endSamp = Samples() - 1;
385 int endLine = Lines() - 1;
387 bool pointfound =
false;
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) {
397 x.erase(x.begin() + i);
398 y.erase(y.begin() + i);
399 xp.erase(xp.begin() + i);
400 yp.erase(yp.begin() + i);
404 int chipSamp, chipLine;
406 chipSamp = startSamp;
412 chipLine = startLine;
419 int sampOffset = chipSamp - TackSample();
420 int lineOffset = chipLine - TackLine();
424 double matchChipSamp = match.
TackSample() + sampOffset;
425 double matchChipLine = match.
TackLine() + lineOffset;
430 if(matchCam != NULL) {
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];
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];
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];
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];
504 if(PointsColinear(xp[0], yp[0], xp[1], yp[1], xp[i], yp[i], tol)) {
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];
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() +
"].";
526 p_affine.Solve(&x[0], &y[0], &xp[0], &yp[0], (
int)x.size());
529 p_affine.Scale(scale);
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);
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) {
591 vector<double> v01, v12, v20;
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);
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)));
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)));
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)));
612 double minSinValue = min(sinP0, min(sinP1, sinP2));
613 if(minSinValue < sin(tol *
PI / 180)) {
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;
651 int linc = (endLine - startLine) / 3;
656 newlocations[0] = startSamp + sinc;
657 newlocations[1] = startLine + linc;
658 newlocations[2] = endSamp - sinc;
659 newlocations[3] = endLine - linc;
672 void Chip::SetChipPosition(
const double sample,
const double line) {
673 p_chipSample = sample;
675 p_affine.Compute(sample - TackSample(), line - TackLine());
676 p_cubeSample = p_affine.xp();
677 p_cubeLine = p_affine.yp();
691 void Chip::SetCubePosition(
const double sample,
const double line) {
692 p_cubeSample = sample;
694 p_affine.ComputeInverse(sample, line);
695 p_chipSample = p_affine.x() + TackSample();
696 p_chipLine = p_affine.y() + TackLine();
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.";
719 p_validMinimum = minimum;
720 p_validMaximum = maximum;
750 bool Chip::IsValid(
double percentage) {
752 for(
int samp = 1; samp <= Samples(); samp++) {
753 for(
int line = 1; line <= Lines(); line++) {
754 if(IsValid(samp, line)) validCount++;
757 double validPercentage = 100.0 * (double) validCount /
758 (
double)(Samples() * Lines());
759 if(validPercentage < percentage)
return false;
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()) +
"]";
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()) {
797 chipped.
SetValue(osamp, oline, GetValue(thisSamp, thisLine));
822 void Chip::Extract(
int samp,
int line,
Chip &chipped) {
823 int samples = chipped.
Samples();
824 int lines = chipped.
Lines();
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()) {
838 chipped.
SetValue(osamp, oline, GetValue(thisSamp, thisLine));
904 int samples = chipped.
Samples();
905 int lines = chipped.
Lines();
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()) {
923 port[i] = GetValue(csamp, cline);
962 stats->SetValidRange(p_validMinimum, p_validMaximum);
964 for(
int i = 0; i < p_chipSamples; i++) {
965 stats->
AddData(&p_buf[i][0], p_chipLines);
993 void Chip::Read(
Cube &cube,
const int band) {
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) ||
1004 (CubeLine() > cube.
lineCount() + 0.5)) {
1005 p_buf[line-1][samp-1] = Isis::NULL8;
1007 else if(p_clipPolygon == NULL) {
1008 port.SetPosition(CubeSample(), CubeLine(), band);
1010 p_buf[line-1][samp-1] =
1011 interp.
Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
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);
1019 p_buf[line-1][samp-1] =
1020 interp.
Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
1023 p_buf[line-1][samp-1] = Isis::NULL8;
1037 void Chip::Write(
const QString &filename) {
1042 for(
int i = 1; i <= Lines(); i++) {
1044 for(
int j = 1; j <= Samples(); j++) {
1045 line[j-1] = GetValue(j, i);
1061 void Chip::SetClipPolygon(
const geos::geom::MultiPolygon &clipPolygon) {
1062 if(p_clipPolygon != NULL)
delete p_clipPolygon;
1063 p_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1074 p_buf = other.
p_buf;
1090 if (p_clipPolygon) {
1091 delete p_clipPolygon;
1092 p_clipPolygon = NULL;
1096 p_clipPolygon = PolygonTools::MakeMultiPolygon(