1#include "MeasureTool.h"
11#include <QStackedWidget>
13#include <QTableWidget>
16#include <geos/geom/Geometry.h>
17#include <geos/geom/Point.h>
24#include "MdiCubeViewport.h"
25#include "Projection.h"
26#include "RingPlaneProjection.h"
27#include "TProjection.h"
28#include "SurfacePoint.h"
53 m_tableWin->addToTable(
false,
"Feature\nName",
"Feature Name");
54 m_tableWin->addToTable(
false,
"Feature\nType",
"Feature Type");
56 "Start\nLatitude:Start\nLongitude:End\nLatitude:End\nLongitude",
57 "Ground Range", -1, Qt::Horizontal,
"Start Latitude/Longitude to End Latitude/Longitude");
58 m_tableWin->addToTable(
false,
"Start\nSample:Start\nLine:End\nSample:End\nLine",
59 "Pixel Range", -1, Qt::Horizontal,
"Start Sample/Line to End Sample/Line");
60 m_tableWin->addToTable(
true,
"Kilometer\nDistance",
"Kilometer Distance");
61 m_tableWin->addToTable(
false,
"Meter\nDistance",
"Meter Distance");
62 m_tableWin->addToTable(
false,
"Pixel\nDistance",
"Pixel Distance");
63 m_tableWin->addToTable(
false,
"Degree\nAngle",
"Degree Angle");
64 m_tableWin->addToTable(
false,
"Radian\nAngle",
"Radian Angle");
65 m_tableWin->addToTable(
false,
"Kilometer\nArea",
"Kilometer Area");
66 m_tableWin->addToTable(
false,
"Meter\nArea",
"Meter Area");
67 m_tableWin->addToTable(
false,
"Pixel\nArea",
"Pixel Area");
68 m_tableWin->addToTable(
false,
"Planar \nDistance",
"Planar Kilometer Distance");
69 m_tableWin->addToTable(
false,
"Segments Sum\nkm",
"Segments Sum", -1, Qt::Horizontal,
"Sum of Segment lengths in kilometers");
70 m_tableWin->addToTable(
false,
"Segment Number",
"Segment Number", -1, Qt::Horizontal,
"Segment number of a segmented line");
72 m_tableWin->addToTable(
false,
"FileName",
"FileName");
73 m_tableWin->addToTable(
false,
"Notes",
"Notes");
75 m_tableWin->setStatusMessage(
"Click, Drag, and Release to Measure a Line");
91 action->setIcon(QPixmap(
toolIconDir() +
"/measure.png"));
92 action->setToolTip(
"Measure (M)");
93 action->setShortcut(Qt::Key_M);
96 "<b>Function:</b> Measure features in active viewport \
97 <p><b>Shortcut:</b> M</p> ";
98 action->setWhatsThis(text);
114 QToolButton *measureButton =
new QToolButton(hbox);
115 measureButton->setText(
"Table");
116 measureButton->setToolTip(
"Record Measurement Data in Table");
118 "<b>Function:</b> This button will bring up a table that will record the \
119 starting and ending points of the line, along with the distance between \
120 the two points on the image. To measure the distance between two points, \
121 click on the first point and releasing the mouse at the second point. \
122 <p><b>Shortcut:</b> CTRL+M</p>";
123 measureButton->setWhatsThis(text);
124 measureButton->setShortcut(Qt::CTRL + Qt::Key_M);
125 connect(measureButton, SIGNAL(clicked()),
m_tableWin, SLOT(showTable()));
126 connect(measureButton, SIGNAL(clicked()),
m_tableWin, SLOT(syncColumns()));
127 connect(measureButton, SIGNAL(clicked()),
m_tableWin, SLOT(raise()));
128 measureButton->setEnabled(
true);
147 QString text2 =
"<b>Function: </b> Shows the length of the line drawn on \
152 m_showAllSegments =
new QCheckBox(hbox);
153 m_showAllSegments->setText(
"Show All Segments");
162 connect(rubberBandTool(), SIGNAL(modeChanged()),
this, SLOT(
updateUnitsCombo()));
164 QHBoxLayout *layout =
new QHBoxLayout(hbox);
165 layout->setMargin(0);
169 layout->addWidget(measureButton);
170 layout->addWidget(m_showAllSegments);
171 layout->addStretch(1);
172 hbox->setLayout(layout);
183 if (miComboUnit >= 0) {
188 m_showAllSegments->setEnabled(
false);
190 if (rubberBandTool()->currentMode() == RubberBandTool::LineMode) {
196 if (miComboUnit < 0 || miComboUnit > 3) {
200 else if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
202 if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
203 m_showAllSegments->setEnabled(
true);
209 if (miComboUnit < 0 || miComboUnit > 2) {
213 else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
216 if (miComboUnit > 1 || miComboUnit < 0) {
224 if (miComboUnit < 0 || miComboUnit > 2) {
255 while (currentRow >=
m_tableWin->table()->rowCount()) {
292 if (rubberBandTool()->currentMode() != RubberBandTool::AngleMode &&
m_unitsComboBox->currentIndex() != 2) {
294 QMessageBox::information((
QWidget *)parent(),
"Error",
295 "File must have a Camera Model or Projection to measure in km or m");
300 if (!
m_tableWin->table()->isVisible())
return;
308 QApplication::sendPostedEvents(
m_tableWin->table(), 0);
328 rubberBandTool()->setDrawActiveViewportOnly(
false);
347 for (
int c = 0; c <
m_tableWin->table()->columnCount(); c++) {
348 m_tableWin->table()->item(row, c)->setText(
"");
445 int requiredRows = m_distanceSegments.size() + row;
446 int rowDiff = (int)(requiredRows -
m_tableWin->table()->rowCount());
449 if (requiredRows >
m_tableWin->table()->rowCount()) {
450 for (
int r = 0; r < rowDiff; r++) {
455 if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
456 m_distanceSegments.size() > 0) {
457 double distanceSum = 0;
458 for (
int i = 0; i < m_distanceSegments.size(); i++) {
460 if (m_startLatSegments[i] !=
Null && m_startLonSegments[i] !=
Null) {
469 if (m_endLatSegments[i] !=
Null && m_endLonSegments[i] !=
Null) {
478 if (m_startSampSegments[i] !=
Null && m_startLineSegments[i] !=
Null) {
487 if (m_endSampSegments[i] !=
Null && m_endLineSegments[i] !=
Null) {
496 if (m_pixDistSegments[i] !=
Null) {
503 if (m_distanceSegments[i] !=
Null) {
518 if (distanceSum !=
Null) {
557 void MeasureTool::addRow() {
561 QTableWidgetItem *item =
new QTableWidgetItem(
"");
565 QAbstractItemView::PositionAtBottom);
595 if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
596 rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
597 m_distanceSegments.clear();
598 m_pixDistSegments.clear();
599 m_startSampSegments.clear();
600 m_endSampSegments.clear();
601 m_startLineSegments.clear();
602 m_endLineSegments.clear();
603 m_startLatSegments.clear();
604 m_endLatSegments.clear();
605 m_startLonSegments.clear();
606 m_endLonSegments.clear();
608 for (
int startIndex = 0; startIndex < rubberBandTool()->vertices().size() - 1; startIndex++) {
609 QPoint start = rubberBandTool()->vertices()[startIndex];
610 QPoint end = rubberBandTool()->vertices()[startIndex + 1];
612 setDistances(cvp, start, end);
614 if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
615 if (m_distanceSegments.size() < 75) {
616 m_distanceSegments.append(
m_kmDist);
630 if (rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode &&
631 m_pixDistSegments.size()) {
636 for (
int i = 1; i < m_pixDistSegments.size(); i++) {
642 thisDistance).kilometers();
644 thisDistance).meters();
648 else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
649 m_radAngle = rubberBandTool()->angle().radians();
650 m_degAngle = rubberBandTool()->angle().degrees();
653 geos::geom::Geometry *polygon = rubberBandTool()->geometry();
654 if (polygon != NULL) {
657 geos::geom::Point *center = polygon->getCentroid().release();
659 cvp->
viewportToCube((
int)center->getX(), (
int)center->getY(), sample, line);
661 if (cvp->
camera() != NULL) {
678 if (rubberBandTool()->currentMode() == RubberBandTool::RectangleMode) {
679 setDistances(cvp, rubberBandTool()->vertices()[0],
680 rubberBandTool()->vertices()[2]);
686 if (m_showAllSegments->isChecked() &&
687 rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
705 double radius =
Null;
737 rproj = (RingPlaneProjection *) cvp->
projection();
768 else if (cvp->
camera() != NULL &&
787 double pixDist = sqrt(lineDif * lineDif + sampDif * sampDif);
796 SurfacePoint startPoint;
797 SurfacePoint endPoint;
799 if (startLat.isValid() && startLon.isValid() &&
800 endLat.isValid() && endLon.isValid() && radiusDist.isValid()) {
801 startPoint = SurfacePoint(startLat, startLon, radiusDist);
802 endPoint = SurfacePoint(endLat, endLon, radiusDist);
805 Distance distance = startPoint.GetDistanceToPoint(endPoint, radiusDist);
810 if (cvp->
camera() != NULL) {
814 double slantDist = 0;
823 if ((!statusStart)&&statusEnd) {
828 if (!(statusStart||statusEnd)) {
835 double dRA = (ra1 - ra2);
837 double angle = acos(sin(dec1)*sin(dec2) + cos(dec1)*cos(dec2)*cos(dRA));
838 double half_angle = angle/2.0;
839 double length = slantDist * sin(half_angle) * 2.0;
848 if (rubberBandTool()->currentMode() == RubberBandTool::LineMode ||
849 rubberBandTool()->currentMode() == RubberBandTool::SegmentedLineMode) {
878 else if (rubberBandTool()->currentMode() == RubberBandTool::AngleMode) {
@ Degrees
Degrees are generally considered more human readable, 0-360 is one circle, however most math does not...
virtual double PixelResolution()
Returns the pixel resolution at the current position in meters/pixel.
virtual bool SetImage(const double sample, const double line)
Sets the sample/line values of the image to get the lat/lon values.
virtual QString fileName() const
Returns the opened cube's filename.
void viewportToCube(int x, int y, double &sample, double &line) const
Turns a viewport into a cube.
Projection * projection() const
Distance measurement, usually in meters.
@ Pixels
The distance is being specified in pixels.
@ Kilometers
The distance is being specified in kilometers.
@ 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.
QString name() const
Returns the name of the file excluding the path and the attributes in the file name.
QString expanded() const
Returns a QString of the full file name including the file path, excluding the attributes.
Cube display widget for certain Isis MDI applications.
bool isLinked() const
Is the viewport linked with other viewports.
ProjectionType
This enum defines the subclasses of Projection supported in Isis.
@ Triaxial
These projections are used to map triaxial and irregular-shaped bodies.
@ RingPlane
These projections are used to map ring planes.
double Resolution() const
This method returns the resolution for mapping world coordinates into projection coordinates.
virtual bool SetWorld(const double x, const double y)
This method is used to set a world coordinate.
bool IsSky() const
Returns true if projection is sky and false if it is land.
ProjectionType projectionType() const
Returns an enum value for the projection type.
Base class for Map Projections of plane shapes.
double UniversalRingLongitude()
This returns a universal ring longitude (clockwise in 0 to 360 domain).
double RingRadius() const
This returns a radius.
double UniversalRingRadius()
This returns a universal radius, which is just the radius in meters.
Combo box for choosing a rubber band type.
@ SegmentedLine
Segmented Line.
@ RotatedRectangle
RotatedRectangle.
virtual double UniversalLatitude() const
Returns the planetocentric latitude, in degrees, at the surface intersection point in the body fixed ...
virtual double RightAscension()
Returns the right ascension angle (sky longitude).
virtual double SlantDistance() const
Return the distance between the spacecraft and surface point in kmv.
virtual double UniversalLongitude() const
Returns the positive east, 0-360 domain longitude, in degrees, at the surface intersection point in t...
Distance LocalRadius() const
Returns the local radius at the intersection point.
virtual double Declination()
Returns the declination angle (sky latitude).
Base class for Map TProjections.
double LocalRadius(double lat) const
This method returns the local radius in meters at the specified latitude position.
virtual double UniversalLongitude()
This returns a universal longitude (positive east in 0 to 360 domain).
virtual double UniversalLatitude()
This returns a universal latitude (planetocentric).
a subclass of the qisis mainwindow, tablemainwindow handles all of the table tasks.
QTableWidget * table() const
Returns the table.
This is free and unencumbered software released into the public domain.
const double DEG2RAD
Multiplier for converting from degrees to radians.
const double Null
Value for an Isis Null pixel.