8 #include <QMutexLocker>
9 #include <QScopedPointer>
12 #include <QXmlStreamWriter>
14 #include <geos/geom/MultiPolygon.h>
15 #include <geos/io/WKTReader.h>
16 #include <geos/io/WKTWriter.h>
22 #include "DisplayProperties.h"
34 #include "XmlStackedHandlerReader.h"
80 xmlReader->pushContentHandler(
new XmlHandler(
this, shapeFolder));
107 void Shape::initMemberData() {
115 m_aspectRatio =
Null;
117 m_lineResolution =
Null;
118 m_sampleResolution =
Null;
121 m_projectionName =
Null;
122 m_pixelResolution =
Null;
127 void Shape::initShape() {
129 if (
cube()->hasTable(
"ShapeModelStatistics")) {
136 m_shapeType = Basemap;
138 catch (IException &) {
141 m_shapeType = Unprojected;
143 catch (IException &) {
144 QString message =
"Cannot create either Camera or Projections ";
145 message +=
"for the ground source file. Check the validity of the ";
146 message +=
" cube labels. The cube must either be projected or ";
147 message +=
" run through spiceinit.";
149 m_shapeType = Unknown;
154 if (m_shapeType == Unprojected) {
157 else if (m_shapeType == Basemap || m_shapeType == Dem) {
159 if (m_shapeType == Dem) {
165 initQuickFootprint();
167 catch (IException &) {
172 m_id =
new QUuid(QUuid::createUuid());
176 Shape::ShapeType Shape::shapeType() {
194 QString pvlFileName = ((
IString)pvl[
"FileName"][0]).ToQt();
197 tr(
"Tried to load Shape [%1] with properties/information from [%2].")
205 QByteArray hexValues(pvl[
"ID"][0].toLatin1());
206 QDataStream valuesStream(QByteArray::fromHex(hexValues));
207 valuesStream >> *
m_id;
232 dataBuffer.open(QIODevice::ReadWrite);
234 QDataStream idStream(&dataBuffer);
239 output +=
PvlKeyword(
"ID", QString(dataBuffer.data().toHex()));
261 QString blobType = example.
Type();
262 QString blobName = example.
Name();
266 for (
int i = 0; i < labels.
objects(); i++) {
269 if (obj.
isNamed(blobType) && obj.
hasKeyword(
"Name") && obj[
"Name"][0] == blobName)
361 *
m_id = QUuid(QString(
"{%1}").arg(
id));
382 initQuickFootprint();
389 IString msg =
"Could not read the footprint from cube [" +
391 "sure footprintinit has been run";
408 return m_aspectRatio;
418 return m_id->toString().remove(QRegExp(
"[{}]"));
440 return m_emissionAngle;
451 return m_incidenceAngle;
462 return m_lineResolution;
473 return m_localRadius;
484 return m_northAzimuth;
506 return m_sampleResolution;
520 QScopedPointer<Cube> newExternalLabel(
525 if (!origShape.storesDnData()) {
530 FileName newDnFileName = newExternalLabelFileName.setExtension(
"cub");
535 newExternalLabel->relocateDnData(newDnFileName.name());
555 tr(
"Could not remove file [%1]").arg(
m_fileName),
561 if (!QFile::remove(cubFile.expanded())) {
563 tr(
"Could not remove file [%1]").arg(
m_fileName),
585 original.dir().dirName() +
"/" + original.name());
597 QMutexLocker lock(cameraMutex);
603 if (sampleStepSize <= 0) sampleStepSize = 1;
606 if (lineStepSize <= 0) lineStepSize = 1;
608 imgPoly.
Create(*
cube(), sampleStepSize, lineStepSize);
611 tr(
"Warning: Polygon re-calculated for [%1] which can be very slow")
624 bool hasCamStats =
false;
627 for (
int i = 0; !hasCamStats && i < label.
objects(); i++) {
631 if (obj.
name() ==
"Table") {
632 if (obj[
"Name"][0] ==
"CameraStatistics") {
644 int numRecords = camStatsTable.
Records();
645 for (
int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
650 QString recordName((QString)record[
"Name"]);
651 double avgValue = (double)record[
"Average"];
653 if (recordName ==
"AspectRatio") {
654 m_aspectRatio = avgValue;
656 else if (recordName ==
"Resolution") {
657 m_resolution = avgValue;
659 else if (recordName ==
"EmissionAngle") {
662 else if (recordName ==
"IncidenceAngle") {
665 else if (recordName ==
"LineResolution") {
666 m_lineResolution = avgValue;
668 else if (recordName ==
"LocalRadius") {
671 else if (recordName ==
"NorthAzimuth") {
674 else if (recordName ==
"PhaseAngle") {
677 else if (recordName ==
"SampleResolution") {
678 m_sampleResolution = avgValue;
683 for (
int i = 0; i < label.
objects(); i++) {
702 void Shape::initMapStats() {
705 for (
int i = 0; i < label.
objects(); i++) {
719 PvlGroup mapGroup = obj.
findGroup(
"Mapping");
721 if (mapGroup.hasKeyword(
"TargetName"))
722 m_targetName = obj.
findGroup(
"Mapping")[
"TargetName"][0];
724 if (mapGroup.hasKeyword(
"ProjectionName"))
725 m_projectionName = obj.
findGroup(
"Mapping")[
"ProjectionName"][0];
727 if (mapGroup.hasKeyword(
"CenterLongitude"))
728 m_centerLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"CenterLongitude"][0]),
731 if (mapGroup.hasKeyword(
"CenterLatitude"))
732 m_centerLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"CenterLatitude"][0]),
735 if (mapGroup.hasKeyword(
"MinimumLatitude"))
736 m_minimumLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"MinimumLatitude"][0]),
739 if (mapGroup.hasKeyword(
"MaximumLatitude"))
740 m_maximumLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"MaximumLatitude"][0]),
743 if (mapGroup.hasKeyword(
"MinimumLongitude"))
744 m_minimumLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"MinimumLongitude"][0]),
747 if (mapGroup.hasKeyword(
"MaximumLongitude"))
748 m_maximumLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"MaximumLongitude"][0]),
751 if (mapGroup.hasKeyword(
"PixelResolution"))
752 m_pixelResolution = obj.
findGroup(
"Mapping")[
"PixelResolution"];
754 if (mapGroup.hasKeyword(
"Scale"))
755 m_scale = obj.
findGroup(
"Mapping")[
"Scale"];
758 catch (IException &) {
764 void Shape::initDemStats() {
770 void Shape::initQuickFootprint() {
786 m_shapeFolder = shapeFolder;
803 stream.writeStartElement(
"shape");
805 stream.writeAttribute(
"id",
m_id->toString());
809 if (m_shapeType == Unprojected) {
810 type =
"Unprojected";
812 else if (m_shapeType == Basemap) {
818 stream.writeAttribute(
"shapeType", type);
820 if (m_shapeType == Unprojected) {
825 stream.writeAttribute(
"aspectRatio",
IString(m_aspectRatio).ToQt());
829 stream.writeAttribute(
"resolution",
IString(m_resolution).ToQt());
832 if (m_emissionAngle.
isValid()) {
833 stream.writeAttribute(
"emissionAngle",
IString(m_emissionAngle.
radians()).ToQt());
836 if (m_incidenceAngle.
isValid()) {
837 stream.writeAttribute(
"incidenceAngle",
IString(m_incidenceAngle.
radians()).ToQt());
841 stream.writeAttribute(
"lineResolution",
IString(m_lineResolution).ToQt());
845 stream.writeAttribute(
"localRadius",
IString(m_localRadius.
meters()).ToQt());
848 if (m_northAzimuth.
isValid()) {
849 stream.writeAttribute(
"northAzimuth",
IString(m_northAzimuth.
radians()).ToQt());
853 stream.writeAttribute(
"phaseAngle",
IString(m_phaseAngle.
radians()).ToQt());
857 stream.writeAttribute(
"sampleResolution",
IString(m_sampleResolution).ToQt());
860 else if (m_shapeType == Basemap) {
863 else if (m_shapeType == Dem) {
868 stream.writeStartElement(
"footprint");
870 geos::io::WKTWriter wktWriter;
871 stream.writeCharacters(QString::fromStdString(wktWriter.write(
m_footprint)));
873 stream.writeEndElement();
878 stream.writeEndElement();
888 const QString &qName,
const QXmlAttributes &atts) {
891 if (XmlStackedHandler::startElement(namespaceURI, localName, qName, atts)) {
892 if (localName ==
"shape") {
893 QString
id = atts.value(
"id");
894 QString
fileName = atts.value(
"fileName");
897 delete m_shape->m_id;
898 m_shape->m_id = NULL;
899 m_shape->m_id =
new QUuid(
id.toLatin1());
902 if (!fileName.isEmpty()) {
903 m_shape->m_fileName = m_shapeFolder.expanded() +
"/" +
fileName;
906 QString shapeType = atts.value(
"shapeType");
908 if (shapeType ==
"Unprojected") {
909 m_shape->m_shapeType = Unprojected;
910 QString instrumentId = atts.value(
"instrumentId");
911 QString spacecraftName = atts.value(
"spacecraftName");
913 QString aspectRatioStr = atts.value(
"aspectRatio");
914 QString resolutionStr = atts.value(
"resolution");
915 QString emissionAngleStr = atts.value(
"emissionAngle");
916 QString incidenceAngleStr = atts.value(
"incidenceAngle");
917 QString lineResolutionStr = atts.value(
"lineResolution");
918 QString localRadiusStr = atts.value(
"localRadius");
919 QString northAzimuthStr = atts.value(
"northAzimuth");
920 QString phaseAngleStr = atts.value(
"phaseAngle");
921 QString sampleResolutionStr = atts.value(
"sampleResolution");
923 if (!instrumentId.isEmpty()) {
924 m_shape->m_instrumentId = m_shapeFolder.expanded() +
"/" + instrumentId;
927 if (!instrumentId.isEmpty()) {
928 m_shape->m_instrumentId = m_shapeFolder.expanded() +
"/" + instrumentId;
931 if (!spacecraftName.isEmpty()) {
932 m_shape->m_spacecraftName = m_shapeFolder.expanded() +
"/" + spacecraftName;
935 if (!aspectRatioStr.isEmpty()) {
936 m_shape->m_aspectRatio = aspectRatioStr.toDouble();
939 if (!resolutionStr.isEmpty()) {
940 m_shape->m_resolution = resolutionStr.toDouble();
943 if (!emissionAngleStr.isEmpty()) {
947 if (!incidenceAngleStr.isEmpty()) {
951 if (!lineResolutionStr.isEmpty()) {
952 m_shape->m_lineResolution = lineResolutionStr.toDouble();
955 if (!localRadiusStr.isEmpty()) {
959 if (!northAzimuthStr.isEmpty()) {
963 if (!phaseAngleStr.isEmpty()) {
967 if (!sampleResolutionStr.isEmpty()) {
968 m_shape->m_sampleResolution = sampleResolutionStr.toDouble();
971 else if (shapeType ==
"Basemap") {
972 m_shape->m_shapeType = Basemap;
974 else if (shapeType ==
"Dem") {
975 m_shape->m_shapeType = Dem;
978 m_shape->m_shapeType = Unknown;
983 else if (localName ==
"displayProperties") {
993 bool Shape::XmlHandler::characters(
const QString &ch) {
996 return XmlStackedHandler::characters(ch);
1001 bool Shape::XmlHandler::endElement(
const QString &namespaceURI,
const QString &localName,
1002 const QString &qName) {
1003 if (localName ==
"footprint" && !m_characters.isEmpty()) {
1004 geos::io::WKTReader wktReader(&globalFactory);
1006 wktReader.read(m_characters.toStdString()));
1008 else if (localName ==
"shape" && !m_shape->m_footprint) {
1010 m_shape->initFootprint(&mutex);
1011 m_shape->closeCube();
1015 return XmlStackedHandler::endElement(namespaceURI, localName, qName);
PvlObject & object(const int index)
Return the object at the specified index.
PvlObject toPvl() const
Convert to Pvl for project files.
int Records() const
Returns the number of records.
Distance localRadius() const
Get the local radius of this shape, as calculated and attached by camstats.
const double Null
Value for an Isis Null pixel.
static Isis::Projection * CreateFromCube(Isis::Cube &cube)
This method is a helper method.
The main project for cnetsuite.
PvlGroupIterator findGroup(const QString &name, PvlGroupIterator beg, PvlGroupIterator end)
Find a group with the specified name, within these indexes.
void closeCube()
Cleans up the Cube *.
Angle emissionAngle() const
Get the emission angle of this shape, as calculated and attached by camstats.
File name manipulation and expansion.
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
double radians() const
Convert an angle to a double.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
QString m_spacecraftName
Spacecraft name associated with this Shape.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
void copyToNewProjectRoot(const Project *project, FileName newProjectRoot)
Copy the cub/ecub files associated with this shape into the new project.
ShapeDisplayProperties * displayProperties()
Get the display (GUI) properties (information) associated with this shape.
geos::geom::MultiPolygon * createFootprint(QMutex *cameraMutex)
Calculate a footprint for an Shape using the camera or projection information.
This is the GUI communication mechanism for shape objects.
~Shape()
Clean up this shape.
void read(Blob &blob) const
This method will read data from the specified Blob object.
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.
This error is for when a programmer made an API call that was illegal.
A type of error that occurred when performing an actual I/O operation.
Distance measurement, usually in meters.
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.
Create cube polygons, read/write polygons to blobs.
static QString Compose(Pvl &label, bool def2filename=false)
Compose a SerialNumber from a PVL.
Angle northAzimuth() const
Get the north azimuth of this shape, as calculated and attached by camstats.
QString m_instrumentId
Instrument id associated with this Shape.
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 ...
bool initFootprint(QMutex *cameraMutex)
Calculate a footprint for this shape.
virtual bool startElement(const QString &namespaceURI, const QString &localName, const QString &qName, const QXmlAttributes &atts)
Handle an XML start element.
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
double meters() const
Get the distance in meters.
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
double sampleResolution() const
Get the sample resolution of this shape, as calculated and attached by camstats.
QString displayName() const
Returns the display name.
PvlObject toPvl() const
Convert this Shape to PVL.
QUuid * m_id
A unique ID for this Shape (useful for others to reference this Shape when saving to disk)...
Cube * cube()
Get the Cube * associated with this display property.
Contains multiple PvlContainers.
#define _FILEINFO_
Macro for the filename and line number.
void print() const
Prints a string representation of this exception to stderr.
bool isValid() const
Test if this distance has been initialized or not.
int objects() const
Returns the number of objects.
QString serialNumber()
Get the serial number.
Manipulate and parse attributes of output cube filenames.
A type of error that could only have occurred due to a mistake on the user's part (e...
A single keyword-value pair.
A type of error that cannot be classified as any of the other error types.
void updateFileName(Project *)
Change the on-disk file name for this cube to be where the shape ought to be in the given project...
QString Type() const
Accessor method that returns a string containing the Blob type.
Shape(QString shapeFileName, QObject *parent=0)
Create an Shape from a cube file on disk.
ShapeDisplayProperties * m_displayProperties
The GUI information for how this Shape ought to be displayed.
bool IsSpecial(const double d)
Returns if the input pixel is special.
QString id() const
Get a unique, identifying string associated with this shape.
Cube * m_cube
The cube associated with this Shape.
static Camera * Create(Cube &cube)
Creates a Camera object using Pvl Specifications.
geos::geom::MultiPolygon * footprint()
Get the footprint of this shape (if available).
Container for cube-like labels.
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
void fromPvl(const PvlObject &pvl)
Read the shape settings from a Pvl.
double resolution() const
Get the resolution of this shape, as calculated and attached by camstats.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Saves this object to an XML file.
void setId(QString id)
Override the automatically generated ID with the given ID.
Defines an angle and provides unit conversions.
bool isFootprintable() const
Test to see if it's possible to create a footprint from this shape.
double aspectRatio() const
Get the aspect ratio of this shape, as calculated and attached by camstats.
void deleteFromDisk()
Delete the shape data from disk.
Class for storing Table blobs information.
This represents a shape in a project-based GUI interface.
Angle phaseAngle() const
Get the phase angle of this shape, as calculated and attached by camstats.
QString Name() const
Accessor method that returns a string containing the Blob name.
QString m_fileName
The on-disk file name of the cube associated with this Shape.
Adds specific functionality to C++ strings.
geos::geom::MultiPolygon * m_footprint
A 0-360 ocentric lon,lat degrees footprint of this Shape.
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
QString fileName() const
Returns the opened cube's filename.
The distance is being specified in meters.
bool hasGroup(const QString &name) const
Returns a boolean value based on whether the object has the specified group or not.
Radians are generally used in mathematical equations, 0-2*PI is one circle, however these are more di...
geos::geom::MultiPolygon * Polys()
Return a geos Multipolygon.
Contains Pvl Groups and Pvl Objects.
QString path() const
Returns the path.
Angle incidenceAngle() const
Get the incidence angle of this shape, as calculated and attached by camstats.
his enables stack-based XML parsing of XML files.
QString projectRoot() const
Get the top-level folder of the project.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
QString fileName() const
Get the file name of the cube that this shape represents.
double lineResolution() const
Get the line resolution of this shape, as calculated and attached by camstats.
QString name() const
Returns the container name.
SpiceInt * m_bodyCode
The NaifBodyCode value, if it exists in the labels.
IO Handler for Isis Cubes.