46 #include <geos/geom/Point.h> 47 #include <tnt/tnt_array2d_utils.h> 66 Chip::Chip(
const Chip &other) {
85 m_clipPolygon = PolygonTools::MakeMultiPolygon(
104 Chip::Chip(
const int samples,
const int lines) {
105 Init(samples, lines);
111 if (m_clipPolygon != NULL)
delete m_clipPolygon;
122 void Chip::SetAllValues(
const double &d) {
123 for (
unsigned int i = 0; i < m_buf.size(); i++) {
124 fill(m_buf[i].begin(), m_buf[i].end(), d);
138 void Chip::Init(
const int samples,
const int lines) {
139 SetReadInterpolator(Interpolator::CubicConvolutionType);
140 SetSize(samples, lines);
142 m_clipPolygon = NULL;
156 void Chip::SetSize(
const int samples,
const int lines) {
157 if ( samples <= 0.0 || lines <= 0.0 ) {
159 msg +=
"Unable to set chip size to [";
161 msg +=
toString(lines) +
"]. Samples and lines must be greater than zero.";
164 m_chipSamples = samples;
168 for (
int i = 0; i < lines; i++) {
169 m_buf[i].resize(samples);
172 m_tackSample = ((samples - 1) / 2) + 1;
173 m_tackLine = ((lines - 1) / 2) + 1;
184 bool Chip::IsInsideChip(
double sample,
double line) {
185 double minSamp = m_cubeTackSample - ((m_chipSamples - 1) / 2);
186 double maxSamp = m_cubeTackSample + ((m_chipSamples - 1) / 2);
188 double minLine = m_cubeTackLine - ((m_chipLines - 1) / 2);
189 double maxLine = m_cubeTackLine + ((m_chipLines - 1) / 2);
191 if ( sample < minSamp || sample > maxSamp )
return false;
192 if ( line < minLine || line > maxLine )
return false;
204 void Chip::TackCube(
const double cubeSample,
const double cubeLine) {
205 m_cubeTackSample = cubeSample;
206 m_cubeTackLine = cubeLine;
208 m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
225 void Chip::Load(
Cube &cube,
const double rotation,
const double scale,
const int band) {
231 m_affine.Scale(scale);
232 m_affine.Rotate(rotation);
233 m_affine.Translate(m_cubeTackSample, m_cubeTackLine);
266 void Chip::Load(
Cube &cube,
const Affine &affine,
const bool &keepPoly,
const int band) {
269 SetTransform(affine);
270 SetChipPosition(TackSample(), TackLine());
274 delete m_clipPolygon;
322 void Chip::Load(
Cube &cube,
Chip &match,
Cube &matchChipCube,
const double scale,
const int band)
328 matchCam = matchChipCube.
camera();
335 QString msg =
"Can not geom chip. ";
336 msg +=
"Match chip cube [" + matchChipCube.
fileName();
337 msg +=
"] is not a camera or map projection";
358 QString msg =
"Can not geom chip. ";
359 msg +=
"Chip cube [" + cube.
fileName();
360 msg +=
"] is not a camera or map projection";
373 vector<double> x(4), y(4);
374 vector<double> xp(4), yp(4);
382 for (
int i = 0; i < (int) xp.size(); i++) {
386 int endSamp = Samples() - 1;
387 int endLine = Lines() - 1;
389 bool pointfound =
false;
390 while (!pointfound) {
393 if (startSamp < 1 || startSamp > Samples() - 1 ||
394 endSamp < 1 || endSamp > Samples() - 1 ||
395 startLine < 1 || startLine > Lines() - 1 ||
396 endLine < 1 || endLine > Lines() - 1) {
399 x.erase(x.begin() + i);
400 y.erase(y.begin() + i);
401 xp.erase(xp.begin() + i);
402 yp.erase(yp.begin() + i);
406 int chipSamp, chipLine;
408 chipSamp = startSamp;
414 chipLine = startLine;
420 int sampOffset = chipSamp - TackSample();
421 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];
500 if (xp.size() == 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 m_affine.Solve(&x[0], &y[0], &xp[0], &yp[0], (
int)x.size());
529 m_affine.Scale(scale);
532 m_affine.Compute(0.0, 0.0);
533 double cubeSampleOffset = m_cubeTackSample - m_affine.xp();
534 double cubeLineOffset = m_cubeTackLine - m_affine.yp();
535 m_affine.Translate(cubeSampleOffset, cubeLineOffset);
568 bool Chip::PointsColinear(
const double x0,
const double y0,
const double x1,
const double y1,
569 const double x2,
const double y2,
const double tol) {
587 vector<double> v01, v12, v20;
588 v01.push_back(x1 - x0);
589 v01.push_back(y1 - y0);
590 v12.push_back(x2 - x1);
591 v12.push_back(y2 - y1);
592 v20.push_back(x0 - x2);
593 v20.push_back(y0 - y2);
597 double sinP0 = fabs(v01[0] * v20[1] - v01[1] * v20[0]) /
598 sqrt((pow(v01[0], 2) + pow(v01[1], 2)) * (pow(v12[0], 2) + pow(v12[1], 2)));
600 double sinP1 = fabs(v12[0] * v20[1] - v12[1] * v20[0]) /
601 sqrt((pow(v12[0], 2) + pow(v12[1], 2)) * (pow(v20[0], 2) + pow(v20[1], 2)));
603 double sinP2 = fabs(v20[0] * v01[1] - v20[1] * v01[0]) /
604 sqrt((pow(v20[0], 2) + pow(v20[1], 2)) * (pow(v01[0], 2) + pow(v01[1], 2)));
611 double minSinValue = min(sinP0, min(sinP1, sinP2));
612 if ( minSinValue < sin(tol *
PI / 180) ) {
637 vector<int> Chip::MovePoints(
const int startSamp,
const int startLine,
638 const int endSamp,
const int endLine) {
639 vector<int> newlocations(4);
640 int sinc = (endSamp - startSamp) / 4;
645 int linc = (endLine - startLine) / 3;
650 newlocations[0] = startSamp + sinc;
651 newlocations[1] = startLine + linc;
652 newlocations[2] = endSamp - sinc;
653 newlocations[3] = endLine - linc;
665 void Chip::SetChipPosition(
const double sample,
const double line) {
666 m_chipSample = sample;
668 m_affine.Compute(sample - TackSample(), line - TackLine());
669 m_cubeSample = m_affine.xp();
670 m_cubeLine = m_affine.yp();
682 void Chip::SetCubePosition(
const double sample,
const double line) {
683 m_cubeSample = sample;
685 m_affine.ComputeInverse(sample, line);
686 m_chipSample = m_affine.x() + TackSample();
687 m_chipLine = m_affine.y() + TackLine();
703 void Chip::SetValidRange(
const double minimum,
const double maximum) {
704 if (minimum >= maximum) {
705 QString msg =
"Unable to set valid chip range to [" +
toString(minimum);
706 msg +=
", " +
toString(maximum) +
"]. First parameter must be smaller than the second.";
710 m_validMinimum = minimum;
711 m_validMaximum = maximum;
723 bool Chip::IsValid(
double percentage) {
725 for (
int samp = 1; samp <= Samples(); samp++) {
726 for (
int line = 1; line <= Lines(); line++) {
727 if (IsValid(samp, line)) validCount++;
730 double validPercentage = 100.0 * (double) validCount /
731 (
double)(Samples() * Lines());
732 if (validPercentage < percentage)
return false;
749 Chip Chip::Extract(
int samples,
int lines,
int samp,
int line) {
750 if ( samples > Samples() || lines > Lines() ) {
751 QString msg =
"Cannot extract sub-chip of size [" +
toString(samples);
752 msg +=
", " +
toString(lines) +
"] from chip of size [" +
toString(Samples());
753 msg +=
", " +
toString(Lines()) +
"]";
757 Chip chipped(samples, lines);
758 for (
int oline = 1; oline <= lines; oline++) {
759 for (
int osamp = 1; osamp <= samples; osamp++) {
760 int thisSamp = samp + (osamp - chipped.
TackSample());
761 int thisLine = line + (oline - chipped.
TackLine());
762 if ((thisSamp < 1) ||
764 (thisSamp > Samples()) ||
765 (thisLine > Lines()) ) {
769 chipped.
SetValue(osamp, oline, GetValue(thisSamp, thisLine));
794 void Chip::Extract(
int samp,
int line,
Chip &chipped) {
795 int samples = chipped.
Samples();
796 int lines = chipped.
Lines();
801 for (
int oline = 1; oline <= lines; oline++) {
802 for (
int osamp = 1; osamp <= samples; osamp++) {
803 int thisSamp = samp + (osamp - chipped.
TackSample());
804 int thisLine = line + (oline - chipped.
TackLine());
805 if ((thisSamp < 1) ||
807 (thisSamp > Samples()) ||
808 (thisLine > Lines()) ) {
812 chipped.
SetValue(osamp, oline, GetValue(thisSamp, thisLine));
874 int samples = chipped.
Samples();
875 int lines = chipped.
Lines();
877 for (
int oline = 1; oline <= lines; oline++) {
878 int relativeLine = oline - chipped.
TackLine();
879 for (
int osamp = 1; osamp <= samples; osamp++) {
880 int relativeSamp = osamp - chipped.
TackSample();
881 affine.
Compute(relativeSamp, relativeLine);
882 double xp = affine.
xp() + TackSample();
883 double yp = affine.
yp() + TackLine();
884 port.SetPosition(xp, yp, 1);
885 for (
int i = 0; i < port.size(); i++) {
886 int csamp = port.Sample(i);
887 int cline = port.Line(i);
890 (csamp > Samples()) ||
891 (cline > Lines()) ) {
895 port[i] = GetValue(csamp, cline);
934 stats->SetValidRange(m_validMinimum, m_validMaximum);
936 for (
int i = 0; i < m_chipSamples; i++) {
937 stats->
AddData(&m_buf[i][0], m_chipLines);
961 void Chip::Read(
Cube &cube,
const int band) {
967 for (
int line = 1; line <= Lines(); line++) {
968 for (
int samp = 1; samp <= Samples(); samp++) {
969 SetChipPosition((
double)samp, (
double)line);
970 if ((CubeSample() < 0.5) ||
971 (CubeLine() < 0.5) ||
975 m_buf[line-1][samp-1] = Isis::NULL8;
977 else if (m_clipPolygon == NULL) {
978 port.SetPosition(CubeSample(), CubeLine(), band);
980 m_buf[line-1][samp-1] =
981 interp.
Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
984 geos::geom::Point *pnt = globalFactory.createPoint(
985 geos::geom::Coordinate(CubeSample(), CubeLine()));
986 if (pnt->within(m_clipPolygon)) {
987 port.SetPosition(CubeSample(), CubeLine(), band);
989 m_buf[line-1][samp-1] =
990 interp.
Interpolate(CubeSample(), CubeLine(), port.DoubleBuffer());
993 m_buf[line-1][samp-1] = Isis::NULL8;
1007 void Chip::Write(
const QString &filename) {
1012 for (
int i = 1; i <= Lines(); i++) {
1014 for (
int j = 1; j <= Samples(); j++) {
1015 line[j-1] = GetValue(j, i);
1030 void Chip::SetClipPolygon(
const geos::geom::MultiPolygon &clipPolygon) {
1031 if (m_clipPolygon != NULL)
delete m_clipPolygon;
1032 m_clipPolygon = PolygonTools::CopyMultiPolygon(clipPolygon);
1046 m_buf = other.
m_buf;
1062 if (m_clipPolygon) {
1063 delete m_clipPolygon;
1064 m_clipPolygon = NULL;
1068 m_clipPolygon = PolygonTools::MakeMultiPolygon(
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...
void SetChipPosition(const double sample, const double line)
Compute the position of the cube given a chip coordinate.
double HotSample()
Returns the sample coordinate of the center pixel in the buffer for the interpolator.
const double Null
Value for an Isis Null pixel.
double m_validMaximum
valid maximum chip pixel value
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.
const double PI
The mathematical constant PI.
double m_cubeLine
cube line set by SetCubePosition
double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
Camera * camera()
Return a camera associated with the cube.
A small chip of data used for pattern matching.
Buffer for containing a two dimensional section of an image.
Base class for Map TProjections.
double m_cubeSample
cube sample set by SetCubePosition
Interpolator::interpType m_readInterpolator
Interpolator type set by.
void append(const IException &exceptionSource)
Appends the given exception (and its list of previous exceptions) to this exception's causational exc...
int m_tackSample
Middle sample of the chip.
Namespace for the standard library.
double m_chipSample
chip sample set by SetChip/CubePosition
double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
bool IsGood() const
This indicates if the last invocation of SetGround, SetCoordinate, SetUniversalGround, or SetWorld was with successful or not.
QString toString(bool boolToConvert)
Global function to convert a boolean to a string.
Projection * projection()
double yp() const
Returns the computed y'.
void setDimensions(int ns, int nl, int nb)
Used prior to the Create method to specify the size of the cube.
Buffer manager, for moving through a cube in lines.
bool SetUniversalGround(const double latitude, const double longitude)
Sets the lat/lon values to get the sample/line values.
double m_cubeTackLine
cube line at the chip tack
double WorldX() const
This returns the world X coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
This class is used to accumulate statistics on double arrays.
double xp() const
Returns the computed x'.
double HotLine()
Returns the line coordinate of the center pixel in the buffer for the interpolator.
Base class for Map Projections.
void Compute(double x, double y)
Compute (xp,yp) given (x,y).
double m_validMinimum
valid minimum chip pixel value
int Samples()
Returns the number of samples needed by the interpolator.
#define _FILEINFO_
Macro for the filename and line number.
double Sample()
Returns the current sample number.
double m_cubeTackSample
cube sample at the chip tack
double CubeSample() const
void close(bool remove=false)
Closes the cube and updates the labels.
void read(Blob &blob) const
This method will read data from the specified Blob object.
int m_chipLines
Number of lines in the chip.
int TackSample() const
This method returns a chip's fixed tack sample; the middle of the chip.
double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
PixelType pixelType() const
double UniversalLatitude()
This returns a universal latitude (planetocentric).
QString m_filename
FileName of loaded cube.
AMatrix Forward() const
Returns the forward Affine matrix.
bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
void SetValue(int sample, int line, const double &value)
Sets a value in the chip.
Affine m_affine
Transform set by SetTransform.
int m_tackLine
Middle line of the chip.
int Lines()
Returns the number of lines needed by the interpolator.
geos::geom::MultiPolygon * m_clipPolygon
clipping polygon set by SetClipPolygon
virtual QString fileName() const
Returns the opened cube's filename.
double Line()
Returns the current line number.
void write(Blob &blob)
This method will write a blob of data (e.g.
virtual bool SetUniversalGround(const double coord1, const double coord2)
This method is used to set the lat/lon or radius/azimuth (i.e.
int m_chipSamples
Number of samples in the chip.
Namespace for ISIS/Bullet specific routines.
std::vector< std::vector< double > > m_buf
Chip buffer.
void AddData(const double *data, const unsigned int count)
Add an array of doubles to the accumulators and counters.
void create(const QString &cfile)
This method will create an isis cube for writing.
double m_chipLine
chip line set by SetChip/CubePosition
double WorldY() const
This returns the world Y coordinate provided SetGround, SetCoordinate, SetUniversalGround, or SetWorld returned with success.
int TackLine() const
This method returns a chip's fixed tack line; the middle of the chip.
bool HasSurfaceIntersection() const
Returns if the last call to either SetLookDirection or SetUniversalGround had a valid intersection wi...
IO Handler for Isis Cubes.