11#include "IException.h"
12#include "Interpolator.h"
14#include "LineManager.h"
15#include "PolygonTools.h"
17#include "Projection.h"
18#include "Statistics.h"
19#include "TProjection.h"
26#include <geos/geom/Point.h>
27#include <tnt/tnt_array2d_utils.h>
62 if (other.m_clipPolygon) {
64 other.m_clipPolygon->clone().release());
101 for (
unsigned int i = 0; i <
m_buf.size(); i++) {
135 if ( samples <= 0.0 || lines <= 0.0 ) {
137 msg +=
"Unable to set chip size to [";
139 msg +=
toString(lines) +
"]. Samples and lines must be greater than zero.";
146 for (
int i = 0; i < lines; i++) {
147 m_buf[i].resize(samples);
169 if ( sample < minSamp || sample > maxSamp )
return false;
170 if ( line < minLine || line > maxLine )
return false;
203 void Chip::Load(
Cube &cube,
const double rotation,
const double scale,
const int band) {
306 matchCam = matchChipCube.camera();
310 matchProj = (
TProjection *) matchChipCube.projection();
313 QString msg =
"Can not geom chip. ";
314 msg +=
"Match chip cube [" + matchChipCube.fileName();
315 msg +=
"] is not a camera or map projection";
318 fullError.append(error1);
319 fullError.append(error2);
336 QString msg =
"Can not geom chip. ";
337 msg +=
"Chip cube [" + cube.
fileName();
338 msg +=
"] is not a camera or map projection";
341 fullError.append(error1);
342 fullError.append(error2);
351 vector<double> x(4), y(4);
352 vector<double> xp(4), yp(4);
360 for (
int i = 0; i < (int) xp.size(); i++) {
365 int endLine =
Lines() - 1;
367 bool pointfound =
false;
368 while (!pointfound) {
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) {
377 x.erase(x.begin() + i);
378 y.erase(y.begin() + i);
379 xp.erase(xp.begin() + i);
380 yp.erase(yp.begin() + i);
384 int chipSamp, chipLine;
386 chipSamp = startSamp;
392 chipLine = startLine;
399 int lineOffset = chipLine -
TackLine();
402 double matchChipSamp = match.TackSample() + sampOffset;
403 double matchChipLine = match.TackLine() + lineOffset;
406 match.SetChipPosition(matchChipSamp, matchChipLine);
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];
418 lat = matchCam->UniversalLatitude();
419 lon = matchCam->UniversalLongitude();
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];
431 lat = matchProj->UniversalLatitude();
432 lon = matchProj->UniversalLongitude();
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];
447 samp = cam->Sample();
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];
460 samp = proj->WorldX();
461 line = proj->WorldY();
478 if (xp.size() == 3) {
482 if (
PointsColinear(xp[0], yp[0], xp[1], yp[1], xp[i], yp[i], tol) ) {
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];
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() +
"].";
547 const double x2,
const double y2,
const double tol) {
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);
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)));
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)));
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)));
589 double minSinValue = min(sinP0, min(sinP1, sinP2));
590 if ( minSinValue < sin(tol *
PI / 180) ) {
616 const int endSamp,
const int endLine) {
617 vector<int> newlocations(4);
618 int sinc = (endSamp - startSamp) / 4;
623 int linc = (endLine - startLine) / 3;
628 newlocations[0] = startSamp + sinc;
629 newlocations[1] = startLine + linc;
630 newlocations[2] = endSamp - sinc;
631 newlocations[3] = endLine - linc;
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.";
703 for (
int samp = 1; samp <=
Samples(); samp++) {
704 for (
int line = 1; line <=
Lines(); line++) {
705 if (
IsValid(samp, line)) validCount++;
708 double validPercentage = 100.0 * (double) validCount /
710 if (validPercentage < percentage)
return false;
729 QString msg =
"Cannot extract sub-chip of size [" +
toString(samples);
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) ||
743 (thisLine >
Lines()) ) {
747 chipped.SetValue(osamp, oline,
GetValue(thisSamp, thisLine));
755 chipped.m_tackSample = chipped.TackSample() +
TackSample() - samp;
756 chipped.m_tackLine = chipped.TackLine() +
TackLine() - line;
773 int samples = chipped.
Samples();
774 int lines = chipped.Lines();
776 chipped.m_tackSample = ((samples - 1) / 2) + 1;
777 chipped.m_tackLine = ((lines - 1) / 2) + 1;
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) ||
786 (thisLine >
Lines()) ) {
790 chipped.SetValue(osamp, oline,
GetValue(thisSamp, thisLine));
798 chipped.m_tackSample = chipped.TackSample() +
TackSample() - samp;
799 chipped.m_tackLine = chipped.TackLine() +
TackLine() - line;
849 Portal port(interp.Samples(), interp.Lines(), Isis::Double,
850 interp.HotSample(), interp.HotLine());
852 int samples = chipped.Samples();
853 int lines = chipped.Lines();
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);
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);
869 (cline >
Lines()) ) {
876 chipped.SetValue(osamp, oline, interp.Interpolate(xp, yp, port.DoubleBuffer()));
889 affine.Compute(0.0, 0.0);
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;
943 interp.HotSample(), interp.HotLine());
945 for (
int line = 1; line <=
Lines(); line++) {
946 for (
int samp = 1; samp <=
Samples(); samp++) {
953 m_buf[line-1][samp-1] = Isis::NULL8;
958 m_buf[line-1][samp-1] =
962 std::unique_ptr<geos::geom::Point> pnt = globalFactory->createPoint(
967 m_buf[line-1][samp-1] =
971 m_buf[line-1][samp-1] = Isis::NULL8;
990 for (
int i = 1; i <=
Lines(); i++) {
992 for (
int j = 1; j <=
Samples(); j++) {
1024 m_buf = other.m_buf;
1045 if (other.m_clipPolygon) {
1047 other.m_clipPolygon->clone().release());
AMatrix Forward() const
Returns the forward Affine matrix.
void ComputeInverse(double xp, double yp)
Compute (x,y) given (xp,yp).
double xp() const
Returns the computed x'.
double y() const
Returns the computed y.
void Translate(double tx, double ty)
Apply a translation to the current affine transform.
double yp() const
Returns the computed y'.
void Scale(double scaleFactor)
Apply a scale to the current affine transform.
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
void Identity()
Set the forward and inverse affine transform to the identity.
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.
void Rotate(double rot)
Apply a translation to the current affine transform.
double x() const
Returns the computed x.
A small chip of data used for pattern matching.
Affine m_affine
Transform set by SetTransform.
void SetReadInterpolator(const Interpolator::interpType type)
Sets Interpolator Type for loading a chip.
double m_cubeTackSample
cube sample at the chip tack
void SetSize(const int samples, const int lines)
Change the size of the Chip.
void Write(const QString &filename)
Writes the contents of the Chip to a cube.
double GetValue(int sample, int line)
Loads a Chip with a value.
Interpolator::interpType m_readInterpolator
Interpolator type set by.
void SetTransform(const Affine &affine, const bool &keepPoly=true)
Sets the internal Affine transform to new translation.
double m_cubeSample
cube sample set by SetCubePosition
void SetValidRange(const double minimum=Isis::ValidMinimum, const double maximum=Isis::ValidMaximum)
Set the valid range of data in the chip.
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.
double m_cubeLine
cube line set by SetCubePosition
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
std::vector< std::vector< double > > m_buf
Chip buffer.
bool IsInsideChip(double sample, double line)
void SetAllValues(const double &d)
Single value assignment operator.
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
double m_chipLine
chip line set by SetChip/CubePosition
double m_validMinimum
valid minimum chip pixel value
int m_tackSample
Middle sample of the chip.
Isis::Statistics * Statistics()
Returns a statistics object of the current data in the chip.
void SetClipPolygon(const geos::geom::MultiPolygon &clipPolygon)
Sets the clipping polygon for this chip.
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.
void Read(Cube &cube, const int band)
This method reads data from a cube and puts it into the chip.
void TackCube(const double cubeSample, const double cubeLine)
This sets which cube position will be located at the chip tack position.
double CubeSample() const
bool IsValid(int sample, int line)
int m_tackLine
Middle line of the chip.
virtual ~Chip()
Destroys the Chip object.
Chip Extract(int samples, int lines, int samp, int line)
Extract a sub-chip from a chip.
int m_chipLines
Number of lines in the chip.
geos::geom::MultiPolygon * m_clipPolygon
clipping polygon set by SetClipPolygon
void Load(Cube &cube, const double rotation=0.0, const double scale=1.0, const int band=1)
Load cube data into the Chip.
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.
Chip & operator=(const Chip &other)
Copy assignment operator.
void SetCubePosition(const double sample, const double line)
Compute the position of the chip given a cube coordinate.
void Init(const int samples, const int lines)
Common initialization used by constructors.
double m_cubeTackLine
cube line at the chip tack
double m_chipSample
chip sample set by SetChip/CubePosition
QString m_filename
FileName of loaded cube.
int m_chipSamples
Number of samples in the chip.
double m_validMaximum
valid maximum chip pixel value
IO Handler for Isis Cubes.
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Camera * camera()
Return a camera associated with the cube.
PixelType pixelType() const
void read(Blob &blob, const std::vector< PvlKeyword > keywords=std::vector< PvlKeyword >()) const
This method will read data from the specified Blob object.
virtual QString fileName() const
Returns the opened cube's filename.
Projection * projection()
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
Buffer manager, for moving through a cube in lines.
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...
Buffer for containing a two dimensional section of an image.
Base class for Map Projections.
This class is used to accumulate statistics on double arrays.
Base class for Map TProjections.
This is free and unencumbered software released into the public domain.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
const double Null
Value for an Isis Null pixel.
const double PI
The mathematical constant PI.
Namespace for the standard library.