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