Isis 3 Programmer Reference
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.tryLock();
560  p_calculatePolygonMutex.unlock();
561  }
562  }
563 
564  // Intersect the current polygon (from the outside loop) with all others
565  // below it
566  for (int inside = outside + 1; inside < p_lonLatOverlaps.size(); ++inside) {
567  try {
568  if (p_lonLatOverlaps.at(outside)->HasAnySameSerialNumber(*p_lonLatOverlaps.at(inside)))
569  continue;
570 
571  // We know these are valid because they were filtered early on
572  const geos::geom::MultiPolygon *poly1 = p_lonLatOverlaps.at(outside)->Polygon();
573  const geos::geom::MultiPolygon *poly2 = p_lonLatOverlaps.at(inside)->Polygon();
574 
575  // Check to see if the two poygons are equivalent.
576  // If they are, then we can get rid of one of them
577  if (PolygonTools::Equal(poly1, poly2)) {
578  p_lonLatOverlapsMutex.lock();
579  AddSerialNumbers(p_lonLatOverlaps[outside], p_lonLatOverlaps[inside]);
580  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
581  p_lonLatOverlapsMutex.unlock();
582  inside --;
583  continue;
584  }
585 
586  // We can get empty polygons in our list sometimes; try to avoid extra processing
587  if (poly2->isEmpty() || poly2->getArea() < 1.0e-14) {
588  p_lonLatOverlapsMutex.lock();
589  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
590  p_lonLatOverlapsMutex.unlock();
591  inside --;
592  continue;
593  }
594 
595  geos::geom::Geometry *intersected = NULL;
596  try {
597  intersected = PolygonTools::Intersect(poly1, poly2);
598  }
599  catch (IException &e) {
600  intersected = NULL;
601  QString error = "Intersection of overlaps failed.";
602 
603  // We never want to double seed, so we must delete one or both
604  // of these polygons because they more than likely have an intersection
605  // that we simply can't calculate.
606  double outsideArea = poly1->getArea();
607  double insideArea = poly2->getArea();
608  double areaRatio = std::min(outsideArea, insideArea) /
609  std::max(outsideArea, insideArea);
610 
611  // If one of the polygons is < 1% the area of the other,
612  // then only throw out the small one to
613  // try to minimize the impact of this failure.
614  if (areaRatio < 0.1) {
615  if (poly1->getArea() > poly2->getArea()) {
616  error += " The first polygon will be removed.";
617  HandleError(e, snlist, error, inside, outside);
618  p_lonLatOverlapsMutex.lock();
619  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
620  p_lonLatOverlapsMutex.unlock();
621  inside --;
622  }
623  else {
624  error += " The second polygon will be removed.";
625  HandleError(e, snlist, error, inside, outside);
626  p_lonLatOverlapsMutex.lock();
627  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
628  p_lonLatOverlapsMutex.unlock();
629  inside = outside;
630  }
631  }
632  else {
633  error += " Both polygons will be removed to prevent the "
634  "possibility of double counted areas.";
635  HandleError(e, snlist, error, inside, outside);
636  p_lonLatOverlapsMutex.lock();
637  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
638  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
639  p_lonLatOverlapsMutex.unlock();
640  inside = outside;
641  }
642 
643  continue;
644  }
645 
646  if (intersected->isEmpty() || intersected->getArea() < 1.0e-14) {
647  delete intersected;
648  intersected = NULL;
649  continue;
650  }
651 
652  // We are only interested in overlaps that result in polygon(s)
653  // and not any that are lines or points, so create a new multipolygon
654  // with only the polygons of overlap
655  geos::geom::MultiPolygon *overlap = NULL;
656  try {
657  overlap = PolygonTools::Despike(intersected);
658 
659  delete intersected;
660  intersected = NULL;
661  }
662  catch (IException &e) {
663  if (!intersected->isValid()) {
664  delete intersected;
665  intersected = NULL;
666 
667  HandleError(e, snlist, "", inside, outside);
668  continue;
669  }
670  else {
671  overlap = PolygonTools::MakeMultiPolygon(intersected);
672 
673  delete intersected;
674  intersected = NULL;
675  }
676  }
677  catch (geos::util::GEOSException *exc) {
678  delete intersected;
679  intersected = NULL;
680  HandleError(exc, snlist, "", inside, outside);
681  continue;
682  }
683 
684  if (!overlap->isValid()) {
685  delete overlap;
686  overlap = NULL;
687  HandleError(snlist, "Intersection produced invalid overlap area", inside, outside);
688  continue;
689  }
690 
691  // is there really overlap?
692  if (overlap->isEmpty() || overlap->getArea() < 1.0e-14) {
693  delete overlap;
694  overlap = NULL;
695  continue;
696  }
697 
698  // poly1 is completely inside poly2
699  if (PolygonTools::Equal(poly1, overlap)) {
700  geos::geom::Geometry *tmpGeom = NULL;
701  try {
702  tmpGeom = PolygonTools::Difference(poly2, poly1);
703  }
704  catch (IException &e) {
705  HandleError(e, snlist, "Differencing overlap polygons failed."
706  "The first polygon will be removed.", inside, outside);
707 
708  // Delete outside polygon directly and reset outside loop
709  // - current outside is thrown out!
710  p_lonLatOverlapsMutex.lock();
711  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + outside);
712  p_lonLatOverlapsMutex.unlock();
713  inside = outside;
714  continue;
715  }
716  if (SetPolygon(tmpGeom, inside) &&
717  SetPolygon(overlap, outside, p_lonLatOverlaps[inside]))
718  foundOverlap = true;
719  }
720  // poly2 is completely inside poly1
721  else if (PolygonTools::Equal(poly2, overlap)) {
722  geos::geom::Geometry *tmpGeom = NULL;
723  try {
724  tmpGeom = PolygonTools::Difference(poly1, poly2);
725  }
726  catch (IException &e) {
727  HandleError(e, snlist, "Differencing overlap polygons failed."
728  "The second polygon will be removed.", inside, outside);
729 
730  // Delete inside polygon directly and process next inside
731  p_lonLatOverlapsMutex.lock();
732  p_lonLatOverlaps.erase(p_lonLatOverlaps.begin() + inside);
733  p_lonLatOverlapsMutex.unlock();
734  inside --;
735  continue;
736  }
737  if (SetPolygon(tmpGeom, outside) &&
738  SetPolygon(overlap, inside, p_lonLatOverlaps[outside]))
739  foundOverlap = true;
740  }
741  // There is partial overlap
742  else {
743  // Subtract overlap from poly1 and set poly1 to the result
744  geos::geom::Geometry *tmpGeom = NULL;
745  try {
746  tmpGeom = PolygonTools::Difference(poly1, overlap);
747  }
748  catch (IException &e) {
749  tmpGeom = NULL;
750  }
751 
752  // If we failed to subtract overlap, try to subtract poly2 from poly1
753  // and set poly1 to the result
754  try {
755  if (tmpGeom == NULL) {
756  tmpGeom = PolygonTools::Difference(poly1, poly2);
757  }
758  }
759  catch (IException &e) {
760  tmpGeom = NULL;
761  HandleError(e, snlist, "Differencing overlap polygons failed", inside, outside);
762  continue;
763  }
764 
765  if (!SetPolygon(tmpGeom, outside)) {
766  if (SetPolygon(Isis::globalFactory.createMultiPolygon(), outside))
767  foundOverlap = true;
768  }
769 
770  int oldSize = p_lonLatOverlaps.size();
771  if (SetPolygon(overlap, inside + 1, p_lonLatOverlaps[outside], true)) {
772  int newSize = p_lonLatOverlaps.size();
773  int newSteps = newSize - oldSize;
774  p.AddSteps(newSteps);
775  foundOverlap = true;
776  if (newSize != oldSize) inside++;
777  }
778  } // End of partial overlap else
779  }
780  // Collections are illegal as intersection argument
781  catch (IException &e) {
782  HandleError(e, snlist, "Unable to find overlap.", inside, outside);
783  }
784  // Collections are illegal as intersection argument
785  catch (geos::util::IllegalArgumentException *ill) {
786  HandleError(NULL, snlist, "Unable to find overlap", inside, outside);
787  }
788  catch (geos::util::GEOSException *exc) {
789  HandleError(exc, snlist, "Unable to find overlap", inside, outside);
790  }
791  catch (...) {
792  HandleError(snlist, "Unknown Error: Unable to find overlap", inside, outside);
793  }
794  }
795 
796  p.CheckStatus();
797  }
798 
799  p_calculatedSoFar = p_lonLatOverlaps.size();
800  delete emptyPolygon;
801 
802  // Do not write empty overlap files
803  if (foundOverlap == false) {
804  p_lonLatOverlapsMutex.lock();
805  p_lonLatOverlaps.clear();
806  p_lonLatOverlapsMutex.unlock();
807  }
808 
809  // unblock the writing process
810  // Check first if the the thread is still locked
811  // to avoid undefined behavior
812  p_calculatePolygonMutex.tryLock();
813  p_calculatePolygonMutex.unlock();
814  }
815 
816 
825  void ImageOverlapSet::AddSerialNumbers(ImageOverlap *to, ImageOverlap *from) {
826 
827  for (int i = 0; i < from->Size(); i++) {
828  QString s = (*from)[i];
829  to->Add(s);
830  }
831  }
832 
833 
840  ImageOverlap *ImageOverlapSet::CreateNewOverlap(QString serialNumber,
841  geos::geom::MultiPolygon *latLonPolygon) {
842 
843  return new ImageOverlap(serialNumber, *latLonPolygon);
844  }
845 
846 
858  std::vector<ImageOverlap *> ImageOverlapSet::operator[](QString serialNumber) {
859 
860  vector<ImageOverlap *> matches;
861 
862  // Look at all the ImageOverlaps we have and return the ones that
863  // have this sn
864  for (int ov = 0; ov < p_lonLatOverlaps.size(); ++ov) {
865  for (int sn = 0; sn < p_lonLatOverlaps[ov]->Size(); ++sn) {
866  if ((*p_lonLatOverlaps[ov])[sn] == serialNumber) {
867  matches.push_back(p_lonLatOverlaps[ov]);
868  }
869  }
870  }
871 
872  return matches;
873  }
874 
875 
886  void ImageOverlapSet::HandleError(IException &e,
887  SerialNumberList *snlist,
888  QString msg,
889  int overlap1, int overlap2) {
890 
891  PvlGroup err("ImageOverlapError");
892 
893  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
894  PvlKeyword serialNumbers("PolySerialNumbers");
895  PvlKeyword filename("FileNames");
896  PvlKeyword polygon("Polygon");
897 
898  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
899  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
900 
901  if (snlist != NULL) {
902  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
903  }
904  }
905  polygon += p_lonLatOverlaps.at(overlap1)->Polygon()->toString().c_str();
906 
907  err += serialNumbers;
908 
909  if (filename.size() != 0) {
910  err += filename;
911  }
912 
913  err += polygon;
914  }
915 
916  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
917  overlap2 < p_lonLatOverlaps.size()) {
918  PvlKeyword serialNumbers("PolySerialNumbers");
919  PvlKeyword filename("FileNames");
920  PvlKeyword polygon("Polygon");
921 
922  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
923  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
924 
925  if (snlist != NULL) {
926  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
927  }
928  }
929  polygon += p_lonLatOverlaps.at(overlap2)->Polygon()->toString().c_str();
930 
931  err += serialNumbers;
932 
933  if (filename.size() != 0) {
934  err += filename;
935  }
936 
937  err += polygon;
938  }
939 
940  err += PvlKeyword("Error", e.what());
941 
942  if (!msg.isEmpty()) {
943  err += PvlKeyword("Description", msg);
944  }
945 
946  p_errorLog.push_back(err);
947 
948  if (!p_continueAfterError) throw;
949  }
950 
951 
962  void ImageOverlapSet::HandleError(geos::util::GEOSException *exc,
963  SerialNumberList *snlist,
964  QString msg,
965  int overlap1, int overlap2) {
966 
967  PvlGroup err("ImageOverlapError");
968 
969  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
970  PvlKeyword serialNumbers("PolySerialNumbers");
971  PvlKeyword filename("FileNames");
972 
973  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
974  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
975 
976  if (snlist != NULL) {
977  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
978  }
979  }
980 
981  err += serialNumbers;
982 
983  if (filename.size() != 0) {
984  err += filename;
985  }
986  }
987 
988  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
989  overlap2 < p_lonLatOverlaps.size()) {
990  PvlKeyword serialNumbers("PolySerialNumbers");
991  PvlKeyword filename("FileNames");
992 
993  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
994  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
995 
996  if (snlist != NULL) {
997  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
998  }
999  }
1000 
1001  err += serialNumbers;
1002 
1003  if (filename.size() != 0) {
1004  err += filename;
1005  }
1006  }
1007 
1008  err += PvlKeyword("Error", exc->what());
1009 
1010  if (!msg.isEmpty()) {
1011  err += PvlKeyword("Description", msg);
1012  }
1013 
1014  p_errorLog.push_back(err);
1015 
1016  delete exc;
1017 
1018  if (!p_continueAfterError) {
1019  throw IException(IException::Programmer, err["Description"][0], _FILEINFO_);
1020  }
1021  }
1022 
1023 
1033  void ImageOverlapSet::HandleError(SerialNumberList *snlist,
1034  QString msg,
1035  int overlap1, int overlap2) {
1036 
1037  PvlGroup err("ImageOverlapError");
1038 
1039  if (overlap1 >= 0 && overlap1 < p_lonLatOverlaps.size()) {
1040  PvlKeyword serialNumbers("PolySerialNumbers");
1041  PvlKeyword filename("FileNames");
1042 
1043  for (int i = 0; i < p_lonLatOverlaps.at(overlap1)->Size(); i++) {
1044  serialNumbers += (*p_lonLatOverlaps.at(overlap1))[i];
1045 
1046  if (snlist != NULL) {
1047  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap1))[i]);
1048  }
1049  }
1050 
1051  err += serialNumbers;
1052 
1053  if (filename.size() != 0) {
1054  err += filename;
1055  }
1056  }
1057 
1058  if (overlap2 >= 0 && overlap1 < p_lonLatOverlaps.size() &&
1059  overlap2 < p_lonLatOverlaps.size()) {
1060  PvlKeyword serialNumbers("PolySerialNumbers");
1061  PvlKeyword filename("FileNames");
1062 
1063  for (int i = 0; i < p_lonLatOverlaps.at(overlap2)->Size(); i++) {
1064  serialNumbers += (*p_lonLatOverlaps.at(overlap2))[i];
1065 
1066  if (snlist != NULL) {
1067  filename += snlist->fileName((*p_lonLatOverlaps.at(overlap2))[i]);
1068  }
1069  }
1070 
1071  err += serialNumbers;
1072 
1073  if (filename.size() != 0) {
1074  err += filename;
1075  }
1076  }
1077 
1078  err += PvlKeyword("Description", msg);
1079 
1080  p_errorLog.push_back(err);
1081 
1082  if (!p_continueAfterError) {
1083  throw IException(IException::Programmer, err["Description"][0], _FILEINFO_);
1084  }
1085  }
1086 
1087 
1093  void ImageOverlapSet::DespikeLonLatOverlaps() {
1094 
1095  for (int i = 0; i < Size(); i++) {
1096  try {
1097  p_lonLatOverlaps[i]->SetPolygon(PolygonTools::Despike(p_lonLatOverlaps[i]->Polygon()));
1098  }
1099  catch (IException &e) {
1100  }
1101  }
1102  }
1103 }
const char * what() const
Returns a string representation of this exception in its current state.
Definition: IException.cpp:391
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:116
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...
Namespace for the standard library.
virtual void SetPolygon(const geos::geom::MultiPolygon &polygon)
This method will replace the existing polygon that defines the overlap with a new one...
Create cube polygons, read/write polygons to blobs.
Definition: ImagePolygon.h:167
void CheckStatus()
Checks and updates the status.
Definition: Progress.cpp:121
QString fileName(const QString &sn)
Return a filename given a serial number.
Program progress reporter.
Definition: Progress.h:58
int size() const
Returns the number of values stored in this keyword.
Definition: PvlKeyword.h:141
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:40
A single keyword-value pair.
Definition: PvlKeyword.h:98
void close(bool remove=false)
Closes the cube and updates the labels.
Definition: Cube.cpp:177
void read(Blob &blob) const
This method will read data from the specified Blob object.
Definition: Cube.cpp:724
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition: FileName.cpp:212
void open(const QString &cfile, QString access="r")
This method will open an isis cube for reading or reading/writing.
Definition: Cube.cpp:544
int size() const
How many serial number / filename combos are in the list.
Isis exception class.
Definition: IException.h:107
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
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:170