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 "geos/operation/overlay/snap/SnapOverlayOp.h"
21
22#include "IException.h"
23#include "ImageOverlapSet.h"
24#include "ImagePolygon.h"
25#include "PolygonTools.h"
26#include "Progress.h"
27#include "SerialNumberList.h"
28
29#include "QMessageBox"
30
31using namespace std;
32
33namespace Isis {
34
44 ImageOverlapSet::ImageOverlapSet(bool continueOnError, bool useThread) {
45
46 p_continueAfterError = continueOnError;
49 p_threadedCalculate = useThread;
50 p_snlist = NULL;
51 }
52
53
61
62 for (int i = 0; i < Size(); i++) {
63 if (p_lonLatOverlaps[i]) delete p_lonLatOverlaps[i];
64 }
65
66 // This class should not retain ownership of p_snlist,
67 // so this member should not need destroyed.
68 };
69
70
80
81 // Create an ImageOverlap for each image boundary
82 for (int i = 0; i < sns.size(); i++) {
83 // Open the cube
84 Cube cube;
85 try {
86 cube.open(sns.fileName(i));
87 }
88 catch (IException &error) {
89 QString msg = "Unable to open cube for serial number [";
90 msg += sns.serialNumber(i) + "] filename [" + sns.fileName(i) + "]";
91
92 HandleError(error, &sns, msg);
93 }
94
95 // Read the bounding polygon
96 ImagePolygon poly = cube.readFootprint();
97 cube.close();
98 // Create an ImageOverlap with the serial number and the bounding
99 // polygon and save it
100 geos::geom::MultiPolygon *tmp = PolygonTools::MakeMultiPolygon(poly.Polys());
101
102 geos::geom::MultiPolygon *mp = NULL;
103
104 // If footprint is invalid throw exception
105 if(!tmp->isValid()) {
106 delete tmp;
107 tmp = NULL;
108 QString msg = "The image [" + sns.fileName(sns.serialNumber(i)) +
109 "] has an invalid footprint";
110 throw IException(IException::Programmer, msg, _FILEINFO_);
111 }
112
113 try {
114 mp = PolygonTools::Despike(tmp);
115 }
116 catch (IException &e) {
117 if (tmp->isValid()) {
118 mp = tmp;
119 tmp = NULL;
120 }
121 else {
122 delete tmp;
123 tmp = NULL;
124 HandleError(e, &sns);
125 continue;
126 }
127 }
128
129 p_lonLatOverlapsMutex.lock();
130 p_lonLatOverlaps.push_back(CreateNewOverlap(sns.serialNumber(i), mp));
131 p_lonLatOverlapsMutex.unlock();
132
133 if (mp) {
134 delete mp;
135 mp = NULL;
136 }
137
138 if (tmp) {
139 delete tmp;
140 tmp = NULL;
141 }
142 }
143
144 // Despikes the polygons from the Serial Numbers prior to overlap
145 // determination
147
149 // Call FindAllOverlaps in other thread
150 start();
151 }
152 else {
153 // Determine the overlap between each boundary polygon
154 FindAllOverlaps(&sns);
155 }
156
157 }
158
159
174 void ImageOverlapSet::FindImageOverlaps(SerialNumberList &boundaries, QString outputFile) {
175
176 // Do a common sense programmer check, this should be empty before we start
177 if (!p_lonLatOverlaps.empty()) {
178 string msg = "FindImageOverlaps(SerialNumberList&,QString) may not be called on " \
179 "an ImageOverlapSet which already contains overlaps.";
180 throw IException(IException::Programmer, msg, _FILEINFO_);
181 }
182
183 p_writtenSoFar = 0;
185
186 p_snlist = &boundaries;
187
188 FindImageOverlaps(boundaries);
189
190 // While our exit condition is not true, call WriteImageOverlaps with the filename.
191 // The WriteImageOverlaps call will block if it is waiting on calculations.
192 while (p_calculatedSoFar != p_lonLatOverlaps.size()) {
193 WriteImageOverlaps(outputFile);
194 }
195
196 // flush the output if we're still not done writing
198 WriteImageOverlaps(outputFile);
199
200 // Wait for the calculation thread to actually exit,
201 // this has more than likely already occurred.
202 wait();
203
204 // re-initialize object to original state
205 p_lonLatOverlaps.clear();
206 p_writtenSoFar = 0;
208 p_threadedCalculate = false;
209 p_snlist = NULL;
210 }
211
212
301 void ImageOverlapSet::FindImageOverlaps(std::vector<QString> sns,
302 std::vector<geos::geom::MultiPolygon *> polygons) {
303
304 if (sns.size() != polygons.size()) {
305 string message = "Invalid argument sizes. Sizes must match.";
306 throw IException(IException::Programmer, message, _FILEINFO_);
307 }
308
309 // Create one ImageOverlap for each image sn
310 for (unsigned int i = 0; i < sns.size(); ++i) {
311 p_lonLatOverlapsMutex.lock();
312 p_lonLatOverlaps.push_back(CreateNewOverlap(sns[i], polygons[i]));
313 p_lonLatOverlapsMutex.unlock();
314 }
315
316 // Despikes the polygons from the Serial Numbers prior to overlap determination
318
319 // Determine the overlap between each boundary polygon
321 }
322
323
329 void ImageOverlapSet::ReadImageOverlaps(const QString &filename) {
330
331 QString file = FileName(filename).expanded();
332
333 try {
334 // Let's get an istream pointed at our file
335 std::ifstream inStream;
336 QByteArray fileArray = file.toLatin1();
337 inStream.open(fileArray.constData(), fstream::in | fstream::binary);
338
339 while (!inStream.eof()) {
340 p_lonLatOverlapsMutex.lock();
341 p_lonLatOverlaps.push_back(new ImageOverlap(inStream));
342 p_lonLatOverlapsMutex.unlock();
343 }
344
345 inStream.close();
346 }
347 catch (IException &e) {
348 p_lonLatOverlapsMutex.unlock();
349 QString msg = "The overlap file [" + filename + "] does not contain a "
350 "valid list of image overlaps";
351 throw IException(e, IException::Unknown, msg, _FILEINFO_);
352 }
353 catch (...) {
354 p_lonLatOverlapsMutex.unlock();
355 QString msg = "The overlap file [" + filename + "] does not contain a "
356 "valid list of image overlaps";
357 throw IException(IException::Unknown, msg, _FILEINFO_);
358 }
359 }
360
361
379 bool ImageOverlapSet::SetPolygon(geos::geom::Geometry *poly,
380 int position,
381 ImageOverlap *sncopy,
382 bool insert) {
383
384 bool success = false;
385 geos::geom::MultiPolygon *multiPolygon = PolygonTools::MakeMultiPolygon(poly);
386 delete poly;
387 poly = NULL;
388
389 if (!multiPolygon->isValid() ||
390 (multiPolygon->getArea() < 1.0e-10 && !multiPolygon->isEmpty())) {
391 delete multiPolygon;
392 multiPolygon = Isis::globalFactory->createMultiPolygon().release();
393 }
394
395 if (position > p_lonLatOverlaps.size()) {
396 position = p_lonLatOverlaps.size();
397 }
398
399 try {
400 if (!multiPolygon->isEmpty()) {
401 geos::geom::MultiPolygon *despiked = PolygonTools::Despike(multiPolygon);
402 delete multiPolygon;
403 multiPolygon = despiked;
404 }
405 }
406 catch (IException &) {
407 }
408
409 if (multiPolygon->isValid() &&
410 (multiPolygon->isEmpty() || multiPolygon->getArea() > 1.0e-14)) {
411 if (!insert) {
412 p_lonLatOverlaps.at(position)->SetPolygon(multiPolygon);
413
414 if (sncopy) {
415 AddSerialNumbers(p_lonLatOverlaps.at(position), sncopy);
416 }
417 }
418 else if (!multiPolygon->isEmpty()) {
419 ImageOverlap *imageOverlap = new ImageOverlap();
420 imageOverlap->SetPolygon(multiPolygon);
421 delete multiPolygon;
422 multiPolygon = NULL;
423
424 if (sncopy) {
425 AddSerialNumbers(imageOverlap, sncopy);
426 }
427
428 // Insert could cause a reallocation of the overlap list, so lock it with
429 // the writing code so that we don't conflict
430 p_lonLatOverlapsMutex.lock();
431 p_lonLatOverlaps.insert(p_lonLatOverlaps.begin() + position, imageOverlap);
432 p_lonLatOverlapsMutex.unlock();
433 }
434
435 success = true;
436 }
437
438 return success;
439 }
440
441
447 void ImageOverlapSet::WriteImageOverlaps(const QString &filename) {
448
449 QString file = FileName(filename).expanded();
450 bool failed = false;
451 bool noOverlaps = false;
452
455 }
456
457 // Let's get an ostream pointed at our file
458 std::ofstream outStream;
459
460 try {
461 QByteArray fileArray = file.toLatin1();
462 if (p_writtenSoFar == 0) {
463 outStream.open(fileArray.constData(), fstream::out | fstream::trunc | fstream::binary);
464 }
465 else {
466 outStream.open(fileArray.constData(), fstream::out | fstream::app | fstream::binary);
467 }
468
469 failed |= outStream.fail();
470
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 (p_writtenSoFar) {
484 outStream << std::endl;
485 }
486
487 p_lonLatOverlaps[overlap]->Write(outStream);
488 }
489
490 delete p_lonLatOverlaps[overlap];
491 p_lonLatOverlaps[overlap] = NULL;
493 }
494 }
495 p_lonLatOverlapsMutex.unlock();
496 }
497
498 failed |= outStream.fail();
499 outStream.close();
500
501 failed |= outStream.fail();
502 }
503 catch (...) {
504 failed = true;
505 }
506 outStream.close();
507
512 if (p_calculatedSoFar == p_lonLatOverlaps.size()) {
513 if (p_threadedCalculate && !noOverlaps) {
514 p_calculatePolygonMutex.tryLock();
516 }
517 }
518
519 if (failed) {
520 p_calculatePolygonMutex.tryLock();
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();
528 QString msg = "No overlaps were found.";
529 throw IException(IException::User, msg, _FILEINFO_);
530 }
531 }
532
533
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().release();
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()))) {
559 p_calculatePolygonMutex.tryLock();
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();
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().release(), 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
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();
814 }
815
816
826
827 for (int i = 0; i < from->Size(); i++) {
828 QString s = (*from)[i];
829 to->Add(s);
830 }
831 }
832
833
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
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
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
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}
IO Handler for Isis Cubes.
Definition Cube.h:168
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
Definition Cube.cpp:872
void open(const QString &cfile, QString access="r")
This method will open an existing isis cube for reading or reading/writing.
Definition Cube.cpp:622
void close(bool remove=false)
Closes the cube and updates the labels.
Definition Cube.cpp:255
File name manipulation and expansion.
Definition FileName.h:100
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Definition FileName.cpp:196
Isis exception class.
Definition IException.h:91
@ Unknown
A type of error that cannot be classified as any of the other error types.
Definition IException.h:118
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
Definition IException.h:126
@ Programmer
This error is for when a programmer made an API call that was illegal.
Definition IException.h:146
@ Io
A type of error that occurred when performing an actual I/O operation.
Definition IException.h:155
Individual overlap container.
void ReadImageOverlaps(const QString &filename)
Create polygons of overlap from the file specified.
QList< ImageOverlap * > p_lonLatOverlaps
The list of lat/lon overlaps.
void FindAllOverlaps(SerialNumberList *snlist=NULL)
Find the overlaps between all the existing ImageOverlap Objects.
std::vector< PvlGroup > p_errorLog
This is a list of detailed* errors including all known information.
int p_calculatedSoFar
The index of the last overlap that is done calculating (number calculated-1)
ImageOverlap * CreateNewOverlap(QString serialNumber, geos::geom::MultiPolygon *lonLatPolygon)
Create an overlap item to hold the overlap poly and its SN.
virtual ~ImageOverlapSet()
Delete this object.
void HandleError(IException &e, SerialNumberList *snlist, QString msg="", int overlap1=-1, int overlap2=-1)
If a problem occurred when searching for image overlaps, this method will handle it.
void AddSerialNumbers(ImageOverlap *to, ImageOverlap *from)
Add the serial numbers from the second overlap to the first.
int p_writtenSoFar
The index of the last overlap that is done writing (number written-1)
bool SetPolygon(geos::geom::Geometry *poly, int position, ImageOverlap *sncopy=NULL, bool insert=false)
This method inserts or overwrites a polygon in the overlap list based on parameters.
ImageOverlapSet(bool continueOnError=false, bool useThread=true)
Create FindImageOverlaps object.
SerialNumberList * p_snlist
This is used for multi-threaded calls to FindAllOverlaps only; this class never gets ownership of thi...
void DespikeLonLatOverlaps()
Despikes all of the overlaps in p_lonLatOverlaps.
QMutex p_calculatePolygonMutex
This mutex will be used to have blocking on the write method when multi-threading (instead of busy wa...
void FindImageOverlaps(SerialNumberList &boundaries)
Create polygons of overlap from the images specified in the serial number list.
int Size()
Returns the total number of latitude and longitude overlaps.
bool p_threadedCalculate
True if we want to do calculations in a threaded way.
bool p_continueAfterError
If false iExceptions will be thrown from FindImageOverlaps(...)
void WriteImageOverlaps(const QString &filename)
Write polygons of overlap to the file specified.
const ImageOverlap * operator[](int index)
Returns the images which overlap at a given loverlap.
Create cube polygons, read/write polygons to blobs.
static geos::geom::MultiPolygon * Despike(const geos::geom::Geometry *geom)
This method attempts to convert the geom to a MultiPolygon and then despike it.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
static geos::geom::Geometry * Difference(const geos::geom::Geometry *geom1, const geos::geom::Geometry *geom2)
This method is used to subtract two polygons.
static geos::geom::Geometry * Intersect(const geos::geom::Geometry *geom1, const geos::geom::Geometry *geom2)
This applies the geos Intersect operator.
Program progress reporter.
Definition Progress.h:42
void SetText(const QString &text)
Changes the value of the text string reported just before 0% processed.
Definition Progress.cpp:61
Contains multiple PvlContainers.
Definition PvlGroup.h:41
A single keyword-value pair.
Definition PvlKeyword.h:87
int size() const
Returns the number of values stored in this keyword.
Definition PvlKeyword.h:133
Serial Number list generator.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
Namespace for the standard library.