Isis 3.0 Programmer Reference
Back | Home
ImageOverlapSet.cpp
1 #include <cmath>
2 #include <iomanip>
3 #include <iostream>
4 #include <sstream>
5 #include <string>
6 #include <vector>
7 
8 #include "Cube.h"
9 #include "FileName.h"
10 #include "geos/operation/distance/DistanceOp.h"
11 #include "geos/util/IllegalArgumentException.h"
12 #include "geos/geom/Point.h"
13 #include "geos/opOverlay.h"
14 #include "IException.h"
15 #include "ImageOverlapSet.h"
16 #include "ImagePolygon.h"
17 #include "PolygonTools.h"
18 #include "Progress.h"
19 #include "SerialNumberList.h"
20 
21 #include "QMessageBox"
22 
23 using namespace std;
24 
25 namespace Isis {
26 
36  ImageOverlapSet::ImageOverlapSet(bool continueOnError) {
37 
38  p_continueAfterError = continueOnError;
39  p_writtenSoFar = 0;
40  p_calculatedSoFar = -1;
41  p_threadedCalculate = false;
42  p_snlist = NULL;
43  }
44 
45 
52  ImageOverlapSet::~ImageOverlapSet() {
53 
54  for (int i = 0; i < Size(); i++) {
55  if (p_lonLatOverlaps[i]) delete p_lonLatOverlaps[i];
56  }
57 
58  // This class should not retain ownership of p_snlist,
59  // so this member should not need destroyed.
60  };
61 
62 
71  void ImageOverlapSet::FindImageOverlaps(SerialNumberList &sns) {
72 
73  // Create an ImageOverlap for each image boundary
74  for (int i = 0; i < sns.size(); i++) {
75  // Open the cube
76  Cube cube;
77  try {
78  cube.open(sns.fileName(i));
79  }
80  catch (IException &error) {
81  QString msg = "Unable to open cube for serial number [";
82  msg += sns.serialNumber(i) + "] filename [" + sns.fileName(i) + "]";
83 
84  HandleError(error, &sns, msg);
85  }
86 
87  // Read the bounding polygon
88  ImagePolygon *poly = new ImagePolygon();
89  cube.read(*poly);
90  cube.close();
91  // Create an ImageOverlap with the serial number and the bounding
92  // polygon and save it
93  geos::geom::MultiPolygon *tmp = PolygonTools::MakeMultiPolygon(poly->Polys());
94 
95  delete poly;
96  poly = NULL;
97 
98  geos::geom::MultiPolygon *mp = NULL;
99 
100  // If footprint is invalid throw exception
101  if(!tmp->isValid()) {
102  delete tmp;
103  tmp = NULL;
104  QString msg = "The image [" + sns.fileName(sns.serialNumber(i)) +
105  "] has an invalid footprint";
106  throw IException(IException::Programmer, msg, _FILEINFO_);
107  }
108 
109  try {
110  mp = PolygonTools::Despike(tmp);
111  }
112  catch (IException &e) {
113  if (tmp->isValid()) {
114  mp = tmp;
115  tmp = NULL;
116  }
117  else {
118  delete tmp;
119  tmp = NULL;
120  HandleError(e, &sns);
121  continue;
122  }
123  }
124 
125  p_lonLatOverlapsMutex.lock();
126  p_lonLatOverlaps.push_back(CreateNewOverlap(sns.serialNumber(i), mp));
127  p_lonLatOverlapsMutex.unlock();
128 
129  if (mp) {
130  delete mp;
131  mp = NULL;
132  }
133 
134  if (tmp) {
135  delete tmp;
136  tmp = NULL;
137  }
138  }
139 
140  // Despikes the polygons from the Serial Numbers prior to overlap
141  // determination
142  DespikeLonLatOverlaps();
143 
144  if (p_threadedCalculate) {
145  // Call FindAllOverlaps in other thread
146  start();
147  }
148  else {
149  // Determine the overlap between each boundary polygon
150  FindAllOverlaps(&sns);
151  }
152 
153  }
154 
155 
170  void ImageOverlapSet::FindImageOverlaps(SerialNumberList &boundaries, QString outputFile) {
171 
172  // Do a common sense programmer check, this should be empty before we start
173  if (!p_lonLatOverlaps.empty()) {
174  string msg = "FindImageOverlaps(SerialNumberList&,QString) may not be called on " \
175  "an ImageOverlapSet which already contains overlaps.";
176  throw IException(IException::Programmer, msg, _FILEINFO_);
177  }
178 
179  p_writtenSoFar = 0;
180  p_calculatedSoFar = -1;
181 
182  p_snlist = &boundaries;
183 
184  // This will enable using mutexes and spawning threads where necessary.
185  p_threadedCalculate = true;
186 
187  FindImageOverlaps(boundaries);
188 
189  // While our exit condition is not true, call WriteImageOverlaps with the filename.
190  // The WriteImageOverlaps call will block if it is waiting on calculations.
191  while (p_calculatedSoFar != p_lonLatOverlaps.size()) {
192  WriteImageOverlaps(outputFile);
193  }
194 
195  // flush the output if we're still not done writing
196  if (p_calculatedSoFar != p_writtenSoFar)
197  WriteImageOverlaps(outputFile);
198 
199  // Wait for the calculation thread to actually exit,
200  // this has more than likely already occurred.
201  wait();
202 
203  // re-initialize object to original state
204  p_lonLatOverlaps.clear();
205  p_writtenSoFar = 0;
206  p_calculatedSoFar = -1;
207  p_threadedCalculate = false;
208  p_snlist = NULL;
209  }
210 
211 
300  void ImageOverlapSet::FindImageOverlaps(std::vector<QString> sns,
301  std::vector<geos::geom::MultiPolygon *> polygons) {
302 
303  if (sns.size() != polygons.size()) {
304  string message = "Invalid argument sizes. Sizes must match.";
305  throw IException(IException::Programmer, message, _FILEINFO_);
306  }
307 
308  // Create one ImageOverlap for each image sn
309  for (unsigned int i = 0; i < sns.size(); ++i) {
310  p_lonLatOverlapsMutex.lock();
311  p_lonLatOverlaps.push_back(CreateNewOverlap(sns[i], polygons[i]));
312  p_lonLatOverlapsMutex.unlock();
313  }
314 
315  // Despikes the polygons from the Serial Numbers prior to overlap determination
316  DespikeLonLatOverlaps();
317 
318  // Determine the overlap between each boundary polygon
319  FindAllOverlaps();
320  }
321 
322 
328  void ImageOverlapSet::ReadImageOverlaps(const QString &filename) {
329 
330  QString file = FileName(filename).expanded();
331 
332  try {
333  // Let's get an istream pointed at our file
334  std::ifstream inStream;
335  QByteArray fileArray = file.toLatin1();
336  inStream.open(fileArray.constData(), fstream::in | fstream::binary);
337 
338  while (!inStream.eof()) {
339  p_lonLatOverlapsMutex.lock();
340  p_lonLatOverlaps.push_back(new ImageOverlap(inStream));
341  p_lonLatOverlapsMutex.unlock();
342  }
343 
344  inStream.close();
345  }
346  catch (IException &e) {
347  p_lonLatOverlapsMutex.unlock();
348  QString msg = "The overlap file [" + filename + "] does not contain a "
349  "valid list of image overlaps";
350  throw IException(e, IException::Unknown, msg, _FILEINFO_);
351  }
352  catch (...) {
353  p_lonLatOverlapsMutex.unlock();
354  QString msg = "The overlap file [" + filename + "] does not contain a "
355  "valid list of image overlaps";
356  throw IException(IException::Unknown, msg, _FILEINFO_);
357  }
358  }
359 
360 
378  bool ImageOverlapSet::SetPolygon(geos::geom::Geometry *poly,
379  int position,
380  ImageOverlap *sncopy,
381  bool insert) {
382 
383  bool success = false;
384  geos::geom::MultiPolygon *multiPolygon = PolygonTools::MakeMultiPolygon(poly);
385  delete poly;
386  poly = NULL;
387 
388  if (!multiPolygon->isValid() ||
389  (multiPolygon->getArea() < 1.0e-10 && !multiPolygon->isEmpty())) {
390  delete multiPolygon;
391  multiPolygon = Isis::globalFactory.createMultiPolygon();
392  }
393 
394  if (position > p_lonLatOverlaps.size()) {
395  position = p_lonLatOverlaps.size();
396  }
397 
398  try {
399  if (!multiPolygon->isEmpty()) {
400  geos::geom::MultiPolygon *despiked = PolygonTools::Despike(multiPolygon);
401  delete multiPolygon;
402  multiPolygon = despiked;
403  }
404  }
405  catch (IException &) {
406  }
407 
408  if (multiPolygon->isValid() &&
409  (multiPolygon->isEmpty() || multiPolygon->getArea() > 1.0e-14)) {
410  if (!insert) {
411  p_lonLatOverlaps.at(position)->SetPolygon(multiPolygon);
412 
413  if (sncopy) {
414  AddSerialNumbers(p_lonLatOverlaps.at(position), sncopy);
415  }
416  }
417  else if (!multiPolygon->isEmpty()) {
418  ImageOverlap *imageOverlap = new ImageOverlap();
419  imageOverlap->SetPolygon(multiPolygon);
420  delete multiPolygon;
421  multiPolygon = NULL;
422 
423  if (sncopy) {
424  AddSerialNumbers(imageOverlap, sncopy);
425  }
426 
427  // Insert could cause a reallocation of the overlap list, so lock it with
428  // the writing code so that we don't conflict
429  p_lonLatOverlapsMutex.lock();
430  p_lonLatOverlaps.insert(p_lonLatOverlaps.begin() + position, imageOverlap);
431  p_lonLatOverlapsMutex.unlock();
432  }
433 
434  success = true;
435  }
436 
437  return success;
438  }
439 
440 
446  void ImageOverlapSet::WriteImageOverlaps(const QString &filename) {
447 
448  QString file = FileName(filename).expanded();
449  bool failed = false;
450  bool noOverlaps = false;
451 
452  if (p_threadedCalculate) {
453  p_calculatePolygonMutex.lock();
454  }
455 
456  try {
457  // Let's get an ostream pointed at our file
458  std::ofstream outStream;
459 
460  QByteArray fileArray = file.toLatin1();
461  if (p_writtenSoFar == 0) {
462  outStream.open(fileArray.constData(), fstream::out | fstream::trunc | fstream::binary);
463  }
464  else {
465  outStream.open(fileArray.constData(), fstream::out | fstream::app | fstream::binary);
466  }
467 
468  failed |= outStream.fail();
469 
470  static bool overlapWritten = false;
471  for (int overlap = p_writtenSoFar; !failed && overlap <= p_calculatedSoFar; overlap++) {
472  // Let's not try anything during a possible reallocate
473  p_lonLatOverlapsMutex.lock();
474 
475  if (p_lonLatOverlaps.size() == 0) {
476  noOverlaps = true;
477  }
478  else {
479  if (overlap < p_lonLatOverlaps.size() && p_lonLatOverlaps[overlap]) {
480 
481  if (!p_lonLatOverlaps[overlap]->Polygon()->isEmpty()) {
482 
483  if (overlapWritten) {
484  outStream << std::endl;
485  }
486 
487  p_lonLatOverlaps[overlap]->Write(outStream);
488  overlapWritten = true;
489  }
490 
491  delete p_lonLatOverlaps[overlap];
492  p_lonLatOverlaps[overlap] = NULL;
493  p_writtenSoFar ++;
494  }
495  }
496  p_lonLatOverlapsMutex.unlock();
497  }
498 
499  failed |= outStream.fail();
500  outStream.close();
501 
502  failed |= outStream.fail();
503  }
504  catch (...) {
505  failed = true;
506  }
507 
512  if (p_calculatedSoFar == p_lonLatOverlaps.size()) {
513  if (p_threadedCalculate && !noOverlaps) {
514  p_calculatePolygonMutex.tryLock();
515  p_calculatePolygonMutex.unlock();
516  }
517  }
518 
519  if (failed) {
520  p_calculatePolygonMutex.tryLock();
521  p_calculatePolygonMutex.unlock();
522  QString msg = "Unable to write the image overlap list to [" + filename + "]";
523  throw IException(IException::Io, msg, _FILEINFO_);
524  }
525  else if (noOverlaps) {
526  p_calculatePolygonMutex.tryLock();
527  p_calculatePolygonMutex.unlock();
528  QString msg = "No overlaps were found.";
529  throw IException(IException::User, msg, _FILEINFO_);
530  }
531  }
532 
533 
540  void ImageOverlapSet::FindAllOverlaps(SerialNumberList *snlist) {
541 
542  bool foundOverlap = false;
543  if (p_lonLatOverlaps.size() <= 1) return;
544 
545  Progress p;
546  p.SetText("Calculating Image Overlaps");
547  p.SetMaximumSteps(p_lonLatOverlaps.size() - 1);
548  p.CheckStatus();
549 
550  geos::geom::MultiPolygon *emptyPolygon = Isis::globalFactory.createMultiPolygon();
551 
552  // Compare each polygon with all of the others
553  for (int outside = 0; outside < p_lonLatOverlaps.size() - 1; ++outside) {
554  p_calculatedSoFar = outside - 1;
555 
556  // unblock the writing process after every 10 polygons if we need to write
557  if (p_calculatedSoFar % 10 == 0 && (!snlist || (p_lonLatOverlaps.size() > snlist->size()))) {
558  if (p_threadedCalculate) {
559  p_calculatePolygonMutex.unlock();
560  }
561  }
562 
563  // Intersect the current polygon (from the outside loop) with all others
564  // below it
565  for (int inside = outside + 1; inside < p_lonLatOverlaps.size(); ++inside) {
566  try {
567  if (p_lonLatOverlaps.at(outside)->HasAnySameSerialNumber(*p_lonLatOverlaps.at(inside)))
568  continue;
569 
570  // We know these are valid because they were filtered early on
571  const geos::geom::MultiPolygon *poly1 = p_lonLatOverlaps.at(outside)->Polygon();
572  const geos::geom::MultiPolygon *poly2 = p_lonLatOverlaps.at(inside)->Polygon();
573 
574  // Check to see if the two poygons are equivalent.
575  // If they are, then we can get rid of one of them
576  if (PolygonTools::Equal(poly1, poly2)) {
577  p_lonLatOverlapsMutex.lock();
578  AddSerialNumbers(p_lonLatOverlaps[outside], p_lonLatOverlaps[inside]);
579  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
580  p_lonLatOverlapsMutex.unlock();
581  inside --;
582  continue;
583  }
584 
585  // We can get empty polygons in our list sometimes; try to avoid extra processing
586  if (poly2->isEmpty() || poly2->getArea() < 1.0e-14) {
587  p_lonLatOverlapsMutex.lock();
588  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
589  p_lonLatOverlapsMutex.unlock();
590  inside --;
591  continue;
592  }
593 
594  geos::geom::Geometry *intersected = NULL;
595  try {
596  intersected = PolygonTools::Intersect(poly1, poly2);
597  }
598  catch (IException &e) {
599  intersected = NULL;
600  QString error = "Intersection of overlaps failed.";
601 
602  // We never want to double seed, so we must delete one or both
603  // of these polygons because they more than likely have an intersection
604  // that we simply can't calculate.
605  double outsideArea = poly1->getArea();
606  double insideArea = poly2->getArea();
607  double areaRatio = std::min(outsideArea, insideArea) /
608  std::max(outsideArea, insideArea);
609 
610  // If one of the polygons is < 1% the area of the other,
611  // then only throw out the small one to
612  // try to minimize the impact of this failure.
613  if (areaRatio < 0.1) {
614  if (poly1->getArea() > poly2->getArea()) {
615  error += " The first polygon will be removed.";
616  HandleError(e, snlist, error, inside, outside);
617  p_lonLatOverlapsMutex.lock();
618  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
619  p_lonLatOverlapsMutex.unlock();
620  inside --;
621  }
622  else {
623  error += " The second polygon will be removed.";
624  HandleError(e, snlist, error, inside, outside);
625  p_lonLatOverlapsMutex.lock();
626  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
627  p_lonLatOverlapsMutex.unlock();
628  inside = outside;
629  }
630  }
631  else {
632  error += " Both polygons will be removed to prevent the "
633  "possibility of double counted areas.";
634  HandleError(e, snlist, error, inside, outside);
635  p_lonLatOverlapsMutex.lock();
636  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
637  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
638  p_lonLatOverlapsMutex.unlock();
639  inside = outside;
640  }
641 
642  continue;
643  }
644 
645  if (intersected->isEmpty() || intersected->getArea() < 1.0e-14) {
646  delete intersected;
647  intersected = NULL;
648  continue;
649  }
650 
651  // We are only interested in overlaps that result in polygon(s)
652  // and not any that are lines or points, so create a new multipolygon
653  // with only the polygons of overlap
654  geos::geom::MultiPolygon *overlap = NULL;
655  try {
656  overlap = PolygonTools::Despike(intersected);
657 
658  delete intersected;
659  intersected = NULL;
660  }
661  catch (IException &e) {
662  if (!intersected->isValid()) {
663  delete intersected;
664  intersected = NULL;
665 
666  HandleError(e, snlist, "", inside, outside);
667  continue;
668  }
669  else {
670  overlap = PolygonTools::MakeMultiPolygon(intersected);
671 
672  delete intersected;
673  intersected = NULL;
674  }
675  }
676  catch (geos::util::GEOSException *exc) {
677  delete intersected;
678  intersected = NULL;
679  HandleError(exc, snlist, "", inside, outside);
680  continue;
681  }
682 
683  if (!overlap->isValid()) {
684  delete overlap;
685  overlap = NULL;
686  HandleError(snlist, "Intersection produced invalid overlap area", inside, outside);
687  continue;
688  }
689 
690  // is there really overlap?
691  if (overlap->isEmpty() || overlap->getArea() < 1.0e-14) {
692  delete overlap;
693  overlap = NULL;
694  continue;
695  }
696 
697  // poly1 is completely inside poly2
698  if (PolygonTools::Equal(poly1, overlap)) {
699  geos::geom::Geometry *tmpGeom = NULL;
700  try {
701  tmpGeom = PolygonTools::Difference(poly2, poly1);
702  }
703  catch (IException &e) {
704  HandleError(e, snlist, "Differencing overlap polygons failed."
705  "The first polygon will be removed.", inside, outside);
706 
707  // Delete outside polygon directly and reset outside loop
708  // - current outside is thrown out!
709  p_lonLatOverlapsMutex.lock();
710  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
711  p_lonLatOverlapsMutex.unlock();
712  inside = outside;
713  continue;
714  }
715  if (SetPolygon(tmpGeom, inside) &&
716  SetPolygon(overlap, outside, p_lonLatOverlaps[inside]))
717  foundOverlap = true;
718  }
719  // poly2 is completely inside poly1
720  else if (PolygonTools::Equal(poly2, overlap)) {
721  geos::geom::Geometry *tmpGeom = NULL;
722  try {
723  tmpGeom = PolygonTools::Difference(poly1, poly2);
724  }
725  catch (IException &e) {
726  HandleError(e, snlist, "Differencing overlap polygons failed."
727  "The second polygon will be removed.", inside, outside);
728 
729  // Delete inside polygon directly and process next inside
730  p_lonLatOverlapsMutex.lock();
731  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
732  p_lonLatOverlapsMutex.unlock();
733  inside --;
734  continue;
735  }
736  if (SetPolygon(tmpGeom, outside) &&
737  SetPolygon(overlap, inside, p_lonLatOverlaps[outside]))
738  foundOverlap = true;
739  }
740  // There is partial overlap
741  else {
742  // Subtract overlap from poly1 and set poly1 to the result
743  geos::geom::Geometry *tmpGeom = NULL;
744  try {
745  tmpGeom = PolygonTools::Difference(poly1, overlap);
746  }
747  catch (IException &e) {
748  tmpGeom = NULL;
749  }
750 
751  // If we failed to subtract overlap, try to subtract poly2 from poly1
752  // and set poly1 to the result
753  try {
754  if (tmpGeom == NULL) {
755  tmpGeom = PolygonTools::Difference(poly1, poly2);
756  }
757  }
758  catch (IException &e) {
759  tmpGeom = NULL;
760  HandleError(e, snlist, "Differencing overlap polygons failed", inside, outside);
761  continue;
762  }
763 
764  if (!SetPolygon(tmpGeom, outside)) {
765  if (SetPolygon(Isis::globalFactory.createMultiPolygon(), outside))
766  foundOverlap = true;
767  }
768 
769  int oldSize = p_lonLatOverlaps.size();
770  if (SetPolygon(overlap, inside + 1, p_lonLatOverlaps[outside], true)) {
771  int newSize = p_lonLatOverlaps.size();
772  int newSteps = newSize - oldSize;
773  p.AddSteps(newSteps);
774  foundOverlap = true;
775  if (newSize != oldSize) inside++;
776  }
777  } // End of partial overlap else
778  }
779  // Collections are illegal as intersection argument
780  catch (IException &e) {
781  HandleError(e, snlist, "Unable to find overlap.", inside, outside);
782  }
783  // Collections are illegal as intersection argument
784  catch (geos::util::IllegalArgumentException *ill) {
785  HandleError(NULL, snlist, "Unable to find overlap", inside, outside);
786  }
787  catch (geos::util::GEOSException *exc) {
788  HandleError(exc, snlist, "Unable to find overlap", inside, outside);
789  }
790  catch (...) {
791  HandleError(snlist, "Unknown Error: Unable to find overlap", inside, outside);
792  }
793  }
794 
795  p.CheckStatus();
796  }
797 
798  p_calculatedSoFar = p_lonLatOverlaps.size();
799  delete emptyPolygon;
800 
801  // Do not write empty overlap files
802  if (foundOverlap == false) {
803  p_lonLatOverlapsMutex.lock();
804  p_lonLatOverlaps.clear();
805  p_lonLatOverlapsMutex.unlock();
806  }
807 
808  // unblock the writing process
809  // Check first if the the thread is still locked
810  // to avoid undefined behavior
811  p_calculatePolygonMutex.tryLock();
812  p_calculatePolygonMutex.unlock();
813  }
814 
815 
824  void ImageOverlapSet::AddSerialNumbers(ImageOverlap *to, ImageOverlap *from) {
825 
826  for (int i = 0; i < from->Size(); i++) {
827  QString s = (*from)[i];
828  to->Add(s);
829  }
830  }
831 
832 
839  ImageOverlap *ImageOverlapSet::CreateNewOverlap(QString serialNumber,
840  geos::geom::MultiPolygon *latLonPolygon) {
841 
842  return new ImageOverlap(serialNumber, *latLonPolygon);
843  }
844 
845 
857  std::vector<ImageOverlap *> ImageOverlapSet::operator[](QString serialNumber) {
858 
859  vector<ImageOverlap *> matches;
860 
861  // Look at all the ImageOverlaps we have and return the ones that
862  // have this sn
863  for (int ov = 0; ov < p_lonLatOverlaps.size(); ++ov) {
864  for (int sn = 0; sn < p_lonLatOverlaps[ov]->Size(); ++sn) {
865  if ((*p_lonLatOverlaps[ov])[sn] == serialNumber) {
866  matches.push_back(p_lonLatOverlaps[ov]);
867  }
868  }
869  }
870 
871  return matches;
872  }
873 
874 
885  void ImageOverlapSet::HandleError(IException &e,
886  SerialNumberList *snlist,
887  QString msg,
888  int overlap1, int overlap2) {
889 
890  PvlGroup err("ImageOverlapError");
891 
892  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
893  PvlKeyword serialNumbers("PolySerialNumbers");
894  PvlKeyword filename("FileNames");
895  PvlKeyword polygon("Polygon");
896 
897  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
898  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
899 
900  if (snlist != NULL) {
901  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
902  }
903  }
904  polygon += p_lonLatOverlaps.at(overlap1)->Polygon()->toString().c_str();
905 
906  err += serialNumbers;
907 
908  if (filename.size() != 0) {
909  err += filename;
910  }
911 
912  err += polygon;
913  }
914 
915  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
916  overlap2 < p_lonLatOverlaps.size()) {
917  PvlKeyword serialNumbers("PolySerialNumbers");
918  PvlKeyword filename("FileNames");
919  PvlKeyword polygon("Polygon");
920 
921  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
922  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
923 
924  if (snlist != NULL) {
925  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
926  }
927  }
928  polygon += p_lonLatOverlaps.at(overlap2)->Polygon()->toString().c_str();
929 
930  err += serialNumbers;
931 
932  if (filename.size() != 0) {
933  err += filename;
934  }
935 
936  err += polygon;
937  }
938 
939  err += PvlKeyword("Error", e.what());
940 
941  if (!msg.isEmpty()) {
942  err += PvlKeyword("Description", msg);
943  }
944 
945  p_errorLog.push_back(err);
946 
947  if (!p_continueAfterError) throw;
948  }
949 
950 
961  void ImageOverlapSet::HandleError(geos::util::GEOSException *exc,
962  SerialNumberList *snlist,
963  QString msg,
964  int overlap1, int overlap2) {
965 
966  PvlGroup err("ImageOverlapError");
967 
968  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
969  PvlKeyword serialNumbers("PolySerialNumbers");
970  PvlKeyword filename("FileNames");
971 
972  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
973  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
974 
975  if (snlist != NULL) {
976  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
977  }
978  }
979 
980  err += serialNumbers;
981 
982  if (filename.size() != 0) {
983  err += filename;
984  }
985  }
986 
987  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
988  overlap2 < p_lonLatOverlaps.size()) {
989  PvlKeyword serialNumbers("PolySerialNumbers");
990  PvlKeyword filename("FileNames");
991 
992  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
993  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
994 
995  if (snlist != NULL) {
996  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
997  }
998  }
999 
1000  err += serialNumbers;
1001 
1002  if (filename.size() != 0) {
1003  err += filename;
1004  }
1005  }
1006 
1007  err += PvlKeyword("Error", exc->what());
1008 
1009  if (!msg.isEmpty()) {
1010  err += PvlKeyword("Description", msg);
1011  }
1012 
1013  p_errorLog.push_back(err);
1014 
1015  delete exc;
1016 
1017  if (!p_continueAfterError) {
1018  throw IException(IException::Programmer, err["Description"][0], _FILEINFO_);
1019  }
1020  }
1021 
1022 
1032  void ImageOverlapSet::HandleError(SerialNumberList *snlist,
1033  QString msg,
1034  int overlap1, int overlap2) {
1035 
1036  PvlGroup err("ImageOverlapError");
1037 
1038  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
1039  PvlKeyword serialNumbers("PolySerialNumbers");
1040  PvlKeyword filename("FileNames");
1041 
1042  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
1043  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
1044 
1045  if (snlist != NULL) {
1046  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
1047  }
1048  }
1049 
1050  err += serialNumbers;
1051 
1052  if (filename.size() != 0) {
1053  err += filename;
1054  }
1055  }
1056 
1057  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
1058  overlap2 < p_lonLatOverlaps.size()) {
1059  PvlKeyword serialNumbers("PolySerialNumbers");
1060  PvlKeyword filename("FileNames");
1061 
1062  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
1063  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
1064 
1065  if (snlist != NULL) {
1066  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
1067  }
1068  }
1069 
1070  err += serialNumbers;
1071 
1072  if (filename.size() != 0) {
1073  err += filename;
1074  }
1075  }
1076 
1077  err += PvlKeyword("Description", msg);
1078 
1079  p_errorLog.push_back(err);
1080 
1081  if (!p_continueAfterError) {
1082  throw IException(IException::Programmer, err["Description"][0], _FILEINFO_);
1083  }
1084  }
1085 
1086 
1092  void ImageOverlapSet::DespikeLonLatOverlaps() {
1093 
1094  for (int i = 0; i < Size(); i++) {
1095  try {
1096  p_lonLatOverlaps[i]->SetPolygon(PolygonTools::Despike(p_lonLatOverlaps[i]->Polygon()));
1097  }
1098  catch (IException &e) {
1099  }
1100  }
1101  }
1102 }
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:141
void SetMaximumSteps(const int steps)
This sets the maximum number of steps in the process.
Definition: Progress.cpp:101
File name manipulation and expansion.
Definition: FileName.h:111
int size() const
How many serial number / filename combos are in the list.
QString serialNumber(const QString &filename)
Return a serial number given a filename.
void Add(QString &sn)
This method will add a new serial number to the list of serial numbers alread associated with the ove...
virtual void SetPolygon(const geos::geom::MultiPolygon &polygon)
This method will replace the existing polygon that defines the overlap with a new one...
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:686
Create cube polygons, read/write polygons to blobs.
Definition: ImagePolygon.h:167
void CheckStatus()
Checks and updates the status.
Definition: Progress.cpp:121
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
QString fileName(const QString &sn)
Return a filename given a serial number.
Program progress reporter.
Definition: Progress.h:58
void AddSteps(const int steps)
If the initial step size was a guess, it can be modified using this method.
Definition: Progress.cpp:215
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition: Progress.cpp:77
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:38
A single keyword-value pair.
Definition: PvlKeyword.h:98
void close(bool remove=false)
Closes the cube and updates the labels.
Definition: Cube.cpp:175
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:509
Isis exception class.
Definition: IException.h:99
Individual overlap container.
Definition: ImageOverlap.h:56
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
Definition: ImagePolygon.h:221
Serial Number list generator.
IO Handler for Isis Cubes.
Definition: Cube.h:158

U.S. Department of the Interior | U.S. Geological Survey
ISIS | Privacy & Disclaimers | Astrogeology Research Program
To contact us, please post comments and questions on the ISIS Support Center
File Modified: 07/12/2023 23:20:13