10#include <QScopedPointer>
13#include <QXmlStreamWriter>
15#include <geos/geom/MultiPolygon.h>
16#include <geos/io/WKTReader.h>
17#include <geos/io/WKTWriter.h>
20#include "CameraFactory.h"
21#include "ControlPoint.h"
23#include "CubeAttribute.h"
24#include "DisplayProperties.h"
27#include "IException.h"
28#include "ImagePolygon.h"
30#include "PolygonTools.h"
32#include "ProjectionFactory.h"
33#include "SerialNumber.h"
34#include "ShapeDisplayProperties.h"
93 void Shape::initMemberData() {
101 m_aspectRatio =
Null;
103 m_lineResolution =
Null;
104 m_sampleResolution =
Null;
107 m_projectionName =
Null;
108 m_pixelResolution =
Null;
113 void Shape::initShape() {
116 m_id =
new QUuid(QUuid::createUuid());
119 m_radiusSource = ControlPoint::RadiusSource::None;
121 if (
cube()->hasTable(
"ShapeModelStatistics")) {
122 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
123 m_radiusSource = ControlPoint::RadiusSource::DEM;
130 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
131 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
132 m_shapeType = Basemap;
134 catch (IException &) {
138 m_surfacePointSource = ControlPoint::SurfacePointSource::Reference;
140 PvlGroup kernels =
cube()->
group(
"Kernels");
141 if (kernels.hasKeyword(
"ShapeModel")) {
142 QString shapeFile = kernels[
"ShapeModel"];
143 if (shapeFile.contains(
"dem")) {
144 m_radiusSource = ControlPoint::RadiusSource::DEM;
147 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
150 m_shapeType = Unprojected;
152 catch (IException &e) {
153 m_surfacePointSource = ControlPoint::SurfacePointSource::None;
154 m_radiusSource = ControlPoint::RadiusSource::None;
155 m_shapeType = Unknown;
156 QString message =
"Cannot create either Camera or Projections "
158 "Check the validity of the cube labels. The cube must either be projected or "
159 " run through spiceinit.";
166 if (m_shapeType == Unprojected) {
169 else if (m_shapeType == Basemap || m_shapeType == Dem) {
171 if (m_shapeType == Dem) {
176 catch (IException &e) {
177 QString message =
"Cannot initialize the camera, map or dem statistics for this shape file [" +
179 "cube must either be projected or run through spiceinit. \n";
180 message += e.toString();
181 QMessageBox::warning((
QWidget *) parent(),
"Warning", message);
185 initQuickFootprint();
187 catch (IException &e) {
193 ControlPoint::SurfacePointSource::Source Shape::surfacePointSource() {
194 return m_surfacePointSource;
198 ControlPoint::RadiusSource::Source Shape::radiusSource() {
199 return m_radiusSource;
203 Shape::ShapeType Shape::shapeType() {
221 QString pvlFileName = ((
IString)pvl[
"FileName"][0]).ToQt();
224 tr(
"Tried to load Shape [%1] with properties/information from [%2].")
231 if (pvl.hasKeyword(
"ID")) {
232 QByteArray hexValues(pvl[
"ID"][0].toLatin1());
233 QDataStream valuesStream(QByteArray::fromHex(hexValues));
234 valuesStream >> *
m_id;
259 dataBuffer.open(QIODevice::ReadWrite);
261 QDataStream idStream(&dataBuffer);
266 output +=
PvlKeyword(
"ID", QString(dataBuffer.data().toHex()));
287 QString blobType = example.
Type();
288 QString blobName = example.Name();
292 for (
int i = 0; i < labels.objects(); i++) {
295 if (obj.isNamed(blobType) && obj.hasKeyword(
"Name") && obj[
"Name"][0] == blobName)
387 *
m_id = QUuid(QString(
"{%1}").arg(
id));
408 initQuickFootprint();
415 IString msg =
"Could not read the footprint from cube [" +
417 "sure footprintinit has been run";
434 return m_aspectRatio;
444 return m_id->toString().remove(QRegExp(
"[{}]"));
466 return m_emissionAngle;
477 return m_incidenceAngle;
488 return m_lineResolution;
499 return m_localRadius;
510 return m_northAzimuth;
532 return m_sampleResolution;
546 QScopedPointer<Cube> newExternalLabel(
551 if (!origShape.storesDnData()) {
552 if (origShape.externalCubeFileName().path() ==
".") {
561 newExternalLabel->relocateDnData(newDnFileName.name());
564 newExternalLabel->relocateDnData(origShape.externalCubeFileName());
581 tr(
"Could not remove file [%1]").arg(
m_fileName),
587 if (!QFile::remove(cubFile.expanded())) {
589 tr(
"Could not remove file [%1]").arg(
m_fileName),
611 original.
dir().dirName() +
"/" + original.
name());
623 QMutexLocker lock(cameraMutex);
629 if (sampleStepSize <= 0) sampleStepSize = 1;
632 if (lineStepSize <= 0) lineStepSize = 1;
634 imgPoly.Create(*
cube(), sampleStepSize, lineStepSize);
637 tr(
"Warning: Polygon re-calculated for [%1] which can be very slow")
650 bool hasCamStats =
false;
653 for (
int i = 0; !hasCamStats && i < label.
objects(); i++) {
657 if (obj.name() ==
"Table") {
658 if (obj[
"Name"][0] ==
"CameraStatistics") {
671 int numRecords = camStatsTable.Records();
672 for (
int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
677 QString recordName((QString)record[
"Name"]);
678 double avgValue = (double)record[
"Average"];
680 if (recordName ==
"AspectRatio") {
681 m_aspectRatio = avgValue;
683 else if (recordName ==
"Resolution") {
684 m_resolution = avgValue;
686 else if (recordName ==
"EmissionAngle") {
689 else if (recordName ==
"IncidenceAngle") {
692 else if (recordName ==
"LineResolution") {
693 m_lineResolution = avgValue;
695 else if (recordName ==
"LocalRadius") {
698 else if (recordName ==
"NorthAzimuth") {
701 else if (recordName ==
"PhaseAngle") {
704 else if (recordName ==
"SampleResolution") {
705 m_sampleResolution = avgValue;
710 for (
int i = 0; i < label.
objects(); i++) {
713 if (obj.hasGroup(
"Instrument")) {
714 PvlGroup instGroup = obj.findGroup(
"Instrument");
716 if (instGroup.hasKeyword(
"SpacecraftName"))
719 if (instGroup.hasKeyword(
"InstrumentId"))
730 void Shape::initMapStats() {
733 for (
int i = 0; i < label.
objects(); i++) {
736 if (obj.hasGroup(
"Instrument")) {
737 PvlGroup instGroup = obj.findGroup(
"Instrument");
739 if (instGroup.hasKeyword(
"SpacecraftName"))
742 if (instGroup.hasKeyword(
"InstrumentId"))
746 if (obj.hasGroup(
"Mapping")) {
747 PvlGroup mapGroup = obj.findGroup(
"Mapping");
749 if (mapGroup.hasKeyword(
"TargetName"))
750 m_targetName = obj.findGroup(
"Mapping")[
"TargetName"][0];
752 if (mapGroup.hasKeyword(
"ProjectionName"))
753 m_projectionName = obj.findGroup(
"Mapping")[
"ProjectionName"][0];
755 if (mapGroup.hasKeyword(
"CenterLongitude"))
756 m_centerLongitude = Longitude(
toDouble(obj.findGroup(
"Mapping")[
"CenterLongitude"][0]),
759 if (mapGroup.hasKeyword(
"CenterLatitude"))
760 m_centerLatitude = Latitude(
toDouble(obj.findGroup(
"Mapping")[
"CenterLatitude"][0]),
763 if (mapGroup.hasKeyword(
"MinimumLatitude"))
764 m_minimumLatitude = Latitude(
toDouble(obj.findGroup(
"Mapping")[
"MinimumLatitude"][0]),
767 if (mapGroup.hasKeyword(
"MaximumLatitude"))
768 m_maximumLatitude = Latitude(
toDouble(obj.findGroup(
"Mapping")[
"MaximumLatitude"][0]),
771 if (mapGroup.hasKeyword(
"MinimumLongitude"))
772 m_minimumLongitude = Longitude(
toDouble(obj.findGroup(
"Mapping")[
"MinimumLongitude"][0]),
775 if (mapGroup.hasKeyword(
"MaximumLongitude"))
776 m_maximumLongitude = Longitude(
toDouble(obj.findGroup(
"Mapping")[
"MaximumLongitude"][0]),
779 if (mapGroup.hasKeyword(
"PixelResolution"))
780 m_pixelResolution = obj.findGroup(
"Mapping")[
"PixelResolution"];
782 if (mapGroup.hasKeyword(
"Scale"))
783 m_scale = obj.findGroup(
"Mapping")[
"Scale"];
786 catch (IException &e) {
793 void Shape::initDemStats() {
799 void Shape::initQuickFootprint() {
818 stream.writeStartElement(
"shape");
820 stream.writeAttribute(
"id",
m_id->toString());
825 if (m_shapeType == Unprojected) {
826 type =
"Unprojected";
828 else if (m_shapeType == Basemap) {
834 stream.writeAttribute(
"shapeType", type);
835 stream.writeAttribute(
"surfacePointSource",
837 stream.writeAttribute(
"radiusSource",
840 if (m_shapeType == Unprojected) {
845 stream.writeAttribute(
"aspectRatio",
IString(m_aspectRatio).ToQt());
849 stream.writeAttribute(
"resolution",
IString(m_resolution).ToQt());
852 if (m_emissionAngle.
isValid()) {
856 if (m_incidenceAngle.
isValid()) {
861 stream.writeAttribute(
"lineResolution",
IString(m_lineResolution).ToQt());
868 if (m_northAzimuth.
isValid()) {
877 stream.writeAttribute(
"sampleResolution",
IString(m_sampleResolution).ToQt());
880 else if (m_shapeType == Basemap) {
883 else if (m_shapeType == Dem) {
888 stream.writeStartElement(
"footprint");
890 geos::io::WKTWriter wktWriter;
891 stream.writeCharacters(QString::fromStdString(wktWriter.write(
m_footprint)));
893 stream.writeEndElement();
898 stream.writeEndElement();
Defines an angle and provides unit conversions.
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid,...
double radians() const
Convert an angle to a double.
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
QString Type() const
Accessor method that returns a string containing the Blob type.
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 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.
ImagePolygon readFootprint() const
Read the footprint polygon for the Cube.
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
PvlGroup & group(const QString &group) const
Read a group from the cube into a Label.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
QString displayName() const
Returns the display name.
PvlObject toPvl() const
Convert to Pvl for project files.
Distance measurement, usually in meters.
bool isValid() const
Test if this distance has been initialized or not.
@ Meters
The distance is being specified in meters.
double meters() const
Get the distance in meters.
File name manipulation and expansion.
QString path() const
Returns the path of the file name.
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
FileName setExtension(const QString &extension) const
Sets all current file extensions to a new extension in the file name.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
@ Unknown
A type of error that cannot be classified as any of the other error types.
@ User
A type of error that could only have occurred due to a mistake on the user's part (e....
@ Programmer
This error is for when a programmer made an API call that was illegal.
@ Io
A type of error that occurred when performing an actual I/O operation.
Adds specific functionality to C++ strings.
QString ToQt() const
Retuns the object string as a QString.
Create cube polygons, read/write polygons to blobs.
Blob toBlob() const
Serialize the ImagePolygon to a Blob.
The main project for ipce.
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
QString projectRoot() const
Get the top-level folder of the project.
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
Contains multiple PvlContainers.
Container for cube-like labels.
A single keyword-value pair.
Contains Pvl Groups and Pvl Objects.
int objects() const
Returns the number of objects.
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.
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.
~Shape()
Clean up this shape.
geos::geom::MultiPolygon * createFootprint(QMutex *cameraMutex)
Calculate a footprint for an Shape using the camera or projection information.
Shape(QString shapeFileName, QObject *parent=0)
Create an Shape from a cube file on disk.
void closeCube()
Cleans up the Cube *.
PvlObject toPvl() const
Convert this Shape to PVL.
bool isFootprintable() const
Test to see if it's possible to create a footprint from this shape.
SpiceInt * m_bodyCode
The NaifBodyCode value, if it exists in the labels.
Distance localRadius() const
Get the local radius of this shape, as calculated and attached by camstats.
Angle phaseAngle() const
Get the phase angle of this shape, as calculated and attached by camstats.
void updateFileName(Project *)
Change the on-disk file name for this cube to be where the shape ought to be in the given project.
double resolution() const
Get the resolution of this shape, as calculated and attached by camstats.
QString serialNumber()
Get the serial number.
QString m_spacecraftName
Spacecraft name associated with this Shape.
double sampleResolution() const
Get the sample resolution of this shape, as calculated and attached by camstats.
ShapeDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this shape.
double lineResolution() const
Get the line resolution of this shape, as calculated and attached by camstats.
void deleteFromDisk()
Delete the shape data from disk.
Angle emissionAngle() const
Get the emission angle of this shape, as calculated and attached by camstats.
QString id() const
Get a unique, identifying string associated with this shape.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
double aspectRatio() const
Get the aspect ratio of this shape, as calculated and attached by camstats.
QString fileName() const
Get the file name of the cube that this shape represents.
Cube * m_cube
The cube associated with this Shape.
geos::geom::MultiPolygon * m_footprint
A 0-360 ocentric lon,lat degrees footprint of this Shape.
Cube * cube()
Get the Cube * associated with this display property.
Angle incidenceAngle() const
Get the incidence angle of this shape, as calculated and attached by camstats.
void copyToNewProjectRoot(const Project *project, FileName newProjectRoot)
Copy the cub/ecub files associated with this shape into the new project.
QUuid * m_id
A unique ID for this Shape (useful for others to reference this Shape when saving to disk).
QString m_serialNumber
This will always be simply the filename and is created on construction.
QString m_instrumentId
Instrument id associated with this Shape.
bool initFootprint(QMutex *cameraMutex)
Calculate a footprint for this shape.
void fromPvl(const PvlObject &pvl)
Read the shape settings from a Pvl.
void setId(QString id)
Override the automatically generated ID with the given ID.
Angle northAzimuth() const
Get the north azimuth of this shape, as calculated and attached by camstats.
geos::geom::MultiPolygon * footprint()
Get the footprint of this shape (if available).
QString m_fileName
The on-disk file name of the cube associated with this Shape.
ShapeDisplayProperties * m_displayProperties
The GUI information for how this Shape ought to be displayed.
Class for storing Table blobs information.
This is free and unencumbered software released into the public domain.
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.