9 #include <QMutexLocker> 10 #include <QScopedPointer> 13 #include <QXmlStreamWriter> 15 #include <geos/geom/MultiPolygon.h> 16 #include <geos/io/WKTReader.h> 17 #include <geos/io/WKTWriter.h> 24 #include "DisplayProperties.h" 36 #include "XmlStackedHandlerReader.h" 109 void Shape::initMemberData() {
117 m_aspectRatio =
Null;
119 m_lineResolution =
Null;
120 m_sampleResolution =
Null;
123 m_projectionName =
Null;
124 m_pixelResolution =
Null;
129 void Shape::initShape() {
132 m_id =
new QUuid(QUuid::createUuid());
135 m_radiusSource = ControlPoint::RadiusSource::None;
137 if (
cube()->hasTable(
"ShapeModelStatistics")) {
138 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
139 m_radiusSource = ControlPoint::RadiusSource::DEM;
146 m_surfacePointSource = ControlPoint::SurfacePointSource::Basemap;
147 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
148 m_shapeType = Basemap;
150 catch (IException &) {
154 m_surfacePointSource = ControlPoint::SurfacePointSource::Reference;
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;
163 m_radiusSource = ControlPoint::RadiusSource::Ellipsoid;
166 m_shapeType = Unprojected;
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 " 174 "Check the validity of the cube labels. The cube must either be projected or " 175 " run through spiceinit.";
182 if (m_shapeType == Unprojected) {
185 else if (m_shapeType == Basemap || m_shapeType == Dem) {
187 if (m_shapeType == Dem) {
192 catch (IException &e) {
193 QString message =
"Cannot initialize the camera, map or dem statistics for this shape file [" +
195 "cube must either be projected or run through spiceinit. \n";
196 message += e.toString();
197 QMessageBox::warning((
QWidget *) parent(),
"Warning", message);
201 initQuickFootprint();
203 catch (IException &e) {
209 ControlPoint::SurfacePointSource::Source Shape::surfacePointSource() {
210 return m_surfacePointSource;
214 ControlPoint::RadiusSource::Source Shape::radiusSource() {
215 return m_radiusSource;
219 Shape::ShapeType Shape::shapeType() {
237 QString pvlFileName = ((
IString)pvl[
"FileName"][0]).ToQt();
240 tr(
"Tried to load Shape [%1] with properties/information from [%2].")
248 QByteArray hexValues(pvl[
"ID"][0].toLatin1());
249 QDataStream valuesStream(QByteArray::fromHex(hexValues));
250 valuesStream >> *
m_id;
275 dataBuffer.open(QIODevice::ReadWrite);
277 QDataStream idStream(&dataBuffer);
282 output +=
PvlKeyword(
"ID", QString(dataBuffer.data().toHex()));
304 QString blobType = example.
Type();
305 QString blobName = example.
Name();
309 for (
int i = 0; i < labels.
objects(); i++) {
312 if (obj.
isNamed(blobType) && obj.
hasKeyword(
"Name") && obj[
"Name"][0] == blobName)
404 *
m_id = QUuid(QString(
"{%1}").arg(
id));
425 initQuickFootprint();
432 IString msg =
"Could not read the footprint from cube [" +
434 "sure footprintinit has been run";
451 return m_aspectRatio;
461 return m_id->toString().remove(QRegExp(
"[{}]"));
483 return m_emissionAngle;
494 return m_incidenceAngle;
505 return m_lineResolution;
516 return m_localRadius;
527 return m_northAzimuth;
549 return m_sampleResolution;
563 QScopedPointer<Cube> newExternalLabel(
578 newExternalLabel->relocateDnData(newDnFileName.name());
598 tr(
"Could not remove file [%1]").arg(
m_fileName),
604 if (!QFile::remove(cubFile.
expanded())) {
606 tr(
"Could not remove file [%1]").arg(
m_fileName),
628 original.
dir().dirName() +
"/" + original.
name());
640 QMutexLocker lock(cameraMutex);
646 if (sampleStepSize <= 0) sampleStepSize = 1;
649 if (lineStepSize <= 0) lineStepSize = 1;
651 imgPoly.
Create(*
cube(), sampleStepSize, lineStepSize);
654 tr(
"Warning: Polygon re-calculated for [%1] which can be very slow")
667 bool hasCamStats =
false;
670 for (
int i = 0; !hasCamStats && i < label.
objects(); i++) {
674 if (obj.
name() ==
"Table") {
675 if (obj[
"Name"][0] ==
"CameraStatistics") {
688 int numRecords = camStatsTable.
Records();
689 for (
int recordIndex = 0; recordIndex < numRecords; recordIndex++) {
694 QString recordName((QString)record[
"Name"]);
695 double avgValue = (double)record[
"Average"];
697 if (recordName ==
"AspectRatio") {
698 m_aspectRatio = avgValue;
700 else if (recordName ==
"Resolution") {
701 m_resolution = avgValue;
703 else if (recordName ==
"EmissionAngle") {
706 else if (recordName ==
"IncidenceAngle") {
709 else if (recordName ==
"LineResolution") {
710 m_lineResolution = avgValue;
712 else if (recordName ==
"LocalRadius") {
715 else if (recordName ==
"NorthAzimuth") {
718 else if (recordName ==
"PhaseAngle") {
721 else if (recordName ==
"SampleResolution") {
722 m_sampleResolution = avgValue;
727 for (
int i = 0; i < label.
objects(); i++) {
747 void Shape::initMapStats() {
750 for (
int i = 0; i < label.
objects(); i++) {
764 PvlGroup mapGroup = obj.
findGroup(
"Mapping");
766 if (mapGroup.hasKeyword(
"TargetName"))
767 m_targetName = obj.
findGroup(
"Mapping")[
"TargetName"][0];
769 if (mapGroup.hasKeyword(
"ProjectionName"))
770 m_projectionName = obj.
findGroup(
"Mapping")[
"ProjectionName"][0];
772 if (mapGroup.hasKeyword(
"CenterLongitude"))
773 m_centerLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"CenterLongitude"][0]),
776 if (mapGroup.hasKeyword(
"CenterLatitude"))
777 m_centerLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"CenterLatitude"][0]),
780 if (mapGroup.hasKeyword(
"MinimumLatitude"))
781 m_minimumLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"MinimumLatitude"][0]),
784 if (mapGroup.hasKeyword(
"MaximumLatitude"))
785 m_maximumLatitude = Latitude(
toDouble(obj.
findGroup(
"Mapping")[
"MaximumLatitude"][0]),
788 if (mapGroup.hasKeyword(
"MinimumLongitude"))
789 m_minimumLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"MinimumLongitude"][0]),
792 if (mapGroup.hasKeyword(
"MaximumLongitude"))
793 m_maximumLongitude = Longitude(
toDouble(obj.
findGroup(
"Mapping")[
"MaximumLongitude"][0]),
796 if (mapGroup.hasKeyword(
"PixelResolution"))
797 m_pixelResolution = obj.
findGroup(
"Mapping")[
"PixelResolution"];
799 if (mapGroup.hasKeyword(
"Scale"))
800 m_scale = obj.
findGroup(
"Mapping")[
"Scale"];
803 catch (IException &e) {
810 void Shape::initDemStats() {
816 void Shape::initQuickFootprint() {
832 m_shapeFolder = shapeFolder;
849 stream.writeStartElement(
"shape");
851 stream.writeAttribute(
"id",
m_id->toString());
856 if (m_shapeType == Unprojected) {
857 type =
"Unprojected";
859 else if (m_shapeType == Basemap) {
865 stream.writeAttribute(
"shapeType", type);
866 stream.writeAttribute(
"surfacePointSource",
868 stream.writeAttribute(
"radiusSource",
871 if (m_shapeType == Unprojected) {
876 stream.writeAttribute(
"aspectRatio",
IString(m_aspectRatio).ToQt());
880 stream.writeAttribute(
"resolution",
IString(m_resolution).ToQt());
883 if (m_emissionAngle.
isValid()) {
884 stream.writeAttribute(
"emissionAngle",
IString(m_emissionAngle.
radians()).ToQt());
887 if (m_incidenceAngle.
isValid()) {
888 stream.writeAttribute(
"incidenceAngle",
IString(m_incidenceAngle.
radians()).ToQt());
892 stream.writeAttribute(
"lineResolution",
IString(m_lineResolution).ToQt());
896 stream.writeAttribute(
"localRadius",
IString(m_localRadius.
meters()).ToQt());
899 if (m_northAzimuth.
isValid()) {
900 stream.writeAttribute(
"northAzimuth",
IString(m_northAzimuth.
radians()).ToQt());
904 stream.writeAttribute(
"phaseAngle",
IString(m_phaseAngle.
radians()).ToQt());
908 stream.writeAttribute(
"sampleResolution",
IString(m_sampleResolution).ToQt());
911 else if (m_shapeType == Basemap) {
914 else if (m_shapeType == Dem) {
919 stream.writeStartElement(
"footprint");
921 geos::io::WKTWriter wktWriter;
922 stream.writeCharacters(QString::fromStdString(wktWriter.write(
m_footprint)));
924 stream.writeEndElement();
929 stream.writeEndElement();
939 const QString &qName,
const QXmlAttributes &atts) {
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");
949 delete m_shape->m_id;
950 m_shape->m_id = NULL;
951 m_shape->m_id =
new QUuid(
id.toLatin1());
955 m_shape->m_fileName = m_shapeFolder.expanded() +
"/" +
fileName;
958 if (m_shape->m_serialNumber.isEmpty()) {
962 m_shape->m_surfacePointSource =
964 m_shape->m_radiusSource =
966 QString shapeType = atts.value(
"shapeType");
968 if (shapeType ==
"Unprojected") {
969 m_shape->m_shapeType = Unprojected;
970 QString instrumentId = atts.value(
"instrumentId");
971 QString spacecraftName = atts.value(
"spacecraftName");
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");
983 if (!instrumentId.isEmpty()) {
984 m_shape->m_instrumentId = m_shapeFolder.expanded() +
"/" + instrumentId;
987 if (!instrumentId.isEmpty()) {
988 m_shape->m_instrumentId = m_shapeFolder.expanded() +
"/" + instrumentId;
991 if (!spacecraftName.isEmpty()) {
992 m_shape->m_spacecraftName = m_shapeFolder.expanded() +
"/" + spacecraftName;
995 if (!aspectRatioStr.isEmpty()) {
996 m_shape->m_aspectRatio = aspectRatioStr.toDouble();
999 if (!resolutionStr.isEmpty()) {
1000 m_shape->m_resolution = resolutionStr.toDouble();
1003 if (!emissionAngleStr.isEmpty()) {
1007 if (!incidenceAngleStr.isEmpty()) {
1011 if (!lineResolutionStr.isEmpty()) {
1012 m_shape->m_lineResolution = lineResolutionStr.toDouble();
1015 if (!localRadiusStr.isEmpty()) {
1019 if (!northAzimuthStr.isEmpty()) {
1023 if (!phaseAngleStr.isEmpty()) {
1027 if (!sampleResolutionStr.isEmpty()) {
1028 m_shape->m_sampleResolution = sampleResolutionStr.toDouble();
1031 else if (shapeType ==
"Basemap") {
1032 m_shape->m_shapeType = Basemap;
1034 else if (shapeType ==
"Dem") {
1035 m_shape->m_shapeType = Dem;
1038 m_shape->m_shapeType = Unknown;
1043 else if (localName ==
"displayProperties") {
1053 bool Shape::XmlHandler::characters(
const QString &ch) {
1056 return XmlStackedHandler::characters(ch);
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);
1067 wktReader.read(m_characters.toStdString()));
1069 catch (IException &e) {
1073 else if (localName ==
"shape" && !m_shape->m_footprint) {
1076 m_shape->initFootprint(&mutex);
1077 m_shape->closeCube();
1079 catch (IException &e) {
1085 return XmlStackedHandler::endElement(namespaceURI, localName, qName);
PvlObject & object(const int index)
Return the object at the specified index.
int Records() const
Returns the number of records.
PvlObject toPvl() const
Convert this Shape to PVL.
double resolution() const
Get the resolution of this shape, as calculated and attached by camstats.
QString path() const
Returns the path of the file name.
double meters() const
Get the distance in meters.
bool hasKeyword(const QString &name) const
Check to see if a keyword exists.
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 ipce.
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 *.
bool storesDnData() const
This method returns a boolean value.
File name manipulation and expansion.
int objects() const
Returns the number of objects.
Angle incidenceAngle() const
Get the incidence angle of this shape, as calculated and attached by camstats.
PvlObject toPvl() const
Convert to Pvl for project files.
QString m_spacecraftName
Spacecraft name associated with this Shape.
double radians() const
Convert an angle to a double.
PvlObjectIterator findObject(const QString &name, PvlObjectIterator beg, PvlObjectIterator end)
Find the index of object with a specified name, between two indexes.
static QString shapeDataRoot(QString projectRoot)
Appends the root directory name 'shapes' to the project .
Angle northAzimuth() const
Get the north azimuth 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.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
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.
Distance localRadius() const
Get the local radius of this shape, as calculated and attached by camstats.
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.
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.
double sampleResolution() const
Get the sample resolution of this shape, as calculated and attached by camstats.
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.
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 ...
PvlGroup & group(const QString &group) const
Read a group from the cube into a Label.
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.
static QString RadiusSourceToString(RadiusSource::Source source)
Obtain a string representation of a given RadiusSource.
QString m_instrumentId
Instrument id associated with this Shape.
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.
void save(QXmlStreamWriter &stream, const Project *project, FileName newProjectRoot) const
Output format:
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
QString shapeDataRoot() const
Accessor for the root directory of the shape model data.
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)...
Cube * cube()
Get the Cube * associated with this display property.
Contains multiple PvlContainers.
#define _FILEINFO_
Macro for the filename and line number.
Angle emissionAngle() const
Get the emission angle of this shape, as calculated and attached by camstats.
double lineResolution() const
Get the line resolution of this shape, as calculated and attached by camstats.
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...
QString m_serialNumber
This will always be simply the filename and is created on construction.
A single keyword-value pair.
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.
void updateFileName(Project *)
Change the on-disk file name for this cube to be where the shape ought to be in the given project...
Shape(QString shapeFileName, QObject *parent=0)
Create an Shape from a cube file on disk.
void read(Blob &blob) const
This method will read data from the specified Blob object.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
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.
Cube * copy(FileName newFile, const CubeAttributeOutput &newFileAttributes)
Copies the cube to the new fileName.
bool isValid() const
Test if this distance has been initialized or not.
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).
QString projectRoot() const
Get the top-level folder of the project.
QDir dir() const
Returns the path of the file's parent directory as a QDir object.
QString id() const
Get a unique, identifying string associated with this shape.
QString fileName() const
Get the file name of the cube that this shape represents.
Container for cube-like labels.
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.
void setId(QString id)
Override the automatically generated ID with the given ID.
static SurfacePointSource::Source StringToSurfacePointSource(QString str)
Obtain a SurfacePoint::Source from a string.
Defines an angle and provides unit conversions.
bool isNamed(const QString &match) const
Returns whether the given string is equal to the container name or not.
void print() const
Prints a string representation of this exception to stderr.
QString Name() const
Accessor method that returns a string containing the Blob name.
QString toString() const
Returns a QString of the full file name including the file path, excluding the attributes with any Is...
void deleteFromDisk()
Delete the shape data from disk.
Pvl * label() const
Returns a pointer to the IsisLabel object associated with the cube.
Class for storing Table blobs information.
This represents a shape in a project-based GUI interface.
virtual QString fileName() const
Returns the opened cube's filename.
FileName setExtension(const QString &extension) const
Sets all current file extensions to a new extension in the file name.
QString m_fileName
The on-disk file name of the cube associated with this Shape.
Adds specific functionality to C++ strings.
Namespace for ISIS/Bullet specific routines.
geos::geom::MultiPolygon * m_footprint
A 0-360 ocentric lon,lat degrees footprint of this Shape.
double aspectRatio() const
Get the aspect ratio of this shape, as calculated and attached by camstats.
The distance is being specified in meters.
Angle phaseAngle() const
Get the phase angle of this shape, as calculated and attached by camstats.
bool isValid() const
This indicates whether we have a legitimate angle stored or are in an unset, or invalid, state.
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.
Manage a stack of content handlers for reading XML files.
QString Type() const
Accessor method that returns a string containing the Blob type.
FileName externalCubeFileName() const
If this is an external cube label file, this will give you the cube dn file that this label reference...
SpiceInt * m_bodyCode
The NaifBodyCode value, if it exists in the labels.
bool isFootprintable() const
Test to see if it's possible to create a footprint from this shape.
IO Handler for Isis Cubes.