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 
38 namespace 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 
294  bool Shape::isFootprintable() const {
295  bool result = false;
296 
297  if (m_footprint)
298  result = true;
299 
300  if (!result && m_cube) {
301  // TODO: Move this to Blob!
302  ImagePolygon example;
303 
304  QString blobType = example.Type();
305  QString blobName = example.Name();
306 
307  Pvl &labels = *m_cube->label();
308 
309  for (int i = 0; i < labels.objects(); i++) {
310  PvlObject &obj = labels.object(i);
311 
312  if (obj.isNamed(blobType) && obj.hasKeyword("Name") && obj["Name"][0] == blobName)
313  result = true;
314  }
315  }
316 
317  return result;
318  }
319 
320 
326  if (!m_cube) {
327  try {
328  m_cube = new Cube(m_fileName);
329  }
330  catch (IException &e) {
331  throw IException(e, IException::Programmer, "Cube cannot be created", _FILEINFO_);
332  }
333  }
334 
335  return m_cube;
336  }
337 
338 
344  if (m_cube) {
345  delete m_cube;
346  m_cube = NULL;
347  }
348  }
349 
350 
357  return m_displayProperties;
358  }
359 
360 
368  return m_displayProperties;
369  }
370 
371 
377  QString Shape::fileName() const {
378  return m_fileName;
379  }
380 
381 
387  return m_serialNumber;
388  }
389 
395  geos::geom::MultiPolygon *Shape::footprint() {
396  return m_footprint;
397  }
398 
399 
403  void Shape::setId(QString id) {
404  *m_id = QUuid(QString("{%1}").arg(id));
405  }
406 
407 
413  const geos::geom::MultiPolygon *Shape::footprint() const {
414  return m_footprint;
415  }
416 
417 
422  bool Shape::initFootprint(QMutex *cameraMutex) {
423  if (!m_footprint) {
424  try {
425  initQuickFootprint();
426  }
427  catch (IException &e) {
428  try {
429  m_footprint = createFootprint(cameraMutex);
430  }
431  catch(IException &e) {
432  IString msg = "Could not read the footprint from cube [" +
433  displayProperties()->displayName() + "]. Please make "
434  "sure footprintinit has been run";
435  throw IException(e, IException::Io, msg, _FILEINFO_);
436  }
437  }
438  }
439 
440  // I'm not sure how this could ever be NULL. -SL
441  return (m_footprint != NULL);
442  }
443 
444 
450  double Shape::aspectRatio() const {
451  return m_aspectRatio;
452  }
453 
454 
460  QString Shape::id() const {
461  return m_id->toString().remove(QRegExp("[{}]"));
462  }
463 
464 
471  double Shape::resolution() const {
472  return m_resolution;
473  }
474 
475 
483  return m_emissionAngle;
484  }
485 
486 
494  return m_incidenceAngle;
495  }
496 
497 
504  double Shape::lineResolution() const {
505  return m_lineResolution;
506  }
507 
508 
516  return m_localRadius;
517  }
518 
519 
527  return m_northAzimuth;
528  }
529 
530 
538  return m_phaseAngle;
539  }
540 
541 
548  double Shape::sampleResolution() const {
549  return m_sampleResolution;
550  }
551 
552 
556  void Shape::copyToNewProjectRoot(const Project *project, FileName newProjectRoot) {
557  if (FileName(newProjectRoot) != FileName(project->projectRoot())) {
558  Cube origShape(m_fileName);
559 
560  FileName newExternalLabelFileName(Project::shapeDataRoot(newProjectRoot.toString()) + "/" +
561  FileName(m_fileName).dir().dirName() + "/" + FileName(m_fileName).name());
562 
563  QScopedPointer<Cube> newExternalLabel(
564  origShape.copy(newExternalLabelFileName, CubeAttributeOutput("+External")));
565 
566  // If this is an ecub (it should be) and is pointing to a relative file name,
567  // then we want to copy the DN cube also.
568  if (!origShape.storesDnData()) {
569  if (origShape.externalCubeFileName().path() == ".") {
570  Cube dnFile(
571  FileName(m_fileName).path() + "/" + origShape.externalCubeFileName().name());
572 
573  FileName newDnFileName = newExternalLabelFileName.setExtension("cub");
574 
575  QScopedPointer<Cube> newDnFile(dnFile.copy(newDnFileName, CubeAttributeOutput()));
576  newDnFile->close();
577 
578  newExternalLabel->relocateDnData(newDnFileName.name());
579  }
580  else {
581  newExternalLabel->relocateDnData(origShape.externalCubeFileName());
582  }
583  }
584  }
585  }
586 
587 
593  bool deleteCubAlso = (cube()->externalCubeFileName().path() == ".");
594  closeCube();
595 
596  if (!QFile::remove(m_fileName)) {
598  tr("Could not remove file [%1]").arg(m_fileName),
599  _FILEINFO_);
600  }
601 
602  if (deleteCubAlso) {
603  FileName cubFile = FileName(m_fileName).setExtension("cub");
604  if (!QFile::remove(cubFile.expanded())) {
606  tr("Could not remove file [%1]").arg(m_fileName),
607  _FILEINFO_);
608  }
609  }
610 
611  // If we're the last thing in the folder, remove the folder too.
612  QDir dir;
613  dir.rmdir(FileName(m_fileName).path());
614  }
615 
616 
624  closeCube();
625 
626  FileName original(m_fileName);
627  FileName newName(project->shapeDataRoot() + "/" +
628  original.dir().dirName() + "/" + original.name());
629  m_fileName = newName.expanded();
630  }
631 
632 
639  geos::geom::MultiPolygon *Shape::createFootprint(QMutex *cameraMutex) {
640  QMutexLocker lock(cameraMutex);
641 
642  // We need to walk the shape to create the polygon...
643  ImagePolygon imgPoly;
644 
645  int sampleStepSize = cube()->sampleCount() / 10;
646  if (sampleStepSize <= 0) sampleStepSize = 1;
647 
648  int lineStepSize = cube()->lineCount() / 10;
649  if (lineStepSize <= 0) lineStepSize = 1;
650 
651  imgPoly.Create(*cube(), sampleStepSize, lineStepSize);
652 
654  tr("Warning: Polygon re-calculated for [%1] which can be very slow")
655  .arg(displayProperties()->displayName()),
656  _FILEINFO_);
657  e.print();
658 
659  return PolygonTools::MakeMultiPolygon(imgPoly.Polys()->clone());
660  }
661 
662 
667  bool hasCamStats = false;
668 
669  Pvl &label = *cube()->label();
670  for (int i = 0; !hasCamStats && i < label.objects(); i++) {
671  PvlObject &obj = label.object(i);
672 
673  try {
674  if (obj.name() == "Table") {
675  if (obj["Name"][0] == "CameraStatistics") {
676  hasCamStats = true;
677  }
678  }
679  }
680  catch (IException &e) {
681  e.print();
682  }
683  }
684 
685  if (hasCamStats) {
686  Table camStatsTable("CameraStatistics", m_fileName, label);
687 
688  int numRecords = camStatsTable.Records();
689  for (int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
690  TableRecord &record = camStatsTable[recordIndex];
691 
692  // The TableField class gives us a std::string with NULL (\0) characters... be careful not
693  // to keep them when going to QString.
694  QString recordName((QString)record["Name"]);
695  double avgValue = (double)record["Average"];
696 
697  if (recordName == "AspectRatio") {
698  m_aspectRatio = avgValue;
699  }
700  else if (recordName == "Resolution") {
701  m_resolution = avgValue;
702  }
703  else if (recordName == "EmissionAngle") {
704  m_emissionAngle = Angle(avgValue, Angle::Degrees);
705  }
706  else if (recordName == "IncidenceAngle") {
707  m_incidenceAngle = Angle(avgValue, Angle::Degrees);
708  }
709  else if (recordName == "LineResolution") {
710  m_lineResolution = avgValue;
711  }
712  else if (recordName == "LocalRadius") {
713  m_localRadius = Distance(avgValue, Distance::Meters);
714  }
715  else if (recordName == "NorthAzimuth") {
716  m_northAzimuth = Angle(avgValue, Angle::Degrees);
717  }
718  else if (recordName == "PhaseAngle") {
719  m_phaseAngle = Angle(avgValue, Angle::Degrees);
720  }
721  else if (recordName == "SampleResolution") {
722  m_sampleResolution = avgValue;
723  }
724  }
725  }
726 
727  for (int i = 0; i < label.objects(); i++) {
728  PvlObject &obj = label.object(i);
729  try {
730  if (obj.hasGroup("Instrument")) {
731  PvlGroup instGroup = obj.findGroup("Instrument");
732 
733  if (instGroup.hasKeyword("SpacecraftName"))
734  m_spacecraftName = obj.findGroup("Instrument")["SpacecraftName"][0];
735 
736  if (instGroup.hasKeyword("InstrumentId"))
737  m_instrumentId = obj.findGroup("Instrument")["InstrumentId"][0];
738  }
739  }
740  catch (IException &e) {
741  e.print();
742  }
743  }
744  }
745 
746 
747  void Shape::initMapStats() {
748 
749  Pvl &label = *cube()->label();
750  for (int i = 0; i < label.objects(); i++) {
751  PvlObject &obj = label.object(i);
752  try {
753  if (obj.hasGroup("Instrument")) {
754  PvlGroup instGroup = obj.findGroup("Instrument");
755 
756  if (instGroup.hasKeyword("SpacecraftName"))
757  m_spacecraftName = obj.findGroup("Instrument")["SpacecraftName"][0];
758 
759  if (instGroup.hasKeyword("InstrumentId"))
760  m_instrumentId = obj.findGroup("Instrument")["InstrumentId"][0];
761  }
762 
763  if (obj.hasGroup("Mapping")) {
764  PvlGroup mapGroup = obj.findGroup("Mapping");
765 
766  if (mapGroup.hasKeyword("TargetName"))
767  m_targetName = obj.findGroup("Mapping")["TargetName"][0];
768 
769  if (mapGroup.hasKeyword("ProjectionName"))
770  m_projectionName = obj.findGroup("Mapping")["ProjectionName"][0];
771 
772  if (mapGroup.hasKeyword("CenterLongitude"))
773  m_centerLongitude = Longitude(toDouble(obj.findGroup("Mapping")["CenterLongitude"][0]),
774  mapGroup, Angle::Degrees);
775 
776  if (mapGroup.hasKeyword("CenterLatitude"))
777  m_centerLatitude = Latitude(toDouble(obj.findGroup("Mapping")["CenterLatitude"][0]),
778  mapGroup, Angle::Degrees);
779 
780  if (mapGroup.hasKeyword("MinimumLatitude"))
781  m_minimumLatitude = Latitude(toDouble(obj.findGroup("Mapping")["MinimumLatitude"][0]),
782  mapGroup, Angle::Degrees);
783 
784  if (mapGroup.hasKeyword("MaximumLatitude"))
785  m_maximumLatitude = Latitude(toDouble(obj.findGroup("Mapping")["MaximumLatitude"][0]),
786  mapGroup, Angle::Degrees);
787 
788  if (mapGroup.hasKeyword("MinimumLongitude"))
789  m_minimumLongitude = Longitude(toDouble(obj.findGroup("Mapping")["MinimumLongitude"][0]),
790  mapGroup, Angle::Degrees);
791 
792  if (mapGroup.hasKeyword("MaximumLongitude"))
793  m_maximumLongitude = Longitude(toDouble(obj.findGroup("Mapping")["MaximumLongitude"][0]),
794  mapGroup, Angle::Degrees);
795 
796  if (mapGroup.hasKeyword("PixelResolution"))
797  m_pixelResolution = obj.findGroup("Mapping")["PixelResolution"];
798 
799  if (mapGroup.hasKeyword("Scale"))
800  m_scale = obj.findGroup("Mapping")["Scale"];
801  }
802  }
803  catch (IException &e) {
804  e.print();
805  }
806  }
807  }
808 
809 
810  void Shape::initDemStats() {
811 
812 
813  }
814 
815 
816  void Shape::initQuickFootprint() {
817  ImagePolygon poly;
818  cube()->read(poly);
819  m_footprint = PolygonTools::MakeMultiPolygon(poly.Polys()->clone());
820  }
821 
822 
831  m_shape = shape;
832  m_shapeFolder = shapeFolder;
833  }
834 
835 
846  void Shape::save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot)
847  const {
848 
849  stream.writeStartElement("shape");
850 
851  stream.writeAttribute("id", m_id->toString());
852  stream.writeAttribute("fileName", FileName(m_fileName).name());
853  stream.writeAttribute("serialNumber", m_serialNumber);
854 
855  QString type;
856  if (m_shapeType == Unprojected) {
857  type = "Unprojected";
858  }
859  else if (m_shapeType == Basemap) {
860  type = "Basemap";
861  }
862  else {
863  type = "Dem";
864  }
865  stream.writeAttribute("shapeType", type);
866  stream.writeAttribute("surfacePointSource",
867  ControlPoint::SurfacePointSourceToString(m_surfacePointSource));
868  stream.writeAttribute("radiusSource",
869  ControlPoint::RadiusSourceToString(m_radiusSource));
870 
871  if (m_shapeType == Unprojected) {
872  stream.writeAttribute("instrumentId", m_instrumentId);
873  stream.writeAttribute("spacecraftName", m_spacecraftName);
874 
875  if (!IsSpecial(m_aspectRatio)) {
876  stream.writeAttribute("aspectRatio", IString(m_aspectRatio).ToQt());
877  }
878 
879  if (!IsSpecial(m_resolution)) {
880  stream.writeAttribute("resolution", IString(m_resolution).ToQt());
881  }
882 
883  if (m_emissionAngle.isValid()) {
884  stream.writeAttribute("emissionAngle", IString(m_emissionAngle.radians()).ToQt());
885  }
886 
887  if (m_incidenceAngle.isValid()) {
888  stream.writeAttribute("incidenceAngle", IString(m_incidenceAngle.radians()).ToQt());
889  }
890 
891  if (!IsSpecial(m_lineResolution)) {
892  stream.writeAttribute("lineResolution", IString(m_lineResolution).ToQt());
893  }
894 
895  if (m_localRadius.isValid()) {
896  stream.writeAttribute("localRadius", IString(m_localRadius.meters()).ToQt());
897  }
898 
899  if (m_northAzimuth.isValid()) {
900  stream.writeAttribute("northAzimuth", IString(m_northAzimuth.radians()).ToQt());
901  }
902 
903  if (m_phaseAngle.isValid()) {
904  stream.writeAttribute("phaseAngle", IString(m_phaseAngle.radians()).ToQt());
905  }
906 
907  if (!IsSpecial(m_sampleResolution)) {
908  stream.writeAttribute("sampleResolution", IString(m_sampleResolution).ToQt());
909  }
910  }
911  else if (m_shapeType == Basemap) {
912 
913  }
914  else if (m_shapeType == Dem) {
915 
916  }
917 
918  if (m_footprint) {
919  stream.writeStartElement("footprint");
920 
921  geos::io::WKTWriter wktWriter;
922  stream.writeCharacters(QString::fromStdString(wktWriter.write(m_footprint)));
923 
924  stream.writeEndElement();
925  }
926 
927  m_displayProperties->save(stream, project, newProjectRoot);
928 
929  stream.writeEndElement();
930  }
931 
932 
938  bool Shape::XmlHandler::startElement(const QString &namespaceURI, const QString &localName,
939  const QString &qName, const QXmlAttributes &atts) {
940  m_characters = "";
941 
942  if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
943  if (localName == "shape") {
944  QString id = atts.value("id");
945  QString fileName = atts.value("fileName");
946  m_shape->m_serialNumber = atts.value("serialNumber");
947 
948  if (!id.isEmpty()) {
949  delete m_shape->m_id;
950  m_shape->m_id = NULL;
951  m_shape->m_id = new QUuid(id.toLatin1());
952  }
953 
954  if (!fileName.isEmpty()) {
955  m_shape->m_fileName = m_shapeFolder.expanded() + "/" + fileName;
956  }
957 
958  if (m_shape->m_serialNumber.isEmpty()) {
959  m_shape->m_serialNumber = SerialNumber::Compose(*m_shape->cube(), true);
960  }
961 
962  m_shape->m_surfacePointSource =
963  ControlPoint::StringToSurfacePointSource(atts.value("surfacePointSource"));
964  m_shape->m_radiusSource =
965  ControlPoint::StringToRadiusSource(atts.value("radiusSource"));
966  QString shapeType = atts.value("shapeType");
967 
968  if (shapeType == "Unprojected") {
969  m_shape->m_shapeType = Unprojected;
970  QString instrumentId = atts.value("instrumentId");
971  QString spacecraftName = atts.value("spacecraftName");
972 
973  QString aspectRatioStr = atts.value("aspectRatio");
974  QString resolutionStr = atts.value("resolution");
975  QString emissionAngleStr = atts.value("emissionAngle");
976  QString incidenceAngleStr = atts.value("incidenceAngle");
977  QString lineResolutionStr = atts.value("lineResolution");
978  QString localRadiusStr = atts.value("localRadius");
979  QString northAzimuthStr = atts.value("northAzimuth");
980  QString phaseAngleStr = atts.value("phaseAngle");
981  QString sampleResolutionStr = atts.value("sampleResolution");
982 
983  if (!instrumentId.isEmpty()) {
984  m_shape->m_instrumentId = m_shapeFolder.expanded() + "/" + instrumentId;
985  }
986 
987  if (!instrumentId.isEmpty()) {
988  m_shape->m_instrumentId = m_shapeFolder.expanded() + "/" + instrumentId;
989  }
990 
991  if (!spacecraftName.isEmpty()) {
992  m_shape->m_spacecraftName = m_shapeFolder.expanded() + "/" + spacecraftName;
993  }
994 
995  if (!aspectRatioStr.isEmpty()) {
996  m_shape->m_aspectRatio = aspectRatioStr.toDouble();
997  }
998 
999  if (!resolutionStr.isEmpty()) {
1000  m_shape->m_resolution = resolutionStr.toDouble();
1001  }
1002 
1003  if (!emissionAngleStr.isEmpty()) {
1004  m_shape->m_emissionAngle = Angle(emissionAngleStr.toDouble(), Angle::Radians);
1005  }
1006 
1007  if (!incidenceAngleStr.isEmpty()) {
1008  m_shape->m_incidenceAngle = Angle(incidenceAngleStr.toDouble(), Angle::Radians);
1009  }
1010 
1011  if (!lineResolutionStr.isEmpty()) {
1012  m_shape->m_lineResolution = lineResolutionStr.toDouble();
1013  }
1014 
1015  if (!localRadiusStr.isEmpty()) {
1016  m_shape->m_localRadius = Distance(localRadiusStr.toDouble(), Distance::Meters);
1017  }
1018 
1019  if (!northAzimuthStr.isEmpty()) {
1020  m_shape->m_northAzimuth = Angle(northAzimuthStr.toDouble(), Angle::Radians);
1021  }
1022 
1023  if (!phaseAngleStr.isEmpty()) {
1024  m_shape->m_phaseAngle = Angle(phaseAngleStr.toDouble(), Angle::Radians);
1025  }
1026 
1027  if (!sampleResolutionStr.isEmpty()) {
1028  m_shape->m_sampleResolution = sampleResolutionStr.toDouble();
1029  }
1030  }
1031  else if (shapeType == "Basemap") {
1032  m_shape->m_shapeType = Basemap;
1033  }
1034  else if (shapeType == "Dem") {
1035  m_shape->m_shapeType = Dem;
1036  }
1037  else {
1038  m_shape->m_shapeType = Unknown;
1039  }
1040 
1041 
1042  }
1043  else if (localName == "displayProperties") {
1044  m_shape->m_displayProperties = new ShapeDisplayProperties(reader());
1045  }
1046  }
1047 
1048  return true;
1049  }
1050 
1051 
1052 
1053  bool Shape::XmlHandler::characters(const QString &ch) {
1054  m_characters += ch;
1055 
1056  return XmlStackedHandler::characters(ch);
1057  }
1058 
1059 
1060 
1061  bool Shape::XmlHandler::endElement(const QString &namespaceURI, const QString &localName,
1062  const QString &qName) {
1063  if (localName == "footprint" && !m_characters.isEmpty()) {
1064  geos::io::WKTReader wktReader(&globalFactory);
1065  try {
1066  m_shape->m_footprint = PolygonTools::MakeMultiPolygon(
1067  wktReader.read(m_characters.toStdString()));
1068  }
1069  catch (IException &e) {
1070  e.print();
1071  }
1072  }
1073  else if (localName == "shape" && !m_shape->m_footprint) {
1074  try {
1075  QMutex mutex;
1076  m_shape->initFootprint(&mutex);
1077  m_shape->closeCube();
1078  }
1079  catch (IException &e) {
1080  e.print();
1081  }
1082  }
1083 
1084  m_characters = "";
1085  return XmlStackedHandler::endElement(namespaceURI, localName, qName);
1086  }
1087 }
PvlObject & object(const int index)
Return the object at the specified index.
Definition: PvlObject.cpp:460
int Records() const
Returns the number of records.
Definition: Table.cpp:224
PvlObject toPvl() const
Convert this Shape to PVL.
Definition: Shape.cpp:268
double resolution() const
Get the resolution of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:471
QString path() const
Returns the path of the file name.
Definition: FileName.cpp:119
double meters() const
Get the distance in meters.
Definition: Distance.cpp:97
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
const double Null
Value for an Isis Null pixel.
Definition: SpecialPixel.h:110
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
The main project for ipce.
Definition: Project.h:289
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
Definition: PvlObject.h:141
void closeCube()
Cleans up the Cube *.
Definition: Shape.cpp:343
bool storesDnData() const
This method returns a boolean value.
Definition: Cube.cpp:1549
File name manipulation and expansion.
Definition: FileName.h:116
int objects() const
Returns the number of objects.
Definition: PvlObject.h:231
Angle incidenceAngle() const
Get the incidence angle of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:493
PvlObject toPvl() const
Convert to Pvl for project files.
QString m_spacecraftName
Spacecraft name associated with this Shape.
Definition: Shape.h:202
double radians() const
Convert an angle to a double.
Definition: Angle.h:243
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Definition: PvlObject.h:286
int sampleCount() const
Definition: Cube.cpp:1452
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name &#39;shapes&#39; to the project .
Definition: Project.cpp:2087
Angle northAzimuth() const
Get the north azimuth of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:526
void copyToNewProjectRoot(const Project *project, FileName newProjectRoot)
Copy the cub/ecub files associated with this shape into the new project.
Definition: Shape.cpp:556
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
Definition: FileName.cpp:178
QString displayName() const
Returns the display name.
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Definition: PvlObject.h:222
Distance localRadius() const
Get the local radius of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:515
ShapeDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this shape.
Definition: Shape.cpp:356
geos::geom::MultiPolygon * createFootprint(QMutex *cameraMutex)
Calculate a footprint for an Shape using the camera or projection information.
Definition: Shape.cpp:639
This is the GUI communication mechanism for shape objects.
~Shape()
Clean up this shape.
Definition: Shape.cpp:89
Unless noted otherwise, the portions of Isis written by the USGS are public domain.
double toDouble(const QString &string)
Global function to convert from a string to a double.
Definition: IString.cpp:164
This error is for when a programmer made an API call that was illegal.
Definition: IException.h:162
A type of error that occurred when performing an actual I/O operation.
Definition: IException.h:171
double sampleResolution() const
Get the sample resolution of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:548
Distance measurement, usually in meters.
Definition: Distance.h:47
void Create(Cube &cube, int sinc=1, int linc=1, int ss=1, int sl=1, int ns=0, int nl=0, int band=1, bool increasePrecision=false)
Create a Polygon from given cube.
XmlHandler(Shape *shape, FileName shapeFolder)
Create an XML Handler (reader) that can populate the Shape class data.
Definition: Shape.cpp:830
Create cube polygons, read/write polygons to blobs.
Definition: ImagePolygon.h:167
bool hasKeyword(const QString &kname, FindOptions opts) const
See if a keyword is in the current PvlObject, or deeper inside other PvlObjects and Pvlgroups within ...
Definition: PvlObject.cpp:207
PvlGroup & group(const QString &group) const
Read a group from the cube into a Label.
Definition: Cube.cpp:1636
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
static QString SurfacePointSourceToString(SurfacePointSource::Source source)
Obtain a string representation of a given SurfacePointSource.
QString name() const
Returns the container name.
Definition: PvlContainer.h:77
static QString RadiusSourceToString(RadiusSource::Source source)
Obtain a string representation of a given RadiusSource.
QString m_instrumentId
Instrument id associated with this Shape.
Definition: Shape.h:198
bool initFootprint(QMutex *cameraMutex)
Calculate a footprint for this shape.
Definition: Shape.cpp:422
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
Definition: Shape.cpp:938
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
Definition: Shape.cpp:846
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
Definition: Angle.h:73
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
Definition: Project.cpp:2097
static RadiusSource::Source StringToRadiusSource(QString str)
Obtain a RadiusSource::Source from a string.
QUuid * m_id
A unique ID for this Shape (useful for others to reference this Shape when saving to disk)...
Definition: Shape.h:210
static geos::geom::MultiPolygon * MakeMultiPolygon(const geos::geom::Geometry *geom)
Make a geos::geom::MultiPolygon out of the components of the argument.
Cube * cube()
Get the Cube * associated with this display property.
Definition: Shape.cpp:325
Contains multiple PvlContainers.
Definition: PvlGroup.h:57
#define _FILEINFO_
Macro for the filename and line number.
Definition: IException.h:40
Angle emissionAngle() const
Get the emission angle of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:482
double lineResolution() const
Get the line resolution of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:504
QString serialNumber()
Get the serial number.
Definition: Shape.cpp:386
Manipulate and parse attributes of output cube filenames.
A type of error that could only have occurred due to a mistake on the user&#39;s part (e...
Definition: IException.h:142
QString m_serialNumber
This will always be simply the filename and is created on construction.
Definition: Shape.h:194
A single keyword-value pair.
Definition: PvlKeyword.h:98
virtual void pushContentHandler(XmlStackedHandler *newHandler)
Push a contentHandler and maybe continue parsing...
A type of error that cannot be classified as any of the other error types.
Definition: IException.h:134
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:623
Shape(QString shapeFileName, QObject *parent=0)
Create an Shape from a cube file on disk.
Definition: Shape.cpp:45
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
ShapeDisplayProperties * m_displayProperties
The GUI information for how this Shape ought to be displayed.
Definition: Shape.h:186
bool IsSpecial(const double d)
Returns if the input pixel is special.
Definition: SpecialPixel.h:212
Cube * copy(FileName newFile, const CubeAttributeOutput &newFileAttributes)
Copies the cube to the new fileName.
Definition: Cube.cpp:193
bool isValid() const
Test if this distance has been initialized or not.
Definition: Distance.cpp:204
Cube * m_cube
The cube associated with this Shape.
Definition: Shape.h:178
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
geos::geom::MultiPolygon * footprint()
Get the footprint of this shape (if available).
Definition: Shape.cpp:395
QString projectRoot() const
Get the top-level folder of the project.
Definition: Project.cpp:1666
QDir dir() const
Returns the path of the file&#39;s parent directory as a QDir object.
Definition: FileName.cpp:481
QString id() const
Get a unique, identifying string associated with this shape.
Definition: Shape.cpp:460
QString fileName() const
Get the file name of the cube that this shape represents.
Definition: Shape.cpp:377
Container for cube-like labels.
Definition: Pvl.h:135
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Saves this object to an XML file.
void fromPvl(const PvlObject &pvl)
Read the shape settings from a Pvl.
Definition: Shape.cpp:236
void initCamStats()
TODO.
Definition: Shape.cpp:666
void setId(QString id)
Override the automatically generated ID with the given ID.
Definition: Shape.cpp:403
static SurfacePointSource::Source StringToSurfacePointSource(QString str)
Obtain a SurfacePoint::Source from a string.
Defines an angle and provides unit conversions.
Definition: Angle.h:62
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
Definition: PvlContainer.h:86
void print() const
Prints a string representation of this exception to stderr.
Definition: IException.cpp:461
QString Name() const
Accessor method that returns a string containing the Blob name.
Definition: Blob.cpp:149
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
Definition: FileName.cpp:531
void deleteFromDisk()
Delete the shape data from disk.
Definition: Shape.cpp:592
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Definition: Cube.cpp:1346
Class for storing Table blobs information.
Definition: Table.h:77
This represents a shape in a project-based GUI interface.
Definition: Shape.h:78
virtual QString fileName() const
Returns the opened cube&#39;s filename.
Definition: Cube.cpp:1208
int lineCount() const
Definition: Cube.cpp:1379
Isis exception class.
Definition: IException.h:107
FileName setExtension(const QString &extension) const
Sets all current file extensions to a new extension in the file name.
Definition: FileName.cpp:281
QString m_fileName
The on-disk file name of the cube associated with this Shape.
Definition: Shape.h:190
Adds specific functionality to C++ strings.
Definition: IString.h:181
Namespace for ISIS/Bullet specific routines.
Definition: Apollo.h:31
geos::geom::MultiPolygon * m_footprint
A 0-360 ocentric lon,lat degrees footprint of this Shape.
Definition: Shape.h:206
double aspectRatio() const
Get the aspect ratio of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:450
The distance is being specified in meters.
Definition: Distance.h:56
Angle phaseAngle() const
Get the phase angle of this shape, as calculated and attached by camstats.
Definition: Shape.cpp:537
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
Definition: Angle.cpp:110
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
Definition: Angle.h:80
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
Definition: ImagePolygon.h:221
Contains Pvl Groups and Pvl Objects.
Definition: PvlObject.h:74
Manage a stack of content handlers for reading XML files.
QString Type() const
Accessor method that returns a string containing the Blob type.
Definition: Blob.cpp:140
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:1180
SpiceInt * m_bodyCode
The NaifBodyCode value, if it exists in the labels.
Definition: Shape.h:167
bool isFootprintable() const
Test to see if it&#39;s possible to create a footprint from this shape.
Definition: Shape.cpp:294
IO Handler for Isis Cubes.
Definition: Cube.h:170