Isis 3 Programmer Reference
Shape.cpp
1#include "Shape.h"
2
3#include <QBuffer>
4#include <QDataStream>
5#include <QDebug>
6#include <QDir>
7#include <QFileInfo>
8#include <QMessageBox>
9#include <QMutexLocker>
10#include <QScopedPointer>
11#include <QString>
12#include <QUuid>
13#include <QXmlStreamWriter>
14
15#include <geos/geom/MultiPolygon.h>
16#include <geos/io/WKTReader.h>
17#include <geos/io/WKTWriter.h>
18
19#include "Angle.h"
20#include "CameraFactory.h"
21#include "ControlPoint.h"
22#include "Cube.h"
23#include "CubeAttribute.h"
24#include "DisplayProperties.h"
25#include "Distance.h"
26#include "FileName.h"
27#include "IException.h"
28#include "ImagePolygon.h"
29#include "IString.h"
30#include "PolygonTools.h"
31#include "Project.h"
32#include "ProjectionFactory.h"
33#include "SerialNumber.h"
34#include "ShapeDisplayProperties.h"
35#include "Target.h"
36#include "XmlStackedHandlerReader.h"
37
38namespace Isis {
45 Shape::Shape(QString imageFileName, QObject *parent) : QObject(parent) {
46
47 m_fileName = imageFileName;
48
49 initMemberData();
50 cube();
51 initShape();
52 }
53
54
61 Shape::Shape(Cube *shapeCube, QObject *parent) : QObject(parent) {
62
63 m_fileName = shapeCube->fileName();
64
65 initMemberData();
66 m_cube = shapeCube;
67 initShape();
68 }
69
70
78 Shape::Shape(FileName shapeFolder, XmlStackedHandlerReader *xmlReader, QObject *parent) :
79 QObject(parent) {
80
81 initMemberData();
82 xmlReader->pushContentHandler(new XmlHandler(this, shapeFolder));
83 }
84
85
90 delete m_bodyCode;
91 m_bodyCode = NULL;
92
93 delete m_cube;
94 m_cube = NULL;
95
96 delete m_footprint;
97 m_footprint = NULL;
98
99 delete m_id;
100 m_id = NULL;
101
102 // Shape is a "Qt" parent of display properties, so the Shape QObject
103 // destructor will take care of deleting the display props. See call to
104 // DisplayProperties' constructor.
105 m_displayProperties = NULL;
106 }
107
108
109 void Shape::initMemberData() {
110
111 m_bodyCode = NULL;
112 m_cube = NULL;
113 m_displayProperties = NULL;
114 m_footprint = NULL;
115 m_id = NULL;
116
117 m_aspectRatio = Null;
118 m_resolution = Null;
119 m_lineResolution = Null;
120 m_sampleResolution = Null;
121
122 m_targetName = Null;
123 m_projectionName = Null;
124 m_pixelResolution = Null;
125 m_scale = Null;
126 }
127
128
129 void Shape::initShape() {
130
131 m_displayProperties = new ShapeDisplayProperties(FileName(m_fileName).name(), this);
132 m_id = new QUuid(QUuid::createUuid());
134
135 m_radiusSource = ControlPoint::RadiusSource::None;
136
137 if (cube()->hasTable("ShapeModelStatistics")) {
138 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
139 m_radiusSource = ControlPoint::RadiusSource::DEM;
140 m_shapeType = Dem;
141 }
142 // Is this a level 1 or level 2?
143 else {
144 try {
146 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
147 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
148 m_shapeType = Basemap;
149 }
150 catch (IException &) {
151 // TODO Determine if unprojected shape has been bundle adjusted. Otherwise, ??
152 try {
154 m_surfacePointSource = ControlPoint::SurfacePointSource::Reference;
155
156 PvlGroup kernels = cube()->group("Kernels");
157 if (kernels.hasKeyword("ShapeModel")) {
158 QString shapeFile = kernels["ShapeModel"];
159 if (shapeFile.contains("dem")) {
160 m_radiusSource = ControlPoint::RadiusSource::DEM;
161 }
162 else {
163 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
164 }
165 }
166 m_shapeType = Unprojected;
167 }
168 catch (IException &e) {
169 m_surfacePointSource = ControlPoint::SurfacePointSource::None;
170 m_radiusSource = ControlPoint::RadiusSource::None;
171 m_shapeType = Unknown;
172 QString message = "Cannot create either Camera or Projections "
173 "for the ground source file [" + displayProperties()->displayName() + "]. "
174 "Check the validity of the cube labels. The cube must either be projected or "
175 " run through spiceinit.";
176 throw IException(e, IException::Io, message, _FILEINFO_);
177 }
178 }
179 }
180
181 try {
182 if (m_shapeType == Unprojected) {
183 initCamStats();
184 }
185 else if (m_shapeType == Basemap || m_shapeType == Dem) {
186 initMapStats();
187 if (m_shapeType == Dem) {
188 initDemStats();
189 }
190 }
191 }
192 catch (IException &e) {
193 QString message = "Cannot initialize the camera, map or dem statistics for this shape file [" +
194 displayProperties()->displayName() + "]. Check the validity of the cube labels. The "
195 "cube must either be projected or run through spiceinit. \n";
196 message += e.toString();
197 QMessageBox::warning((QWidget *) parent(), "Warning", message);
198 }
199
200 try {
201 initQuickFootprint();
202 }
203 catch (IException &e) {
204
205 }
206 }
207
208
209 ControlPoint::SurfacePointSource::Source Shape::surfacePointSource() {
210 return m_surfacePointSource;
211 }
212
213
214 ControlPoint::RadiusSource::Source Shape::radiusSource() {
215 return m_radiusSource;
216 }
217
218
219 Shape::ShapeType Shape::shapeType() {
220 return m_shapeType;
221 }
222
223
236 void Shape::fromPvl(const PvlObject &pvl) {
237 QString pvlFileName = ((IString)pvl["FileName"][0]).ToQt();
238 if (m_fileName != pvlFileName) {
240 tr("Tried to load Shape [%1] with properties/information from [%2].")
241 .arg(m_fileName).arg(pvlFileName),
242 _FILEINFO_);
243 }
244
245 displayProperties()->fromPvl(pvl.findObject("DisplayProperties"));
246
247 if (pvl.hasKeyword("ID")) {
248 QByteArray hexValues(pvl["ID"][0].toLatin1());
249 QDataStream valuesStream(QByteArray::fromHex(hexValues));
250 valuesStream >> *m_id;
251 }
252 }
253
254
269 PvlObject output("Shape");
270
271 output += PvlKeyword("FileName", m_fileName);
272
273 // Do m_id
274 QBuffer dataBuffer;
275 dataBuffer.open(QIODevice::ReadWrite);
276
277 QDataStream idStream(&dataBuffer);
278 idStream << *m_id;
279
280 dataBuffer.seek(0);
281
282 output += PvlKeyword("ID", QString(dataBuffer.data().toHex()));
283
284 output += displayProperties()->toPvl();
285
286 return output;
287 }
288
289
295 bool result = false;
296
297 if (m_footprint)
298 result = true;
299
300 if (!result && m_cube) {
301 Blob example = ImagePolygon().toBlob();
302
303 QString blobType = example.Type();
304 QString blobName = example.Name();
305
306 Pvl &labels = *m_cube->label();
307
308 for (int i = 0; i < labels.objects(); i++) {
309 PvlObject &obj = labels.object(i);
310
311 if (obj.isNamed(blobType) && obj.hasKeyword("Name") && obj["Name"][0] == blobName)
312 result = true;
313 }
314 }
315
316 return result;
317 }
318
319
325 if (!m_cube) {
326 try {
327 m_cube = new Cube(m_fileName);
328 }
329 catch (IException &e) {
330 throw IException(e, IException::Programmer, "Cube cannot be created", _FILEINFO_);
331 }
332 }
333
334 return m_cube;
335 }
336
337
343 if (m_cube) {
344 delete m_cube;
345 m_cube = NULL;
346 }
347 }
348
349
358
359
369
370
376 QString Shape::fileName() const {
377 return m_fileName;
378 }
379
380
386 return m_serialNumber;
387 }
388
394 geos::geom::MultiPolygon *Shape::footprint() {
395 return m_footprint;
396 }
397
398
402 void Shape::setId(QString id) {
403 *m_id = QUuid(QString("{%1}").arg(id));
404 }
405
406
412 const geos::geom::MultiPolygon *Shape::footprint() const {
413 return m_footprint;
414 }
415
416
421 bool Shape::initFootprint(QMutex *cameraMutex) {
422 if (!m_footprint) {
423 try {
424 initQuickFootprint();
425 }
426 catch (IException &e) {
427 try {
428 m_footprint = createFootprint(cameraMutex);
429 }
430 catch(IException &e) {
431 IString msg = "Could not read the footprint from cube [" +
432 displayProperties()->displayName() + "]. Please make "
433 "sure footprintinit has been run";
434 throw IException(e, IException::Io, msg, _FILEINFO_);
435 }
436 }
437 }
438
439 // I'm not sure how this could ever be NULL. -SL
440 return (m_footprint != NULL);
441 }
442
443
449 double Shape::aspectRatio() const {
450 return m_aspectRatio;
451 }
452
453
459 QString Shape::id() const {
460 return m_id->toString().remove(QRegExp("[{}]"));
461 }
462
463
470 double Shape::resolution() const {
471 return m_resolution;
472 }
473
474
482 return m_emissionAngle;
483 }
484
485
493 return m_incidenceAngle;
494 }
495
496
503 double Shape::lineResolution() const {
504 return m_lineResolution;
505 }
506
507
515 return m_localRadius;
516 }
517
518
526 return m_northAzimuth;
527 }
528
529
537 return m_phaseAngle;
538 }
539
540
547 double Shape::sampleResolution() const {
548 return m_sampleResolution;
549 }
550
551
555 void Shape::copyToNewProjectRoot(const Project *project, FileName newProjectRoot) {
556 if (FileName(newProjectRoot) != FileName(project->projectRoot())) {
557 Cube origShape(m_fileName);
558
559 FileName newExternalLabelFileName(Project::shapeDataRoot(newProjectRoot.toString()) + "/" +
560 FileName(m_fileName).dir().dirName() + "/" + FileName(m_fileName).name());
561
562 QScopedPointer<Cube> newExternalLabel(
563 origShape.copy(newExternalLabelFileName, CubeAttributeOutput("+External")));
564
565 // If this is an ecub (it should be) and is pointing to a relative file name,
566 // then we want to copy the DN cube also.
567 if (!origShape.storesDnData()) {
568 if (origShape.externalCubeFileName().path() == ".") {
569 Cube dnFile(
570 FileName(m_fileName).path() + "/" + origShape.externalCubeFileName().name());
571
572 FileName newDnFileName = newExternalLabelFileName.setExtension("cub");
573
574 QScopedPointer<Cube> newDnFile(dnFile.copy(newDnFileName, CubeAttributeOutput()));
575 newDnFile->close();
576
577 newExternalLabel->relocateDnData(newDnFileName.name());
578 }
579 else {
580 newExternalLabel->relocateDnData(origShape.externalCubeFileName());
581 }
582 }
583 }
584 }
585
586
592 bool deleteCubAlso = (cube()->externalCubeFileName().path() == ".");
593 closeCube();
594
595 if (!QFile::remove(m_fileName)) {
597 tr("Could not remove file [%1]").arg(m_fileName),
598 _FILEINFO_);
599 }
600
601 if (deleteCubAlso) {
602 FileName cubFile = FileName(m_fileName).setExtension("cub");
603 if (!QFile::remove(cubFile.expanded())) {
605 tr("Could not remove file [%1]").arg(m_fileName),
606 _FILEINFO_);
607 }
608 }
609
610 // If we're the last thing in the folder, remove the folder too.
611 QDir dir;
612 dir.rmdir(FileName(m_fileName).path());
613 }
614
615
623 closeCube();
624
625 FileName original(m_fileName);
626 FileName newName(project->shapeDataRoot() + "/" +
627 original.dir().dirName() + "/" + original.name());
628 m_fileName = newName.expanded();
629 }
630
631
638 geos::geom::MultiPolygon *Shape::createFootprint(QMutex *cameraMutex) {
639 QMutexLocker lock(cameraMutex);
640
641 // We need to walk the shape to create the polygon...
642 ImagePolygon imgPoly;
643
644 int sampleStepSize = cube()->sampleCount() / 10;
645 if (sampleStepSize <= 0) sampleStepSize = 1;
646
647 int lineStepSize = cube()->lineCount() / 10;
648 if (lineStepSize <= 0) lineStepSize = 1;
649
650 imgPoly.Create(*cube(), sampleStepSize, lineStepSize);
651
653 tr("Warning: Polygon re-calculated for [%1] which can be very slow")
654 .arg(displayProperties()->displayName()),
655 _FILEINFO_);
656 e.print();
657
658 return PolygonTools::MakeMultiPolygon(imgPoly.Polys()->clone().release());
659 }
660
661
666 bool hasCamStats = false;
667
668 Pvl &label = *cube()->label();
669 for (int i = 0; !hasCamStats && i < label.objects(); i++) {
670 PvlObject &obj = label.object(i);
671
672 try {
673 if (obj.name() == "Table") {
674 if (obj["Name"][0] == "CameraStatistics") {
675 hasCamStats = true;
676 }
677 }
678 }
679 catch (IException &e) {
680 e.print();
681 }
682 }
683
684 if (hasCamStats) {
685 Table camStatsTable("CameraStatistics", m_fileName, label);
686
687 int numRecords = camStatsTable.Records();
688 for (int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
689 TableRecord &record = camStatsTable[recordIndex];
690
691 // The TableField class gives us a std::string with NULL (\0) characters... be careful not
692 // to keep them when going to QString.
693 QString recordName((QString)record["Name"]);
694 double avgValue = (double)record["Average"];
695
696 if (recordName == "AspectRatio") {
697 m_aspectRatio = avgValue;
698 }
699 else if (recordName == "Resolution") {
700 m_resolution = avgValue;
701 }
702 else if (recordName == "EmissionAngle") {
703 m_emissionAngle = Angle(avgValue, Angle::Degrees);
704 }
705 else if (recordName == "IncidenceAngle") {
706 m_incidenceAngle = Angle(avgValue, Angle::Degrees);
707 }
708 else if (recordName == "LineResolution") {
709 m_lineResolution = avgValue;
710 }
711 else if (recordName == "LocalRadius") {
712 m_localRadius = Distance(avgValue, Distance::Meters);
713 }
714 else if (recordName == "NorthAzimuth") {
715 m_northAzimuth = Angle(avgValue, Angle::Degrees);
716 }
717 else if (recordName == "PhaseAngle") {
718 m_phaseAngle = Angle(avgValue, Angle::Degrees);
719 }
720 else if (recordName == "SampleResolution") {
721 m_sampleResolution = avgValue;
722 }
723 }
724 }
725
726 for (int i = 0; i < label.objects(); i++) {
727 PvlObject &obj = label.object(i);
728 try {
729 if (obj.hasGroup("Instrument")) {
730 PvlGroup instGroup = obj.findGroup("Instrument");
731
732 if (instGroup.hasKeyword("SpacecraftName"))
733 m_spacecraftName = obj.findGroup("Instrument")["SpacecraftName"][0];
734
735 if (instGroup.hasKeyword("InstrumentId"))
736 m_instrumentId = obj.findGroup("Instrument")["InstrumentId"][0];
737 }
738 }
739 catch (IException &e) {
740 e.print();
741 }
742 }
743 }
744
745
746 void Shape::initMapStats() {
747
748 Pvl &label = *cube()->label();
749 for (int i = 0; i < label.objects(); i++) {
750 PvlObject &obj = label.object(i);
751 try {
752 if (obj.hasGroup("Instrument")) {
753 PvlGroup instGroup = obj.findGroup("Instrument");
754
755 if (instGroup.hasKeyword("SpacecraftName"))
756 m_spacecraftName = obj.findGroup("Instrument")["SpacecraftName"][0];
757
758 if (instGroup.hasKeyword("InstrumentId"))
759 m_instrumentId = obj.findGroup("Instrument")["InstrumentId"][0];
760 }
761
762 if (obj.hasGroup("Mapping")) {
763 PvlGroup mapGroup = obj.findGroup("Mapping");
764
765 if (mapGroup.hasKeyword("TargetName"))
766 m_targetName = obj.findGroup("Mapping")["TargetName"][0];
767
768 if (mapGroup.hasKeyword("ProjectionName"))
769 m_projectionName = obj.findGroup("Mapping")["ProjectionName"][0];
770
771 if (mapGroup.hasKeyword("CenterLongitude"))
772 m_centerLongitude = Longitude(toDouble(obj.findGroup("Mapping")["CenterLongitude"][0]),
773 mapGroup, Angle::Degrees);
774
775 if (mapGroup.hasKeyword("CenterLatitude"))
776 m_centerLatitude = Latitude(toDouble(obj.findGroup("Mapping")["CenterLatitude"][0]),
777 mapGroup, Angle::Degrees);
778
779 if (mapGroup.hasKeyword("MinimumLatitude"))
780 m_minimumLatitude = Latitude(toDouble(obj.findGroup("Mapping")["MinimumLatitude"][0]),
781 mapGroup, Angle::Degrees);
782
783 if (mapGroup.hasKeyword("MaximumLatitude"))
784 m_maximumLatitude = Latitude(toDouble(obj.findGroup("Mapping")["MaximumLatitude"][0]),
785 mapGroup, Angle::Degrees);
786
787 if (mapGroup.hasKeyword("MinimumLongitude"))
788 m_minimumLongitude = Longitude(toDouble(obj.findGroup("Mapping")["MinimumLongitude"][0]),
789 mapGroup, Angle::Degrees);
790
791 if (mapGroup.hasKeyword("MaximumLongitude"))
792 m_maximumLongitude = Longitude(toDouble(obj.findGroup("Mapping")["MaximumLongitude"][0]),
793 mapGroup, Angle::Degrees);
794
795 if (mapGroup.hasKeyword("PixelResolution"))
796 m_pixelResolution = obj.findGroup("Mapping")["PixelResolution"];
797
798 if (mapGroup.hasKeyword("Scale"))
799 m_scale = obj.findGroup("Mapping")["Scale"];
800 }
801 }
802 catch (IException &e) {
803 e.print();
804 }
805 }
806 }
807
808
809 void Shape::initDemStats() {
810
811
812 }
813
814
815 void Shape::initQuickFootprint() {
816 ImagePolygon poly = cube()->readFootprint();
817 m_footprint = PolygonTools::MakeMultiPolygon(poly.Polys()->clone().release());
818 }
819
820
829 m_shape = shape;
830 m_shapeFolder = shapeFolder;
831 }
832
833
844 void Shape::save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot)
845 const {
846
847 stream.writeStartElement("shape");
848
849 stream.writeAttribute("id", m_id->toString());
850 stream.writeAttribute("fileName", FileName(m_fileName).name());
851 stream.writeAttribute("serialNumber", m_serialNumber);
852
853 QString type;
854 if (m_shapeType == Unprojected) {
855 type = "Unprojected";
856 }
857 else if (m_shapeType == Basemap) {
858 type = "Basemap";
859 }
860 else {
861 type = "Dem";
862 }
863 stream.writeAttribute("shapeType", type);
864 stream.writeAttribute("surfacePointSource",
865 ControlPoint::SurfacePointSourceToString(m_surfacePointSource));
866 stream.writeAttribute("radiusSource",
867 ControlPoint::RadiusSourceToString(m_radiusSource));
868
869 if (m_shapeType == Unprojected) {
870 stream.writeAttribute("instrumentId", m_instrumentId);
871 stream.writeAttribute("spacecraftName", m_spacecraftName);
872
873 if (!IsSpecial(m_aspectRatio)) {
874 stream.writeAttribute("aspectRatio", IString(m_aspectRatio).ToQt());
875 }
876
877 if (!IsSpecial(m_resolution)) {
878 stream.writeAttribute("resolution", IString(m_resolution).ToQt());
879 }
880
881 if (m_emissionAngle.isValid()) {
882 stream.writeAttribute("emissionAngle", IString(m_emissionAngle.radians()).ToQt());
883 }
884
885 if (m_incidenceAngle.isValid()) {
886 stream.writeAttribute("incidenceAngle", IString(m_incidenceAngle.radians()).ToQt());
887 }
888
889 if (!IsSpecial(m_lineResolution)) {
890 stream.writeAttribute("lineResolution", IString(m_lineResolution).ToQt());
891 }
892
893 if (m_localRadius.isValid()) {
894 stream.writeAttribute("localRadius", IString(m_localRadius.meters()).ToQt());
895 }
896
897 if (m_northAzimuth.isValid()) {
898 stream.writeAttribute("northAzimuth", IString(m_northAzimuth.radians()).ToQt());
899 }
900
901 if (m_phaseAngle.isValid()) {
902 stream.writeAttribute("phaseAngle", IString(m_phaseAngle.radians()).ToQt());
903 }
904
905 if (!IsSpecial(m_sampleResolution)) {
906 stream.writeAttribute("sampleResolution", IString(m_sampleResolution).ToQt());
907 }
908 }
909 else if (m_shapeType == Basemap) {
910
911 }
912 else if (m_shapeType == Dem) {
913
914 }
915
916 if (m_footprint) {
917 stream.writeStartElement("footprint");
918
919 geos::io::WKTWriter wktWriter;
920 stream.writeCharacters(QString::fromStdString(wktWriter.write(m_footprint)));
921
922 stream.writeEndElement();
923 }
924
925 m_displayProperties->save(stream, project, newProjectRoot);
926
927 stream.writeEndElement();
928 }
929
930
936 bool Shape::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
937 const QString &qName, const QXmlAttributes &atts) {
938 m_characters = "";
939
940 if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
941 if (localName == "shape") {
942 QString id = atts.value("id");
943 QString fileName = atts.value("fileName");
944 m_shape->m_serialNumber = atts.value("serialNumber");
945
946 if (!id.isEmpty()) {
947 delete m_shape->m_id;
948 m_shape->m_id = NULL;
949 m_shape->m_id = new QUuid(id.toLatin1());
950 }
951
952 if (!fileName.isEmpty()) {
953 m_shape->m_fileName = m_shapeFolder.expanded() + "/" + fileName;
954 }
955
956 if (m_shape->m_serialNumber.isEmpty()) {
957 m_shape->m_serialNumber = SerialNumber::Compose(*m_shape->cube(), true);
958 }
959
960 m_shape->m_surfacePointSource =
961 ControlPoint::StringToSurfacePointSource(atts.value("surfacePointSource"));
962 m_shape->m_radiusSource =
963 ControlPoint::StringToRadiusSource(atts.value("radiusSource"));
964 QString shapeType = atts.value("shapeType");
965
966 if (shapeType == "Unprojected") {
967 m_shape->m_shapeType = Unprojected;
968 QString instrumentId = atts.value("instrumentId");
969 QString spacecraftName = atts.value("spacecraftName");
970
971 QString aspectRatioStr = atts.value("aspectRatio");
972 QString resolutionStr = atts.value("resolution");
973 QString emissionAngleStr = atts.value("emissionAngle");
974 QString incidenceAngleStr = atts.value("incidenceAngle");
975 QString lineResolutionStr = atts.value("lineResolution");
976 QString localRadiusStr = atts.value("localRadius");
977 QString northAzimuthStr = atts.value("northAzimuth");
978 QString phaseAngleStr = atts.value("phaseAngle");
979 QString sampleResolutionStr = atts.value("sampleResolution");
980
981 if (!instrumentId.isEmpty()) {
982 m_shape->m_instrumentId = m_shapeFolder.expanded() + "/" + instrumentId;
983 }
984
985 if (!instrumentId.isEmpty()) {
986 m_shape->m_instrumentId = m_shapeFolder.expanded() + "/" + instrumentId;
987 }
988
989 if (!spacecraftName.isEmpty()) {
990 m_shape->m_spacecraftName = m_shapeFolder.expanded() + "/" + spacecraftName;
991 }
992
993 if (!aspectRatioStr.isEmpty()) {
994 m_shape->m_aspectRatio = aspectRatioStr.toDouble();
995 }
996
997 if (!resolutionStr.isEmpty()) {
998 m_shape->m_resolution = resolutionStr.toDouble();
999 }
1000
1001 if (!emissionAngleStr.isEmpty()) {
1002 m_shape->m_emissionAngle = Angle(emissionAngleStr.toDouble(), Angle::Radians);
1003 }
1004
1005 if (!incidenceAngleStr.isEmpty()) {
1006 m_shape->m_incidenceAngle = Angle(incidenceAngleStr.toDouble(), Angle::Radians);
1007 }
1008
1009 if (!lineResolutionStr.isEmpty()) {
1010 m_shape->m_lineResolution = lineResolutionStr.toDouble();
1011 }
1012
1013 if (!localRadiusStr.isEmpty()) {
1014 m_shape->m_localRadius = Distance(localRadiusStr.toDouble(), Distance::Meters);
1015 }
1016
1017 if (!northAzimuthStr.isEmpty()) {
1018 m_shape->m_northAzimuth = Angle(northAzimuthStr.toDouble(), Angle::Radians);
1019 }
1020
1021 if (!phaseAngleStr.isEmpty()) {
1022 m_shape->m_phaseAngle = Angle(phaseAngleStr.toDouble(), Angle::Radians);
1023 }
1024
1025 if (!sampleResolutionStr.isEmpty()) {
1026 m_shape->m_sampleResolution = sampleResolutionStr.toDouble();
1027 }
1028 }
1029 else if (shapeType == "Basemap") {
1030 m_shape->m_shapeType = Basemap;
1031 }
1032 else if (shapeType == "Dem") {
1033 m_shape->m_shapeType = Dem;
1034 }
1035 else {
1036 m_shape->m_shapeType = Unknown;
1037 }
1038
1039
1040 }
1041 else if (localName == "displayProperties") {
1042 m_shape->m_displayProperties = new ShapeDisplayProperties(reader());
1043 }
1044 }
1045
1046 return true;
1047 }
1048
1049
1050
1051 bool Shape::XmlHandler::characters(const QString &ch) {
1052 m_characters += ch;
1053
1054 return XmlStackedHandler::characters(ch);
1055 }
1056
1057
1058
1059 bool Shape::XmlHandler::endElement(const QString &namespaceURI, const QString &localName,
1060 const QString &qName) {
1061 if (localName == "footprint" && !m_characters.isEmpty()) {
1062 geos::io::WKTReader wktReader(*globalFactory);
1063 try {
1064 m_shape->m_footprint = PolygonTools::MakeMultiPolygon(
1065 wktReader.read(m_characters.toStdString()).release());
1066 }
1067 catch (IException &e) {
1068 e.print();
1069 }
1070 }
1071 else if (localName == "shape" && !m_shape->m_footprint) {
1072 try {
1073 QMutex mutex;
1074 m_shape->initFootprint(&mutex);
1075 m_shape->closeCube();
1076 }
1077 catch (IException &e) {
1078 e.print();
1079 }
1080 }
1081
1082 m_characters = "";
1083 return XmlStackedHandler::endElement(namespaceURI, localName, qName);
1084 }
1085}
Defines an angle and provides unit conversions.
Definition Angle.h:45
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid,...
Definition Angle.cpp:95
double radians() const
Convert an angle to a double.
Definition Angle.h:226
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition Angle.h:56
@ Radians
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition Angle.h:63
QString Type() const
Accessor method that returns a string containing the Blob type.
Definition Blob.cpp:124
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
static QString RadiusSourceToString(RadiusSource::Source source)
Obtain a string representation of a given RadiusSource.
static SurfacePointSource::Source StringToSurfacePointSource(QString str)
Obtain a SurfacePoint::Source from a string.
static RadiusSource::Source StringToRadiusSource(QString str)
Obtain a RadiusSource::Source from a string.
static QString SurfacePointSourceToString(SurfacePointSource::Source source)
Obtain a string representation of a given SurfacePointSource.
Manipulate and parse attributes of output cube filenames.
IO Handler for Isis Cubes.
Definition Cube.h:168
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
Definition Cube.cpp:872
int lineCount() const
Definition Cube.cpp:1740
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
Definition Cube.cpp:1541
PvlGroup & group(const QString &group) const
Read a group from the cube into a Label.
Definition Cube.cpp:1997
int sampleCount() const
Definition Cube.cpp:1813
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition Cube.cpp:1707
QString displayName() const
Returns the display name.
PvlObject toPvl() const
Convert to Pvl for project files.
Distance measurement, usually in meters.
Definition Distance.h:34
bool isValid() const
Test if this distance has been initialized or not.
Definition Distance.cpp:192
@ Meters
The distance is being specified in meters.
Definition Distance.h:43
double meters() const
Get the distance in meters.
Definition Distance.cpp:85
File name manipulation and expansion.
Definition FileName.h:100
QString path() const
Returns the path of the file name.
Definition FileName.cpp:103
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
Definition FileName.cpp:465
FileName setExtension(const QString &extension) const
Sets all current file extensions to a new extension in the file name.
Definition FileName.cpp:265
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition FileName.cpp:162
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition FileName.cpp:515
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
Adds specific functionality to C++ strings.
Definition IString.h:165
QString ToQt() const
Retuns the object string as a QString.
Definition IString.cpp:869
Create cube polygons, read/write polygons to blobs.
Blob toBlob() const
Serialize the ImagePolygon to a Blob.
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
The main project for ipce.
Definition Project.h:289
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
Definition Project.cpp:2086
QString projectRoot() const
Get the top-level folder of the project.
Definition Project.cpp:1665
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition Project.cpp:2096
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
Contains multiple PvlContainers.
Definition PvlGroup.h:41
Container for cube-like labels.
Definition Pvl.h:119
A single keyword-value pair.
Definition PvlKeyword.h:87
Contains Pvl Groups and Pvl Objects.
Definition PvlObject.h:61
int objects() const
Returns the number of objects.
Definition PvlObject.h:221
PvlObject & object(const int index)
Return the object at the specified index.
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
XmlHandler(Shape *shape, FileName shapeFolder)
Create an XML Handler (reader) that can populate the Shape class data.
Definition Shape.cpp:828
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
Definition Shape.cpp:936
This is the GUI communication mechanism for shape objects.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Saves this object to an XML file.
This represents a shape in a project-based GUI interface.
Definition Shape.h:68
void initCamStats()
TODO.
Definition Shape.cpp:665
~Shape()
Clean up this shape.
Definition Shape.cpp:89
geos::geom::MultiPolygon * createFootprint(QMutex *cameraMutex)
Calculate a footprint for an Shape using the camera or projection information.
Definition Shape.cpp:638
Shape(QString shapeFileName, QObject *parent=0)
Create an Shape from a cube file on disk.
Definition Shape.cpp:45
void closeCube()
Cleans up the Cube *.
Definition Shape.cpp:342
PvlObject toPvl() const
Convert this Shape to PVL.
Definition Shape.cpp:268
bool isFootprintable() const
Test to see if it's possible to create a footprint from this shape.
Definition Shape.cpp:294
SpiceInt * m_bodyCode
The NaifBodyCode value, if it exists in the labels.
Definition Shape.h:157
Distance localRadius() const
Get the local radius of this shape, as calculated and attached by camstats.
Definition Shape.cpp:514
Angle phaseAngle() const
Get the phase angle of this shape, as calculated and attached by camstats.
Definition Shape.cpp:536
void updateFileName(Project *)
Change the on-disk file name for this cube to be where the shape ought to be in the given project.
Definition Shape.cpp:622
double resolution() const
Get the resolution of this shape, as calculated and attached by camstats.
Definition Shape.cpp:470
QString serialNumber()
Get the serial number.
Definition Shape.cpp:385
QString m_spacecraftName
Spacecraft name associated with this Shape.
Definition Shape.h:192
double sampleResolution() const
Get the sample resolution of this shape, as calculated and attached by camstats.
Definition Shape.cpp:547
ShapeDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this shape.
Definition Shape.cpp:355
double lineResolution() const
Get the line resolution of this shape, as calculated and attached by camstats.
Definition Shape.cpp:503
void deleteFromDisk()
Delete the shape data from disk.
Definition Shape.cpp:591
Angle emissionAngle() const
Get the emission angle of this shape, as calculated and attached by camstats.
Definition Shape.cpp:481
QString id() const
Get a unique, identifying string associated with this shape.
Definition Shape.cpp:459
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
Definition Shape.cpp:844
double aspectRatio() const
Get the aspect ratio of this shape, as calculated and attached by camstats.
Definition Shape.cpp:449
QString fileName() const
Get the file name of the cube that this shape represents.
Definition Shape.cpp:376
Cube * m_cube
The cube associated with this Shape.
Definition Shape.h:168
geos::geom::MultiPolygon * m_footprint
A 0-360 ocentric lon,lat degrees footprint of this Shape.
Definition Shape.h:196
Cube * cube()
Get the Cube * associated with this display property.
Definition Shape.cpp:324
Angle incidenceAngle() const
Get the incidence angle of this shape, as calculated and attached by camstats.
Definition Shape.cpp:492
void copyToNewProjectRoot(const Project *project, FileName newProjectRoot)
Copy the cub/ecub files associated with this shape into the new project.
Definition Shape.cpp:555
QUuid * m_id
A unique ID for this Shape (useful for others to reference this Shape when saving to disk).
Definition Shape.h:200
QString m_serialNumber
This will always be simply the filename and is created on construction.
Definition Shape.h:184
QString m_instrumentId
Instrument id associated with this Shape.
Definition Shape.h:188
bool initFootprint(QMutex *cameraMutex)
Calculate a footprint for this shape.
Definition Shape.cpp:421
void fromPvl(const PvlObject &pvl)
Read the shape settings from a Pvl.
Definition Shape.cpp:236
void setId(QString id)
Override the automatically generated ID with the given ID.
Definition Shape.cpp:402
Angle northAzimuth() const
Get the north azimuth of this shape, as calculated and attached by camstats.
Definition Shape.cpp:525
geos::geom::MultiPolygon * footprint()
Get the footprint of this shape (if available).
Definition Shape.cpp:394
QString m_fileName
The on-disk file name of the cube associated with this Shape.
Definition Shape.h:180
ShapeDisplayProperties * m_displayProperties
The GUI information for how this Shape ought to be displayed.
Definition Shape.h:176
Class for storing Table blobs information.
Definition Table.h:61
Manage a stack of content handlers for reading XML files.
This is free and unencumbered software released into the public domain.
Definition Apollo.h:16
const double Null
Value for an Isis Null pixel.
bool IsSpecial(const double d)
Returns if the input pixel is special.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition IString.cpp:149